直接Actor通信快速入门

直接Actor通信方法的快速入门介绍。

Choose your operating system:

Windows

macOS

Linux

选择实现方法:

Blueprints

C++

概述

直接Actor通信(Direct Actor communication)是关卡中各Actor之间的常用信息共享方法。 这种方法要求你引用目标Actor,以便当前Actor访问它。采用这种通信方法时,工作Actor和目标Actor之间是一对一关系。 在此快速入门指南中,你将学习如何使用直接Actor通信来访问目标Actor中的信息。

1 - 必要设置

  1. 在菜单的 新项目类别(New Project Categories) 部分中,选择 游戏(Games) ,然后点击 下一步(Next)

    图像替换文本

  2. 选择 第三人称(Third Person) 模板,然后点击 下一步(Next)

    图像替换文本

  3. 选择 蓝图(Blueprint) 含初学者内容包(With Starter Content) 选项,然后点击 创建项目(Create Project)

    图像替换文本

阶段成果

你已经创建了一个新的第三人称项目,现在可以开始实现直接Actor通信。

2 - 添加直接Actor通信

  1. 转到 内容浏览器(Content Browser) 中的 初学者内容包(Starter Content) > 蓝图(Blueprints) ,然后 Blueprint_CeilingLight actor拖动到关卡中。

    图像替换文本

  2. 在关卡中选择 ThirdPersonCharacter Actor,将其放置在靠近电灯的位置。

    图像替换文本

  3. 选择你的 ThirdPersonCharacter Actor之后,转到 世界大纲视图(World Outliner) ,点击 编辑ThirdPersonCharacter(Edit ThirdPersonCharacter) 以打开蓝图编辑器。

    图像替换文本

  4. 转到 变量(Variable) 部分,然后点击 添加变量(+ Variable) 按钮以创建新的变量。

    图像替换文本

  5. 将变量命名为 LampReference

  6. 转到 细节(Details) 面板,然后点击 变量类型(Variable Type) 下拉菜单。搜索并选择 对象引用(Object Reference) 中的 蓝图天花板光源(Blueprint Ceiling Light) ,如下所示。

    图像替换文本

  7. 最后,启用 实例可编辑(Instance Editable) 复选框,并 编译(Compile) 保存(Save) 蓝图。

    图像替换文本

  8. 事件图表(Event Graph) 中,右键点击并搜索和选择 F 键,以创建输入节点。

    图像替换文本

  9. F Key 节点的 已按下(Pressed) 引脚拖出一根引线,然后搜索并选择 Flip Flop

    图像替换文本

  10. 电灯引用(Lamp Reference) 变量拖动到 事件图表(Event Graph) 中,然后选择 获取LampReference(Get LampReference) 。从引脚拖出一根引线,然后搜索并选择 Get Point Light 1

    图像替换文本

  11. Point Light 1 引脚拖出一根引线,然后搜索并选择 Set Visibility 。将 A引脚(A pin) Flip Flop 节点连接到 Set Visibility 节点,如下所示。

    图像替换文本

  12. 复制 Lamp Reference Point Lamp 1 Set Visibility 节点,将它们连接到 Flip Flop 节点的 B 引脚。启用 New Visibility(新可视性) 复选框,如下所示。

    图像替换文本

  13. 编译(Compile) 保存(Save) 蓝图。

阶段成果

在此小节中,你修改了 ThirdPersonCharacter 蓝图Actor以使用对电灯Actor的引用,并通过按F键打开和关闭电灯。

3 - 与电灯Actor交互

1.在你的关卡中选择 ThirdPersonCharacter Actor,然后在 细节(Details) 面板中点击 电灯引用(Lamp Reference) 下拉菜单。搜索并选择 Blueprint_CeilingLight 蓝图。

![图像替换文本](image_14.png)(convert:false)
  1. 按运行(Play)进入播放模式,然后按 F键(F Key) 打开和关闭电灯。

    图像替换文本

阶段成果

在本小节中,你在 ThirdPersonCharacter 蓝图Actor中添加了天花板电灯的引用,并且通过按F键打开和关闭了光源。

后续步骤

现在,你现在你已了解如何使用直接Actor通信,接下来可以查看 Actor通信 文档页面中引用的其他通信类型。

概述

