生成/销毁Actor总览

在虚幻引擎4中生成Actor的指南。

Choose your operating system:

Windows

macOS

Linux

选择实现方法:

Blueprints

C++

很多时候,玩家在游戏中会不断获得新物品或新武器,甚至是遇到新的敌人。

在你的游戏中,你可能会希望在关卡中动态添加物品或敌人,这种行文称作"生成"。

在本篇入门指南中,你将创建一个Actor类,并且能通过点击按钮让这个Actor在出生点位置生成。

image alt text

创建要生成的Actor

在此小节中,你将创建一个Actor,它包含球体组件、静态网格体组件和粒子系统组件。

  1. 首先新建一个 第三人称(Third Person) 蓝图(Blueprint) 游戏项目,其中 初学者内容包(Starter Content) 设置为 启用(enabled) 。将该项目命名为 SpawnDestroy

    ![](image_1. png)(convert:false)

  2. 内容浏览器(Content Browser) 中选择 添加/导入(Add/Import) 按钮,新建一个 蓝图Actor(Blueprint Actor) 类,并将其命名为 Bp_ActorToSpawn

    image_2.png

  3. 类默认值(Class Defaults) 中,导航至 组件(Components) 选项卡并选择 添加组件(Add Component) 。然后,搜索并选择 球体组件(Sphere Component) ,并将其拖动到 场景组件(Scene Component) 上,使其成为新的 根组件(Root Component)

    image_3.png

  4. 球体组件(Sphere Component) 细节(Details) 面板中,导航至 形状(Shape) 类别,并将 球体半径(Sphere Radius) 值更改为 16.0

    image_4.png

  5. 导航至 物理(Physics) 类别,并选中 模拟物理(Simulate Physics) 变量旁边的框。

    image_5.png

  6. 导航至 组件(Components) 选项卡并选择 添加组件(Add Component) ,然后搜索并选择 静态网格体组件(Static Mesh Component)

    image_6.png

  7. 细节(Details) 面板中,找到 静态网格体(Static Mesh) 类别,选择 静态网格体(Static Mesh) 变量旁边的下拉箭头。然后,搜索并选择 Shape_Sphere静态网格体(Shape_Sphere Static Mesh) 资产。

    image_7.png

  8. 导航至 变换(Transform) 类别,并在 比例(Scale) 变量中将 X、Y Z 值更改为 0 .25 、0 .25 、0 .25 。然后在 位置(Location) 变量中将 Z 值更改为 -12.0

    image_8.png

  9. 导航至 组件(Components) 选项卡,选择 添加组件(Add Component) 。搜索并选择 粒子系统组件(Particle System Component)

    image_9.png

  10. 导航至 细节(Details) 面板,在 粒子(Particles) 类别中选择 模板(Template) 变量旁边的下拉箭头,然后搜索并选择 P_Fire

    image_10.png

  11. 编译(Compile) 保存(save) 蓝图。

    ![](image_11. png)(convert:false)

完成的蓝图

image_12.png

创建Actor生成器

现在已经创建了要生成的Actor,接下来将创建一个Actor生成器,其中包含用于生成新Bp_ActorSpawn蓝图的自定义函数。

  1. 内容浏览器(Content Browser) 中选择 添加/导入(Add/Import) 按钮,新建一个 蓝图Actor(Blueprint Actor) 类,并将其命名为 Bp_ActorSpawner

    image_13.png

  2. 类默认值(Class Defaults) 中,导航至 组件(Components) 选项卡并选择 添加组件(Add Component) 。然后搜索并选择 盒体组件(Box Component) ,并将其重命名为 SpawnVolume

    image_14.png

  3. 右键点击 事件图表(Event Graph) ,从 操作(Actions) 上下文菜单中搜索并选择 添加自定义事件(Add Custom Event) ,然后将其命名为 SpawnActor

    image_15.png

  4. 生成Actor自定义事件(Spawn Actor Custom Event) 执行引脚拖出一根引线,然后在 可执行操作(Executable actions) 下拉菜单中搜索并选择 Spawn Actor From Class

    image_16.png

  5. SpawnActor 节点的 类(Class) 引脚中,选择 BP_ActorToSpawn 类。

    image_17.png

  6. 点击 Spawn Actor from Class 节点中的 生成变换(Spawn Transform) 引脚并从中拖出一根引线,然后从 操作(Actions) 下拉菜单中搜索并选择 Get Actor Transform

    image_18.png

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

    image_19.png

