类型转换快速入门指南

类型转换通信方法的快速入门介绍。

Choose your operating system:

Windows

macOS

Linux

选择实现方法:

Blueprints

C++

概述

类型转换(Cast)是一种常用的通信方法,它允许你引用一个Actor,并尝试将它转换为其他类。如果转换成功,则可以直接访问对象Actor的信息和函数。

此方法中,你可以先引用关卡中的Actor,然后使用 类型转换(Cast) 节点将其转换为特定类型。在这类通信方法中,当前Actor和目标Actor之间是一对一的关系。

目标

在此快速入门指南中,你将学习如何使用类型转换(Cast)来访问目标Actor中的信息。

任务

  • 创建一个会根据变量值旋转的Actor。

  • 修改ThirdPersonCharacter蓝图,将碰撞对象转换成你创建的旋转Actor。

  • 将旋转的Actor作为父类,派生多个子Actor,展示如何将类型转换用于共享同一个父类的多个子类Actor。

1 - 必要设置

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

    image alt text

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

    image alt text

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

    image alt text

阶段成果

你已经创建了一个新的第三人称项目,现在可以尝试类型转换了。

2 - 创建旋转Actor

本示例将创建一个静态网格体Actor,当玩家靠近时,该Actor将会开始旋转。

  1. 内容浏览器(Content Browser) 中点击右键,在 创建基本资产(Create Basic Asset) 分段下点击 蓝图类(Blueprint Class)

    image alt text

  2. 选择 Actor 作为父类,并将蓝图命名为 BP_RotateObject

    image alt text

    image alt text

  3. 内容浏览器(Content Browser) 中双击蓝图将其打开。然后在蓝图编辑器窗口中,转到 组件(Components) 面板,点击 添加组件(Add Component) 按钮。搜索并选择 静态网格体(Static Mesh) 。这会将静态网格体组件添加到蓝图。

    image alt text

  4. 在选择 静态网格体(Static Mesh) 组件之后,转到 细节(Details) 面板并点击 静态网格体(Static Mesh) 下拉菜单。搜索并选择 Shape_Cube

    image alt text

  5. 事件图表(Event Graph) 中点击右键以打开上下文敏感的搜索窗口,搜索并选择 AddActorLocalRotation ,以将此节点添加到图表。

    image alt text

  6. AddActorLocalRotation 节点连接到 Event Tick 。将 Z值(Z value) 设置为 2.0

    image alt text

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

  8. BP_RotateObject Actor 拖动到关卡中,然后点击 运行(Play) 。你应该看到立方体在持续旋转。

    image alt text

    image alt text

  9. 现在要添加一个条件,让对象仅在玩家靠近时旋转。右键点击 事件图表(Event Graph) ,然后添加 Branch 节点。连接 Event Tick 节点的输出引脚和 AddActorLocalRotation 节点的输入引脚之间的节点。

    image alt text

  10. 创建名为 可以旋转(Can Rotate) 的布尔类型的变量,然后将其连接到 Branch 节点的 条件(Condition) 引脚,如下所示。

image alt text

  1. 编译(Compile) 蓝图,将 CanRotate 默认值(Default Value) 设置为 False

    image alt text

  2. 打开 我的蓝图(My Blueprints) 选项卡,然后点击 添加函数(+ Function) 按钮以创建新的函数。将函数命名为 OverlappedPlayer

    image alt text

  3. 在选择函数之后,转到 细节(Details) 面板并点击 添加新参数(+ New Parameter) 按钮。将新的布尔参数命名为 开始重叠(Begin Overlap)

    image alt text

  4. CanRotate 变量拖动到函数内部,然后选择 设置CanRotate(Set CanRotate) 。将 Overlapped Player 节点连接到 Set Can Rotate 节点。将 Overlapped Player 节点的 开始重叠(Begin Overlap) 引脚连接到 Set Can Rotate 节点的 可以旋转(Can Rotate) 引脚,如下所示。

    image alt text

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

阶段成果

在此小节中,你创建了一个能在 CanRotate 变量设置为 True 时发生旋转的静态网格体Actor。

修改玩家蓝图

