直接Actor通信快速入门

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

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 ReferencePoint Lamp 1Set 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通信 文档页面中引用的其他通信类型。

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