完成的蓝图

image_20.png

设置其他角色操作命令

现在已经创建了两个Actor类(Bp_ActorToSpawn和Bp_ActorSpawner),接下来的任务是设置第三人称角色,使其拥有调用Actor生成器的Spawn Actor函数的功能。

  1. 导航至 编辑(Edit) > 项目设置(Project Settings) > 引擎(Engine) > 输入(Input) ,然后从 绑定(Bindings) > 操作(Action) 映射(Mappings) 类别中,点击 + 按钮 额外添加两个名为 SpawnActors DestroyActors 的映射。

    ![](image_21. png)(convert:false)

  2. SpawnActors 操作键映射设置为数字键 1 ,将 DestroyActors 操作键映射到数字键 2

    image_22.png

  3. 内容浏览器(Content Browser) 导航至 第三人称角色(Third Person Character) 蓝图,双击打开其类默认值,然后右键点击 事件图表(Event Graph) 。从 此蓝图的所有操作(All Actions for this Blueprint) 上下文菜单中,搜索并选择 SpawnActors 输入操作。

    image_23.png

  4. 按下(Pressed) 执行引脚拖出一根引线,然后在 可执行操作(Executable actions) 下拉菜单中搜索并选择 Get Actor Of Class 节点。然后,点击 Actor类(Actor Class) 的下拉箭头,选择 Bp Actor Spawner

    image_24.png

  5. Get Actor of Class 节点的 返回值引脚(Return value pin) 拖出一根引线。在 操作菜单(Actions menu) 中搜索并选择调用函数 Spawn Actor ,然后将 Get Actor Of Class 节点的执行引脚连接到 Spawn Actor 节点的执行引脚。

    image_25.png

  6. 右键点击 事件图表(Event Graph) ,在上下文菜单中搜索并选择 DestroyActors 输入操作事件。

    image_26.png

  7. 按下(Pressed) 执行引脚拖出一根引线,并在 可执行操作(Executable actions) 下拉菜单中搜索并选择 Get All Actors Of Class 节点。然后,点击 Actor类(Actor Class) 的下拉箭头,并选择 要生成的Bp Actor(Bp Actor to Spawn)

    image_27.png

  8. Out Actors返回值引脚(Out Actors Return value pin) 拖出一根引线,然后在下拉菜单中搜索并选择 For Each Loop With Break 节点。

    image_28.png

  9. 数组元素引脚(Array Element pin) 拖出一根引线,并在 操作(Actions) 菜单中搜索并选择 Destroy Actor 函数,然后将 Get All Actors of Class 节点的输出执行引脚连接到 For Each Loop with Break 节点的 执行引脚(the Execution Pin)

  10. 接下来,将For Each Loop with Break的 循环主体(Loop Body) 执行引脚连接到 销毁Actor(Destroy Actor) 输入执行引脚。

    image_29.png

  11. 编译(Compile) 保存(save)

    image_30.png

完成的蓝图

![](image_31. png)(convert:false)

设置场景

现在已经完成了玩家角色所需的功能创建,可以调用Bp_Spawner的SpawnActor函数,接下来将需要选择Bp_Spawner在关卡中的路径。

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

    image_32.png

  2. 选择 PIE (在编辑器中运行),以测试你的Bp_ActorSpawner。

最终结果

在编辑器中进行测试时,如果按 1 键,Actor生成器类将在关卡中生成Actor。如果决定按 2 键,则关卡中的所有ActorsToSpawn都将被销毁。

image_33.gif