直接蓝图通信(Direct Blueprint communication)是在关卡中的Actor之间共享信息时的常用方法。 这种方法要求你引用目标Actor蓝图,以便当前Actor的蓝图能够访问它。采用这种通信类型时,当前Actor和目标Actor之间是一对一关系。 在此快速入门指南中,你将学习如何使用直接蓝图通信来访问目标Actor蓝图中的信息。

1 - 准备工作

  1. 在菜单的 新项目类别(New Project Categories) 部分中,选择 游戏(Games) ,然后点击 下一步(Next)

    图像替换文本

  2. 选择 第三人称(Third Person) 模板,然后点击 下一步(Next)

    图像替换文本

  3. 选择 C++ 含初学者内容包(With Starter Content) 选项,然后点击 创建项目(Create Project)

    图像替换文本

阶段成果

你已经创建了一个新的第三人称项目,现在可以开始实现直接蓝图通信了。

2 - 创建天花板光源Actor

  1. [C++类向导]([C++ Class Wizard])(ProductionPipelines/DevelopmentSetup/ManagingGameCode/CppClassWizard) 中新建名为 CeilingLight 的Actor类。

    图像替换文本

  2. 在类中, CeilingLight.h 的类默认值中,实现以下代码。

    protected:
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        USceneComponent* SceneComp;
    
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        class UPointLightComponent* PointLightComp;
    
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        UStaticMeshComponent* StaticMeshComp;
    
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        float Brightness;
    
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        float SourceRadius;
    
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        FLinearColor Color;
    
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        bool IsLightOn;
  3. 然后导航至 CeilingLight.Cpp 并声明以下Include库。

    #include "Components/PointLightComponent.h"
  4. 在构造函数 ACeilingLight::CeilingLight 中声明以下代码。

    ACeilingLight::ACeilingLight()
    {
        // 将此Actor设置为每帧调用Tick()函数。如果你不需要此特性,你可以关闭它以提升性能。
        PrimaryActorTick.bCanEverTick = true;
        SceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComp"));
        PointLightComp = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComp"));
        StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMeshComp"));
        SceneComp = RootComponent;
        PointLightComp->AttachToComponent(SceneComp,FAttachmentTransformRules::KeepRelativeTransform);
        StaticMeshComp->AttachToComponent(SceneComp, FAttachmentTransformRules::KeepRelativeTransform);
        PointLightComp->SetWorldLocation(FVector(0, 0, -130));
        Brightness = 1700.f;
        Color = FLinearColor(1.f, 0.77f, 0.46f);
        SourceRadius = 3.5f;
        PointLightComp->SetIntensity(Brightness);
        PointLightComp->SetLightColor(Color);
        PointLightComp->SetSourceRadius(SourceRadius);
    
    }
  5. 编译你的代码。

最终代码

CeilingLight.h

//在项目设置(Project Settings)的描述(Description)页面中填写版权声明。
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "CeilingLight.generated.h"

UCLASS()
class BPCOMMUNICATION_API ACeilingLight : public AActor
{
    GENERATED_BODY()

public: 
    // 为此Actor的属性设置默认值
    ACeilingLight();
protected:
    // 当游戏开始或重生(Spawn)时被调用
    virtual void BeginPlay() override;

    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    USceneComponent* SceneComp;

    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    class UPointLightComponent* PointLightComp;

    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    UStaticMeshComponent* StaticMeshComp;

    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    float Brightness;

    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    float SourceRadius;

    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    FLinearColor Color;

    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    bool IsLightOn;

public: 
    // 每一帧都调用
    virtual void Tick(float DeltaTime) override;

    UFUNCTION()
    void TurnOffLight();
};

CeilingLight.cpp

//版权所有Epic Games, Inc。保留所有权利。
#include "CeilingLight.h"
#include "Components/PointLightComponent.h"

// 设置默认值
ACeilingLight::ACeilingLight()
{
    // 将此Actor设置为每帧调用Tick()。  如果你不需要此特性,你可以关闭它以提升性能。
    PrimaryActorTick.bCanEverTick = true;
    SceneComp = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComp"));
    PointLightComp = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLightComp"));
    StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMeshComp"));
    SceneComp = RootComponent;
    PointLightComp->AttachToComponent(SceneComp,FAttachmentTransformRules::KeepRelativeTransform);
    StaticMeshComp->AttachToComponent(SceneComp, FAttachmentTransformRules::KeepRelativeTransform);
    PointLightComp->SetWorldLocation(FVector(0, 0, -130));
    Brightness = 1700.f;
    Color = FLinearColor(1.f, 0.77f, 0.46f);
    SourceRadius = 3.5f;
    PointLightComp->SetIntensity(Brightness);
    PointLightComp->SetLightColor(Color);
    PointLightComp->SetSourceRadius(SourceRadius);

}