在此部分中,你将修改 ThirdPersonCharacter 蓝图,以便将碰撞对象转换成 BP_RotateObject Actor,并在你靠近时将其 旋转(Rotate) 变量设置为 True

  1. 选择你的 ThirdPersonCharacter 蓝图,打开 世界大纲视图(World Outliner) ,点击 编辑ThirdPersonCharacter(Edit ThirdPersonCharacter) 以打开蓝图。

    image alt text

  2. 在蓝图编辑器窗口中,转到 组件(Components) 面板,点击 添加组件(Add Component) 按钮。 搜索并选择 球体碰撞(Sphere Collision) 。这会将球体碰撞组件添加到蓝图。

    image alt text

  3. 选择 球体碰撞(Sphere Collision) 组件之后,转到 细节(Details) 面板,将 半径(Radius) 设置为200。

    image alt text

  4. 右键点击 球体碰撞(Sphere Collision) 组件,然后选择 OnComponentBeginOverlap OnComponentEndOverlap 事件,将其添加到 事件图表(Event Graph)

    image alt text

    image alt text

  5. On Component Begin Overlap 节点的 其他Actor(Other Actor) 引脚拖出一根引线,然后搜索并选择 类型转换到BP旋转对象(cast to BP Rotate Object)

    image alt text

  6. 作为BP旋转对象(As BP Rotate Object) 引脚拖出一根引线,然后搜索并选择 Overlapped Player 。启用 Overlapped Player 节点的 开始重叠(Begin Overlap)

    image alt text

    image alt text

  7. 重复步骤5和6,将相同的节点附加到 On Component End Overlap 节点。禁用 Overlapped Player 节点的 开始重叠(Begin Overlap) 引脚。

    image alt text

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

  9. 运行(Play) 并接近 BP_RotateObject Actor,可以看到只有当玩家靠近后它才会开始旋转。

    image alt text

阶段成果

在此小节中,你在 ThirdPersonCharacter 蓝图中添加了球体碰撞组件,该蓝图会尝试转换它碰撞到的所有Actor。

ThirdPersonCharacter 蓝图会尝试将碰撞到的Actor引用转换成 BP_RotateObject ,并在玩家靠近后将 CanRotate 变量设置为 True 。如果碰撞到的Actor不是 BP_RotateObject 类的实例,则转换失败,不会修改任何变量。

4 - 添加不同的旋转形状

现在,你需要从 BP_RotateObject Actor类派生出多个子Actor,让玩家激活不同形状的旋转。本小节将演示如何通过子类Actor来扩展或修改父类的功能,同时保留子类转换为共有父类的能力。

  1. 内容浏览器(Content Browser) 中右键点击 BP_RotateObject ,然后选择 创建子蓝图类(Create Child Blueprint Class) 。将蓝图命名为 BP_RotateObject_Cone

    image alt text

  2. 重复上述步骤两次,创建 BP_RotateObject_Pyramid BP_RotateObject_Torus

    image alt text

  3. 打开 BP_RotateObject_Cone 并在 组件(Components) 窗口中选择 静态网格体(Static Mesh) 组件。在 细节(Details) 面板中,点击 静态网格体(Static Mesh) 下拉菜单,然后搜索并选择 Shape_Cone

    image alt text

  4. 将Y轴的 旋转(Rotation) 设置为90度。

    image alt text

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

  6. 针对 BP_RotateObject_Pyramid 重复执行上述步骤,并选择 Shape_Quad_Pyramid 作为静态网格体。

  7. 针对 BP_RotateObject_Torus 重复执行上述步骤,并选择 Shape_Torus 作为静态网格体。在Y轴上旋转网格体90度。

  8. 将每个形状拖动到关卡中并按 运行(Play) ,验证它们全都可以在玩家靠近时旋转。

    image alt text

    image alt text

阶段成果

在此部分中,你根据 BP_RotateObject Acotr创建了多个子Actor,并将一个不同的 静态网格体(Static Mesh) 分配到每个子Actor。

此外,你还学习了如何将子类转换成父类,以便访问共有的函数。在此情况下,你碰撞了每个子类Actor并将其转换为父类,以触发旋转。

后续步骤

现在你已了解如何使用类型转换方法,接下来请了解 Actor通信 中提到的其他通信类型。

概述

对蓝图类进行类型转换是一种常见的通信手段。在这种方法中,你需要引用某个Actor类的蓝图,然后将它转换为其他类。如果成功,则能通过"直接蓝图通信(Direct Blueprint)"来访问其信息和功能。

此方法需要你引用关卡中的Actor类蓝图,以便使用 Cast 节点将其转换为特定类。采用这种通信类型时,当前Actor类蓝图和目标Actor类蓝图之间是一对一关系。

目标

在此快速入门指南中,你将学习如何使用C++创建Actor,为它编写转换蓝图类的功能,以便它访问目标蓝图中的信息。