创建要生成的Actor

  1. 首先创建一个新的 第三人称C++游戏项目 ,并启用 初学者内容包(Starter Content) 。将该项目命名为 SpawnDestroy

    image_34.png

  2. C++类向导(C++ Class Wizard) 中新建名为 ActorToSpawn Actor 类。

    image_35.png

  3. 在ActorToSpawn.h的类默认值中,实现以下内容。

    protected:
    
        UPROPERTY(EditAnywhere, BlueprintReadWrite)
        class USphereComponent* SphereComp;
    
        UPROPERTY(EditAnywhere, BlueprintReadWrite)
        UStaticMeshComponent* StaticMeshComp;
    
        UPROPERTY(EditAnywhere, BlueprintReadWrite)
        class UParticleSystemComponent* ParticleComp;
  4. 导航至ActorToSpawn.cpp并声明以下类库。

    #include "Components/SphereComponent.h"
    #include "Particles/ParticleSystemComponent.h"
  5. AActorToSpawn::AActorToSpawn 构造函数中,实现以下代码。

    AActorToSpawn::AActorToSpawn()
    {
        // 将此Actor设置为每帧调用Tick()。  如果不需要此特性,可以关闭以提升性能。
        PrimaryActorTick.bCanEverTick = true;
    
        //创建我们的默认组件
        SphereComp = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere"));
        StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
        ParticleComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("ParticleComp"));
    
        //绑定组件并设置物理效果
        SphereComp->SetupAttachment(RootComponent);
        SphereComp->SetSimulatePhysics(true);
        SphereComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
    
        StaticMeshComp->AttachToComponent(SphereComp,FAttachmentTransformRules::KeepRelativeTransform);
        ParticleComp->AttachToComponent(StaticMeshComp,FAttachmentTransformRules::KeepRelativeTransform);
    
        //将球体半径设置为符合静态网格体需求的更小尺寸。
        SphereComp->SetSphereRadius(16.0f);
    
        //设置静态网格体缩放和位置以符合球体半径的需求。
        StaticMeshComp->SetRelativeLocation(FVector(0.0, 0.0, -12.0f));
        StaticMeshComp->SetRelativeScale3D(FVector(0.25, 0.25, 0.25));
    
        //通过构造辅助函数,将静态网格体组件设置成球体形状。
        static ConstructorHelpers::FObjectFinder<UStaticMesh>SphereMeshAsset(TEXT("StaticMesh'/Game/StarterContent/Shapes/Shape_Sphere.Shape_Sphere'"));
        StaticMeshComp->SetStaticMesh(SphereMeshAsset.Object);
    
        //通过构造函数辅助,把粒子组件设置成火焰粒子组件。
        static ConstructorHelpers::FObjectFinder<UParticleSystem>ParticleCompAsset(TEXT("ParticleSystem'/Game/StarterContent/Particles/P_Fire.P_Fire'"));
        ParticleComp->SetTemplate(ParticleCompAsset.Object);
    }
  6. 编译 你的代码。

  7. 在编辑器中,导航到 C++类文件夹(C++ classes folder) ,然后右键点击你的 ActorToSpawn 。在上下文菜单中,选择 基于ActorToSpawn创建蓝图类(Create Blueprint class based on ActorToSpawn)

    image_36.png

    已完成的Bp_ActorToSpawn将如下图所示。

    image_37.png

已完成代码

ActorToSpawn.h

#pragma once

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

UCLASS()
class SPAWNDESTROYCPP_API AActorToSpawn : public AActor
{
    GENERATED_BODY()

public: 
    // 为此Actor的属性设置默认值
    AActorToSpawn();

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

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    class USphereComponent* SphereComp;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    UStaticMeshComponent* StaticMeshComp;