// 当游戏开始或重生(Spawn)时被调用
void ACeilingLight::BeginPlay()
{
    Super::BeginPlay();

}

void ACeilingLight::TurnOffLight()
{
    if (IsLightOn)
    {
        PointLightComp->SetVisibility(false);
        IsLightOn = false;
    }
    else
    {
        PointLightComp->SetVisibility(true);
        IsLightOn = true;
    }
}

// 每一帧都调用
void ACeilingLight::Tick(float DeltaTime)
{
    Super::Tick(DeltaTime);
}

6.在 C++类文件夹(C++ Classes folder) 中,右键点击 CeilingLight Actor,然后在 C++类操作(C++ Class Actions) 下拉菜单中,选择 基于CeilingLight创建蓝图类(Create Blueprint class based on CeilingLight) 。将蓝图命名为 BP_CeilingLight

![图像替换文本](image_4.png)(convert:false)

7.在 BP_CeilingLight 类默认值中,导航至 组件(Components) 面板,然后选择 StaticMeshComp

![图像替换文本](image_5.png)(convert:false)

8.在 细节(Details) 面板中,导航至 静态网格体类别(Static Mesh category) ,选择 静态网格体(Static Mesh) 变量旁边的下拉箭头,然后搜索并选择 SM_Lamp_Ceiling

![图像替换文本](image_6.png)(convert:false)
  1. 编译并保存蓝图

  2. 内容浏览器(Content Browser) 中,将 BP_CeilingLight Actor 的实例拖动到关卡中。

    图像替换文本

修改ThirdPersonCharacter类

  1. 导航至C++类文件夹,然后双击 BPCommunicationCharacter 类以打开其 BPCommunicationCharacter.h ,然后在类默认值中声明以下代码。

    protected:
        UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
        class ACeilingLight* CeilingLightToToggle;
        void ToggleCeilingLight();
  2. 导航至你的 BPCommunicationCharacter.cpp ,并声明以下include代码:

    #include "CeilingLight.h"
  3. 实现你的 ABPCommunicationCharacter::ToggleCeilingLight 方法。

    void ABPCommunicationCharacter::ToggleCeilingLight()
    {
        if (CeilingLightToToggle)
            {
              CeilingLightToToggle->TurnOffLight();
            }
    }
  4. 导航至 ABPCommunicationCharacter::SetupPlayerInputComponent 方法,并声明以下代码。

    PlayerInputComponent->BindAction("Use", IE_Pressed, this, &ABPCommunicationCharacter::ToggleCeilingLight);
  5. 编辑器(Editor) 中,导航至 编辑(Edit) > 项目设置(Project Settings) > 输入(Input) 。 在 绑定(Bindings) 类别中,导航至 操作映射(Action Mappings) ,然后点击 + 按钮以创建名为 Use 的新 操作映射(Action mapping) ,然后为 键值(key value) 选择 E 键。

    图像替换文本

  6. 编译你的代码。

最终代码

BPCommunicationCharacter.h

//版权所有Epic Games, Inc。保留所有权利。
#pragma once

#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "BPCommunicationCharacter.generated.h"

UCLASS(config=Game)
class ABPCommunicationCharacter : public ACharacter
{
    GENERATED_BODY()

    /** 用于将摄像机放置在角色后面的摄像机升降臂 */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class USpringArmComponent* CameraBoom;

    /** 跟随摄像机 */
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category = Camera, meta = (AllowPrivateAccess = "true"))
    class UCameraComponent* FollowCamera;

public:
    ABPCommunicationCharacter();

    /** 基本旋转速度,以"度/秒"为单位。其他计量方式可能会影响最终旋转速度。*/
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    float BaseTurnRate;

    /** 基本仰视/俯视速度,以"度/秒"为单位。其他计量方式可能会影响最终速度。*/
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    float BaseLookUpRate;