任务

  • 创建一个能根据变量值旋转的蓝图。

  • 修改ThirdPersonCharacter蓝图,将碰撞对象转换成你创建的旋转蓝图。

  • 将旋转的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) 中新建名为 RotatingActor 的新Actor类。

    图像替换文本

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

    public: 
    
        void SetbCanRotate(bool value);
    
    protected:
    
        // 当游戏开始或重生(Spawn)时被调用
        virtual void BeginPlay() override;
        void RotateActor();
        bool bCanRotate;
    
        UPROPERTY(EditAnywhere, BlueprintReadWrite)
        UStaticMeshComponent* MeshComp;
  3. 导航到 RotatingActor.cpp 并在构造函数 ARotatingActor::ARotatingActor 中声明以下代码

    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
    MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("StaticMesh"));
    MeshComp->SetupAttachment(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
    bCanRotate = false;
  4. ARotatingActor::RotateActor 方法实现以下代码。

    AddActorLocalRotation(ActorRotation);
  5. 找到 ARotatingActor::Tick 方法并实现以下代码。

    void ARotatingActor::Tick(float DeltaTime)
    {
        Super::Tick(DeltaTime);
    
        if (bCanRotate)
        {
            RotateActor();
        }
    }

已完成代码

RotatingActor.h

#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "RotatingActor.generated.h"

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

public: 
    // 为此Actor的属性设置默认值
    ARotatingActor();
    void SetbCanRotate(bool value);

protected:
    // 当游戏开始或重生(Spawn)时被调用
    virtual void BeginPlay() override;
    void RotateActor();
    bool bCanRotate;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    UStaticMeshComponent* MeshComp;

    //Actor的旋转速度。
    const FQuat ActorRotationRate =(FQuat(FRotator(0,2,0));

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

RotatingActor.cpp

#include "RotatingActor.h"

// 设置默认值
ARotatingActor::ARotatingActor()
{
    // 让此Actor每帧调用Tick()。  如果你不需要,可以关闭它以提升性能。
    PrimaryActorTick.bCanEverTick = true;
    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("SceneComponent"));
    MeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
    MeshComp->SetupAttachment(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
    bCanRotate = false;
}

void ARotatingActor::SetbCanRotate(bool value)
{
    bCanRotate = value;
}

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

void ARotatingActor::RotateActor()
{
    AddActorLocalRotation(ActorRotation);
}

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

    if (bCanRotate)
    {
        RotateActor();
    }
}
  1. 编译 你的代码。

  2. 在编辑器中,导航至 C++类文件夹(C++ Classes folder) ,右键点击 RotatingActor ,在 C++类操作(C++ Class Actions) 下拉菜单中,选择 基于RotatingActor创建蓝图类(Create Blueprint class based on RotatingActor) ,此旋转Actor名为 BP_RotatingActor

    图像替换文本

  3. BP_RotatingActor 蓝图的类默认值中,导航至 组件(Components) 选项卡,选择 MeshComp 静态网格体组件(Static Mesh Component) ,然后导航至 细节面板(Details panel) ,在 静态网格体类别(Static Mesh category) 中, 选择 静态网格体变量(Static Mesh variable) 旁边的箭头。 最后,在下拉菜单中选择 Shape_Cube 静态网格体。

    图像替换文本

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

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

    图像替换文本

阶段成果

在此小节中,你创建了一个会旋转的蓝图Actor。当 bCanRotate 变量设置为 True 时,它的其静态网格体每帧会发生旋转。

3 - 修改第三人称角色类

在此小节中,你将修改 BPCommunicationCharacter ,以便将碰撞对象转换为 旋转Actor(Rotating Actor) 类,并在玩家靠近时将 bCanRotate 变量设置为 True**。

  1. 打开 BPCommunicationCharacter.h 并实现以下代码。

    protected:
        virtual void NotifyActorBeginOverlap(AActor* OtherActor);
        virtual void NotifyActorEndOverlap(AActor* OtherActor);
        class USphereComponent* SphereComp;
  2. BPCommunicationCharacter.cpp 中包含以下类库

    include "RotatingActor.h"

    include "Components/SphereComponent.h"

  3. 在构造函数 ABPCommunicaionCharacter::BPCommunicationCharacter 中声明以下代码。

    SphereComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComp"));
    SphereComp->AttachToComponent(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform);
    SphereComp->SetSphereRadius(200);
  4. 接下来,实现 ABPCommunicationCharacter::NotifyActorBeginOverlap ABPCommunicationCharacter::NotifyActorEndOverlap

    void ABPCommunicationCharacter::NotifyActorBeginOverlap(AActor* OtherActor)
    {
        if (ARotatingActor* RotatingActorCheck =Cast<ARotatingActor>(OtherActor))
        {
            ActorCheck->SetbCanRotate(true);
        }
    }
    
    void ABPCommunicationCharacter::NotifyActorEndOverlap(AActor* OtherActor)
    {
        if (ARotatingActor* RotatingActorCheck = Cast<ARotatingActor>(OtherActor))
        {
            ActorCheck->SetbCanRotate(false);
        }
    }
  5. 编译你的代码。

最终代码

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:
        virtual void NotifyActorBeginOverlap(AActor* OtherActor);
        virtual void NotifyActorEndOverlap(AActor* OtherActor);

    UPROPERTY(EditAnywhere, BlueprintReadWrite)

        class USphereComponent* SphereComp;

        /** 重置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; }
};

BpCommunication.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"
#include "RotatingActor.h"
#include "Components/SphereComponent.h"

//////////////////////////////////////////////////////////////////////////
// ABPCommunicationCharacter

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; // 摄像机不相对于升降臂旋转

    SphereComp = CreateDefaultSubobject<USphereComponent>(TEXT("SphereComp"));
    SphereComp->SetupAttachment(GetMesh(), FAttachmentTransformRules::KeepRelativeTransform);
    SphereComp->SetSphereRadius(200);

    // 注意:网格体组件上的骨骼网格体和动画蓝图引用(从角色继承) 
    // 是在名为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"处理提供绝对增量的设备,例如鼠标。
    // "turnrate"适用于我们选择以变化速度方式进行处理的设备,例如模拟摇杆
    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::NotifyActorBeginOverlap(AActor* OtherActor)
{
    if (ARotatingActor* RotatingActorCheck =Cast<ARotatingActor>(OtherActor))
    {
        ActorCheck->SetbCanRotate(true);
    }
}

void ABPCommunicationCharacter::NotifyActorEndOverlap(AActor* OtherActor)
{
    if (ARotatingActor* RotatingActorCheck = Cast<ARotatingActor>(OtherActor))
    {
        ActorCheck->SetbCanRotate(false);
    }
}

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);
    }
}
  1. 按运行(Play)并接近 BP_RotateObject Actor,可以看到它仅当玩家在附近时才会旋转。

    图像替换文本

阶段成果

在此部分中,你将 球体组件(Sphere Component) 添加到了 BPCommunicationCharacter 类。

此外,你还创建了转换到 RotatingActor 类所需的碰撞逻辑,然后调用其 SetbCanRotate 函数。当玩家的球体组件与其碰撞时,该函数将 bCanRotate 变量设置为 True

4 - 添加不同的旋转形状

现在,你可以从 BP_RotatingActor 派生出多个子蓝图类,以便添加不同形状来响应玩家。本小节将演示如何通过子类Actor来扩展或修改父类的功能,同时保留子类转换为共有父类的能力。

  1. 内容浏览器(Content Browser) 中,右键点击 BP_Rotating Actor ,然后选择 创建子蓝图类(Create Child Blueprint Class) 。将蓝图命名为 BP_RotateObject_Cone

    图像替换文本

  2. 再重复执行步骤1两次,创建 BP_RotateObject_Pyramid BP_RotateObject_Torus 蓝图类。

    图像替换文本

  3. 在蓝图编辑器中打开 BP_RotateObject_Cone 并在 组件(Components) 选项卡中选择 静态网格体(Static Mesh) 组件。在 细节(Details) 面板中,点击 静态网格体(Static Mesh) 下拉菜单,然后搜索并选择 Shape_Cone

    图像替换文本

  4. 将Y轴的 旋转(Rotation) 设置为90度。

    图像替换文本

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

  6. 针对 BP_RotatingActor_Pyramid 重复执行步骤3-5,并选择 Shape_Quad_Pyramid 作为静态网格体。

  7. 针对 BP_RotatingActor_Torus 重复执行步骤3-5,并选择 Shape_Torus 作为静态网格体。在Y轴上旋转网格体90度。

  8. 将各形状拖到关卡中并点击 运行(Play) ,确保它们全都可以在玩家靠近时旋转。

    图像替换文本

    图像替换文本

阶段成果

在此小节中,你根据 BP_RotateObject 蓝图创建了多个子蓝图类,并为每个子Actor指定了一个 静态网格体(Static Mesh)

此外,你还学习了如何将子类转换成父类蓝图,以便访问共有函数。在本示例中,你碰撞了每个子类蓝图并将其转换为父类,以触发旋转。

后续步骤

现在你已了解如何使用类型转换方法,接下来请了解 Actor通信 中提到的其他通信类型。

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