    UPROPERTY(EditAnywhere, BlueprintReadWrite)
    class UParticleSystemComponent* ParticleComp;

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

ActorToSpawn.cpp

#include "ActorToSpawn.h"
#include "Components/SphereComponent.h"
#include "Particles/ParticleSystemComponent.h"

// 设置默认值
AActorToSpawn::AActorToSpawn()
{
    // 将此Actor设置为每帧调用更新函数()。  如果不需要此特性,可以关闭以提升性能。
    PrimaryActorTick.bCanEverTick = true;

    //创建我们的默认组件
    SphereComp = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere"));
    StaticMeshComp = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComp"));
    ParticleComp = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("ParticleComp"));

    //绑定组件并设置物理
    SphereComp->SetupAttachment(RootComponent);
    SphereComp->SetSimulatePhysics(true);

    SphereComp->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
    StaticMeshComp->AttachToComponent(SphereComp,FAttachmentTransformRules::KeepRelativeTransform);
    ParticleComp->AttachToComponent(StaticMeshComp,FAttachmentTransformRules::KeepRelativeTransform);

    //将球体半径设置为符合静态网格体需求的更小尺寸。
    SphereComp->SetSphereRadius(16.0f);

    //设置静态网格体缩放和位置以符合球体半径的需求。
    StaticMeshComp->SetRelativeLocation(FVector(0.0, 0.0, -12.0f));
    StaticMeshComp->SetRelativeScale3D(FVector(0.25, 0.25, 0.25));
}

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

}

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

}

创建Actor生成器

现在你已经创建了要生成的Actor,接下来要创建一个使用自定义函数来生成新Actor的Actor生成器。

  1. C++类向导(C++ Class Wizard) 中新建名为 ActorSpawner Actor 类。

    image_38.png

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

    public:
    
        UFUNCTION()
        void SpawnActor();
    
    protected:
        UPROPERTY(EditAnywhere,BlueprintReadWrite)
        class UBoxComponent* SpawnVolume;
  3. 导航至ActorSpawner.cpp,并添加以下类库

    #include "Components/BoxComponent.h"
    #include "ActorToSpawn.h"
  4. AActorSpawner::AActorSpawner 构造函数中实现以下代码。

    AActorSpawner::AActorSpawner()
    {
        RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultSceneRoot"));
        SpawnVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolume"));
        SpawnVolume->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
    }
  5. AActorSpawner::SpawnActor 类方法实现以下代码。

    void AActorSpawner::SpawnActor()
    {
        FVector SpawnLocation = GetActorLocation();
        FRotator SpawnRotation = GetActorRotation();
    
            GetWorld()->SpawnActor<AActorToSpawn>(SpawnLocation,SpawnRotation);
    }
  6. 编译 你的代码。

  7. 内容浏览器(Content Browser) 中,导航至 C++类文件夹(C++ classes folder) ,然后右键点击 ActorSpawner 类,在 C++类操作(C++ Class Actions) 上下文菜单中,选择 基于ActorSpawner创建蓝图类(Create Blueprint class based on ActorSp awner) (此处的ActorSpawner名为 Bp_ActorSpawner )。

    image_39.png

    完成后的蓝图看起来应该类似于下图。

    image_40.png

已完成代码

ActorSpawner.h

#pragma once

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

UCLASS()
class SPAWNDESTROYCPP_API AActorSpawner : public AActor
{
    GENERATED_BODY()

public: 
    // 为此Actor的属性设置默认值
    AActorSpawner();

    UFUNCTION()
    void SpawnActor();

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

    UPROPERTY(EditAnywhere,BlueprintReadWrite)
    class UBoxComponent* SpawnVolume;

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

ActorSpawner.cpp

#include "ActorSpawner.h"
#include "Components/BoxComponent.h"
#include "ActorToSpawn.h"

// 设置默认值
AActorSpawner::AActorSpawner()
{
    // 将此Actor设置为每帧调用Tick()。  如果不需要此特性,可以关闭以提升性能。
    PrimaryActorTick.bCanEverTick = true;

    RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultSceneRoot"));
    SpawnVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolume"));

    SpawnVolume->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform);
}

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