protected:
    UPROPERTY(EditInstanceOnly, BlueprintReadWrite)
    class ACeilingLight* CeilingLightToToggle;
    void ToggleCeilingLight();

    /** 重置VR中的HMD方向。*/
    void OnResetVR();

    /** 出现向前/向后输入时调用 */
    void MoveForward(float Value);

    /** 出现侧边到侧边输入时调用 */
    void MoveRight(float Value);

    /** 
     * 通过输入进行调用,以给定的速度旋转。 
     * @param速度 这是标准化速度,即1.0表示100%的所需旋转速度
     */

    void TurnAtRate(float Rate);
    /**
     * 通过输入进行调用,以给定的速度仰视/俯视旋转。 
     * @param速度 这是标准化速度,即1.0表示100%的所需旋转速度
     */

    void LookUpAtRate(float Rate);

    /** 当触摸输入开始时的处理程序。*/
    void TouchStarted(ETouchIndex::Type FingerIndex, FVector Location);

    /** 当触摸输入停止时的处理程序。*/
    void TouchStopped(ETouchIndex::Type FingerIndex, FVector Location);

protected:

    // APawn接口
    virtual void SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) override;
    // APawn接口结束

public:
    /** 返回CameraBoom子对象 **/
    FORCEINLINE class USpringArmComponent* GetCameraBoom() const { return CameraBoom; }

    /** 返回FollowCamera子对象 **/
    FORCEINLINE class UCameraComponent* GetFollowCamera() const { return FollowCamera; }
};

BPCommunicationCharacter.cpp

//版权所有Epic Games, Inc。保留所有权利。
#include "BPCommunicationCharacter.h"
#include "HeadMountedDisplayFunctionLibrary.h"
#include "Camera/CameraComponent.h"
#include "Components/CapsuleComponent.h"
#include "Components/InputComponent.h"
#include "GameFramework/CharacterMovementComponent.h"
#include "GameFramework/Controller.h"
#include "GameFramework/SpringArmComponent.h"
#include "CeilingLight.h"

ABPCommunicationCharacter::ABPCommunicationCharacter()
{
    // 设置碰撞胶囊体的大小
    GetCapsuleComponent()->InitCapsuleSize(42.f, 96.0f);

    // 设置我们的输入旋转速度
    BaseTurnRate = 45.f;
    BaseLookUpRate = 45.f;

    // 不在控制器旋转时旋转。使其仅影响摄像机。
    bUseControllerRotationPitch = false;
    bUseControllerRotationYaw = false;
    bUseControllerRotationRoll = false;

    // 配置角色移动
    GetCharacterMovement()->bOrientRotationToMovement = true; // 角色沿输入方向移动...   
    GetCharacterMovement()->RotationRate = FRotator(0.0f, 540.0f, 0.0f); // ...以此旋转速度
    GetCharacterMovement()->JumpZVelocity = 600.f;
    GetCharacterMovement()->AirControl = 0.2f;

    // 创建摄像机升降臂(如果发生碰撞,朝着玩家推进)
    CameraBoom = CreateDefaultSubobject<USpringArmComponent>(TEXT("CameraBoom"));
    CameraBoom->SetupAttachment(RootComponent);
    CameraBoom->TargetArmLength = 300.0f; // 摄像机在角色后面的这个距离上跟随   
    CameraBoom->bUsePawnControlRotation = true; // 基于控制器旋转升降臂

    // 创建跟随摄像机
    FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
    FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // 将摄像机附于升降臂末端,调整升降臂,使其与控制器方向一致
    FollowCamera->bUsePawnControlRotation = false; // 摄像机不相对于升降臂旋转

    // 注意:网格体组件上的骨骼网格体和动画蓝图引用(从角色继承) 
    // 是在名为MyCharacter的派生蓝图资产中设置的(以避免C++中的直接内容引用)
}

void ABPCommunicationCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
    // 设置游戏的按键绑定
    check(PlayerInputComponent);
    PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
    PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);
    PlayerInputComponent->BindAction("Use", IE_Pressed, this, &ABPCommunicationCharacter::ToggleCeilingLight);
    PlayerInputComponent->BindAxis("MoveForward", this, &ABPCommunicationCharacter::MoveForward);
    PlayerInputComponent->BindAxis("MoveRight", this, &ABPCommunicationCharacter::MoveRight);

    // 我们提供了两个版本的旋转绑定来分别处理不同类型的设备
    // "turn"处理提供绝对增量的设备,例如鼠标。
    // "turn rate"适用于我们选择以变化速度方式进行处理的设备,例如模拟摇杆
    PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
    PlayerInputComponent->BindAxis("TurnRate", this, &ABPCommunicationCharacter::TurnAtRate);
    PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
    PlayerInputComponent->BindAxis("LookUpRate", this, &ABPCommunicationCharacter::LookUpAtRate);

    // 处理触摸设备
    PlayerInputComponent->BindTouch(IE_Pressed, this, &ABPCommunicationCharacter::TouchStarted);
    PlayerInputComponent->BindTouch(IE_Released, this, &ABPCommunicationCharacter::TouchStopped);

    // VR头戴设备功能
    PlayerInputComponent->BindAction("ResetVR", IE_Pressed, this, &ABPCommunicationCharacter::OnResetVR);
}