void AActorSpawner::SpawnActor()
{
    FVector SpawnLocation = GetActorLocation();
    FRotator SpawnRotation = GetActorRotation();
    GetWorld()->SpawnActor<AActorToSpawn>(SpawnLocation,SpawnRotation);
}

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

设置其他角色操作命令

你的Actor和Actor生成器类已经设置,现在可以设置第三人称角色,而且具备调用Actor生成器的Spawn Actor函数的功能。此外,你还需要映射你的输入键映射,以便于玩家角色可以为你的玩家提供调用Actor生成器的Spawn Actor函数的能力。

  1. 导航至 编辑(Edit) > 项目设置(Project Settings) > 引擎(Engine) > 输入(Input) ,然后在 绑定(Bindings) > 操作(Action) 映射(mappings) 类别中,点击 + 按钮 额外添加名为SpawnActors和DestroyActors的两个映射。

    image_41.png

  2. SpawnActors 操作键设置为数字 1 键,然后将 DestroyActors 操作键映射设置为数字 2 键。

    image_42.png

  3. 打开你的ThirdPersonCharacter.h文件并声明以下类声明。

    protected:
        void SpawnActors();
        void DestroyActors();
  4. 导航至你的ThirdPersonCharacter.cpp,并添加以下类库。

    #include "Kismet/GameplayStatics.h"
    #include "ActorSpawner.h"
    #include "ActorToSpawn.h"

    GameplayStatics中包含可以从蓝图和C++调用的强大Gameplay工具函数。如需更多信息,请参见 GameplayStatics 的以下API文档。

  5. 为你的 ASpawnDestroyCppCharacter::SpawnActors ASpawnDestroyCppCharacter::DestroyActors 方法实现以下类实现。

    void ASpawnDestroyCppCharacter::SpawnActors()
    {
        //在世界中找到Actor生成器,并调用其Spawn Actor函数
        AActor* ActorSpawnerTofind = UGameplayStatics::GetActorOfClass(GetWorld(),AActorSpawner::StaticClass());
    
        AActorSpawner* ActorSpawnerReference = Cast<AActorSpawner>(ActorSpawnerTofind);
        if (ActorSpawnerReference)
        {
            ActorSpawnerReference->SpawnActor();
        }
    }
    
    void ASpawnDestroyCppCharacter::DestroyActors()
    {
        //获取世界中每个要生成的Actor,然后调用销毁Actor
        TArray<AActor*> FoundActors;
        UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActorToSpawn::StaticClass(), FoundActors);
        for (AActor* ActorFound :FoundActors)
        {
            ActorFound->Destroy();
        }
    }
  6. 导航至 ASpawnDestroyCppCharacter::SetupPlayerInputComponent 方法,并添加以下代码。

    void ASpawnDestroyCppCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
    {
        PlayerInputComponent->BindAction("SpawnActors", IE_Pressed, this, &ASpawnDestroyCppCharacter::SpawnActors);
        PlayerInputComponent->BindAction("DestroyActors", IE_Pressed, this, &ASpawnDestroyCppCharacter::DestroyActors);
    }

已完成代码

SpawnDestroyCppCharacter.h

#pragma once

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

UCLASS(config=Game)
class ASpawnDestroyCppCharacter : 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:
    ASpawnDestroyCppCharacter();

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

    /** 基础向上看/向下看速度,以度/秒为单位。其他单位可能会影响最终速度。*/
    UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
    float BaseLookUpRate;

protected:
    /*在关卡中调用Actor生成器来生成要生成的Actor*/
    void SpawnActors();

    /*获取所有ActorToSpawn Actor并调用它们的销毁函数 */
    void DestroyActors();

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

SpawnDestroyCppCharacter.cpp