void ABPCommunicationCharacter::ToggleCeilingLight()
{
    if (CeilingLightToToggle)
    {
        CeilingLightToToggle->TurnOffLight();
    }
}

void ABPCommunicationCharacter::OnResetVR()
{
    // 如果在虚幻编辑器中通过"添加功能(Add Feature)"将BPCommunication添加到项目,则BPCommunication.Build.cs中HeadMountedDisplay上的依赖关系不会自动传播,
    // 并将产生连接器错误。
    // 你需要:
    //      将"HeadMountedDisplay"添加到[YourProject].Build.cs PublicDependencyModuleNames,以便成功构建(如果支持VR则适用)。
    // 或者:
    //      注释掉或删除下面对ResetOrientationAndPosition的调用(如果不支持VR则适用)
    UHeadMountedDisplayFunctionLibrary::ResetOrientationAndPosition();
}

void ABPCommunicationCharacter::TouchStarted(ETouchIndex::Type FingerIndex, FVector Location)
{
        Jump();
}

void ABPCommunicationCharacter::TouchStopped(ETouchIndex::Type FingerIndex, FVector Location)
{
        StopJumping();
}

void ABPCommunicationCharacter::TurnAtRate(float Rate)
{
    // 根据速度信息计算此帧的增量
    AddControllerYawInput(Rate * BaseTurnRate * GetWorld()->GetDeltaSeconds());
}

void ABPCommunicationCharacter::LookUpAtRate(float Rate)
{
    // 根据速度信息计算此帧的增量
    AddControllerPitchInput(Rate * BaseLookUpRate * GetWorld()->GetDeltaSeconds());
}

void ABPCommunicationCharacter::MoveForward(float Value)
{
    if ((Controller != nullptr) && (Value != 0.0f))
    {
        // 找出向前方向
        const FRotator Rotation = Controller->GetControlRotation();
        const FRotator YawRotation(0, Rotation.Yaw, 0);

        // 获取向前向量
        const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::X);
        AddMovementInput(Direction, Value);
    }
}

void ABPCommunicationCharacter::MoveRight(float Value)
{
    if ( (Controller != nullptr) && (Value != 0.0f) )
    {
        // 找出向右方向
        const FRotator Rotation = Controller->GetControlRotation();
        const FRotator YawRotation(0, Rotation.Yaw, 0);

        // 获取向右向量 
        const FVector Direction = FRotationMatrix(YawRotation).GetUnitAxis(EAxis::Y);

        // 在该方向上添加位移
        AddMovementInput(Direction, Value);
    }
}

3 - 与电灯蓝图交互

  1. 在关卡中选择 ThirdPersonCharacter 蓝图,将其放置在靠近电灯的位置。

    图像替换文本

  2. 在选择 ThirdPersonCharacter 之后,导航至 细节(Details) 面板,然后从BPCommunication角色类别中,找到 要切换的天花板光源(Ceiling Light To Toggle) 变量,然后选择它旁边的箭头。在下拉菜单中,搜索并选择 BP_CeilingLight Actor。

    图像替换文本

1.按 运行(Play) 进入 PlE (在编辑器中运行)模式,然后按 E键(E Key) 打开和关闭电灯。

![图像替换文本](image_11.gif)(convert:false)

阶段成果

在此部分中,你添加了天花板光源Actor对 ThirdPersonCharacter 蓝图的引用,并且通过按E键打开和关闭了光源。

后续步骤

现在你已了解如何使用直接蓝图通信类型,接下来可以查看 Actor通信 文档页面中引用的其他通信类型。

欢迎帮助改进虚幻引擎文档!请告诉我们该如何更好地为您服务。
填写问卷调查
取消