#include "SpawnDestroyCppCharacter.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 "Kismet/GameplayStatics.h"
#include "ActorSpawner.h"
#include "ActorToSpawn.h"
//////////////////////////////////////////////////////////////////////////
// ASpawnDestroyCppCharacter

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

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

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

    // 配置角色移动
    GetCharacterMovement()->bOrientRotationToMovement = true; // Character moves in the direction of input...   
    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; // The camera follows at this distance behind the character   
    CameraBoom->bUsePawnControlRotation = true; // 基于控制器旋转升降臂

    // 创建一个跟随摄像机
    FollowCamera = CreateDefaultSubobject<UCameraComponent>(TEXT("FollowCamera"));
    FollowCamera->SetupAttachment(CameraBoom, USpringArmComponent::SocketName); // 将摄像机连接到升降臂末端,对升降臂进行调整以便与控制器方向保持一致
    FollowCamera->bUsePawnControlRotation = false; // 摄像机不相对于升降臂旋转

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

//////////////////////////////////////////////////////////////////////////
// 输入

void ASpawnDestroyCppCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent)
{
    // 设置Gameplay键绑定
    check(PlayerInputComponent);
    PlayerInputComponent->BindAction("Jump", IE_Pressed, this, &ACharacter::Jump);
    PlayerInputComponent->BindAction("Jump", IE_Released, this, &ACharacter::StopJumping);

    PlayerInputComponent->BindAction("SpawnActors", IE_Pressed, this, &ASpawnDestroyCppCharacter::SpawnActors);
    PlayerInputComponent->BindAction("DestroyActors", IE_Pressed, this, &ASpawnDestroyCppCharacter::DestroyActors);
    PlayerInputComponent->BindAxis("MoveForward", this, &ASpawnDestroyCppCharacter::MoveForward);
    PlayerInputComponent->BindAxis("MoveRight", this, &ASpawnDestroyCppCharacter::MoveRight);

    // 我们提供了两个版本的旋转绑定来处理不同类型的设备,
    // "旋转"负责处理可以提供绝对增量的设备,例如鼠标。
    // "旋转速度"适用于我们选择作为更改速度来处理的设备,例如模拟摇杆
    PlayerInputComponent->BindAxis("Turn", this, &APawn::AddControllerYawInput);
    PlayerInputComponent->BindAxis("TurnRate", this, &ASpawnDestroyCppCharacter::TurnAtRate);
    PlayerInputComponent->BindAxis("LookUp", this, &APawn::AddControllerPitchInput);
    PlayerInputComponent->BindAxis("LookUpRate", this, &ASpawnDestroyCppCharacter::LookUpAtRate);

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

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

void ASpawnDestroyCppCharacter::SpawnActors()
{

    //在关卡中找到Actor生成器,并调用其Spawn Actor函数
    AActor* ActorSpawnerTofind = UGameplayStatics::GetActorOfClass(GetWorld(),AActorSpawner::StaticClass());
    AActorSpawner* ActorSpawnerReference = Cast<AActorSpawner>(ActorSpawnerTofind);

    if (ActorSpawnerReference)
    {
        ActorSpawnerReference->SpawnActor();
    }
}

void ASpawnDestroyCppCharacter::DestroyActors()
{
    TArray<AActor*> FoundActors;
    UGameplayStatics::GetAllActorsOfClass(GetWorld(), AActorToSpawn::StaticClass(), FoundActors);
    for (AActor* ActorFound :FoundActors)
    {
        ActorFound->Destroy();
    }
}

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

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

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

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

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

void ASpawnDestroyCppCharacter::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 ASpawnDestroyCppCharacter::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);
    }
}

设置场景

现在你已经完成了玩家角色所需的功能创建,可以调用Bp_Spawner的SpawnActor函数,接下来将需要设置Bp_Spawner在关卡中的位置。

  1. 内容浏览器(Content Browser) 中,点击 Bp_ Spawner 的实例并将其拖动到关卡中。

    image_43.png

  2. 选择 PIE (在编辑器中运行)以测试你的生成器。

最终结果

在编辑器中测试时,如果你按 1 键,Actor生成器类将生成其Actor以生成到关卡中。如果决定按 2 键,则关卡中的所有ActorsToSpawn都将被销毁。

image_44.gif

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