Choose your operating system:
Windows
macOS
Linux
选择实现方法:
Blueprints
C++
很多时候,玩家在游戏中会不断获得新物品或新武器,甚至是遇到新的敌人。
在你的游戏中,你可能会希望在关卡中动态添加物品或敌人,这种行文称作"生成"。
在本篇入门指南中,你将创建一个Actor类,并且能通过点击按钮让这个Actor在出生点位置生成。
创建要生成的Actor
在此小节中,你将创建一个Actor,它包含球体组件、静态网格体组件和粒子系统组件。
-
首先新建一个 第三人称(Third Person) 蓝图(Blueprint) 游戏项目,其中 初学者内容包(Starter Content) 设置为 启用(enabled) 。将该项目命名为 SpawnDestroy 。
![](image_1. png)(convert:false) -
从 内容浏览器(Content Browser) 中选择 添加/导入(Add/Import) 按钮,新建一个 蓝图Actor(Blueprint Actor) 类,并将其命名为 Bp_ActorToSpawn 。
-
在 类默认值(Class Defaults) 中,导航至 组件(Components) 选项卡并选择 添加组件(Add Component) 。然后,搜索并选择 球体组件(Sphere Component) ,并将其拖动到 场景组件(Scene Component) 上,使其成为新的 根组件(Root Component) 。
-
在 球体组件(Sphere Component) 的 细节(Details) 面板中,导航至 形状(Shape) 类别,并将 球体半径(Sphere Radius) 值更改为 16.0 。
-
导航至 物理(Physics) 类别,并选中 模拟物理(Simulate Physics) 变量旁边的框。
-
导航至 组件(Components) 选项卡并选择 添加组件(Add Component) ,然后搜索并选择 静态网格体组件(Static Mesh Component) 。
-
在 细节(Details) 面板中,找到 静态网格体(Static Mesh) 类别,选择 静态网格体(Static Mesh) 变量旁边的下拉箭头。然后,搜索并选择 Shape_Sphere静态网格体(Shape_Sphere Static Mesh) 资产。
-
导航至 变换(Transform) 类别,并在 比例(Scale) 变量中将 X、Y 和 Z 值更改为 0 .25 、0 .25 、0 .25 。然后在 位置(Location) 变量中将 Z 值更改为 -12.0 。
-
导航至 组件(Components) 选项卡,选择 添加组件(Add Component) 。搜索并选择 粒子系统组件(Particle System Component) 。
-
导航至 细节(Details) 面板,在 粒子(Particles) 类别中选择 模板(Template) 变量旁边的下拉箭头,然后搜索并选择 P_Fire 。
-
编译(Compile) 并 保存(save) 蓝图。
![](image_11. png)(convert:false)
完成的蓝图
创建Actor生成器
现在已经创建了要生成的Actor,接下来将创建一个Actor生成器,其中包含用于生成新Bp_ActorSpawn蓝图的自定义函数。
-
从 内容浏览器(Content Browser) 中选择 添加/导入(Add/Import) 按钮,新建一个 蓝图Actor(Blueprint Actor) 类,并将其命名为 Bp_ActorSpawner 。
-
在 类默认值(Class Defaults) 中,导航至 组件(Components) 选项卡并选择 添加组件(Add Component) 。然后搜索并选择 盒体组件(Box Component) ,并将其重命名为 SpawnVolume 。
-
右键点击 事件图表(Event Graph) ,从 操作(Actions) 上下文菜单中搜索并选择 添加自定义事件(Add Custom Event) ,然后将其命名为 SpawnActor 。
-
从 生成Actor自定义事件(Spawn Actor Custom Event) 执行引脚拖出一根引线,然后在 可执行操作(Executable actions) 下拉菜单中搜索并选择 Spawn Actor From Class 。
-
在 SpawnActor 节点的 类(Class) 引脚中,选择 BP_ActorToSpawn 类。
-
点击 Spawn Actor from Class 节点中的 生成变换(Spawn Transform) 引脚并从中拖出一根引线,然后从 操作(Actions) 下拉菜单中搜索并选择 Get Actor Transform 。
-
编译(Compile) 并 保存(save) 蓝图。
完成的蓝图
设置其他角色操作命令
现在已经创建了两个Actor类(Bp_ActorToSpawn和Bp_ActorSpawner),接下来的任务是设置第三人称角色,使其拥有调用Actor生成器的Spawn Actor函数的功能。
-
导航至 编辑(Edit) > 项目设置(Project Settings) > 引擎(Engine) > 输入(Input) ,然后从 绑定(Bindings) > 操作(Action) 映射(Mappings) 类别中,点击 + 按钮 额外添加两个名为 SpawnActors 和 DestroyActors 的映射。
![](image_21. png)(convert:false) -
将 SpawnActors 操作键映射设置为数字键 1 ,将 DestroyActors 操作键映射到数字键 2 。
-
从 内容浏览器(Content Browser) 导航至 第三人称角色(Third Person Character) 蓝图,双击打开其类默认值,然后右键点击 事件图表(Event Graph) 。从 此蓝图的所有操作(All Actions for this Blueprint) 上下文菜单中,搜索并选择 SpawnActors 输入操作。
-
从 按下(Pressed) 执行引脚拖出一根引线,然后在 可执行操作(Executable actions) 下拉菜单中搜索并选择 Get Actor Of Class 节点。然后,点击 Actor类(Actor Class) 的下拉箭头,选择 Bp Actor Spawner 。
-
从 Get Actor of Class 节点的 返回值引脚(Return value pin) 拖出一根引线。在 操作菜单(Actions menu) 中搜索并选择调用函数 Spawn Actor ,然后将 Get Actor Of Class 节点的执行引脚连接到 Spawn Actor 节点的执行引脚。
-
右键点击 事件图表(Event Graph) ,在上下文菜单中搜索并选择 DestroyActors 输入操作事件。
-
从 按下(Pressed) 执行引脚拖出一根引线,并在 可执行操作(Executable actions) 下拉菜单中搜索并选择 Get All Actors Of Class 节点。然后,点击 Actor类(Actor Class) 的下拉箭头,并选择 要生成的Bp Actor(Bp Actor to Spawn) 。
-
从 Out Actors返回值引脚(Out Actors Return value pin) 拖出一根引线,然后在下拉菜单中搜索并选择 For Each Loop With Break 节点。
-
从 数组元素引脚(Array Element pin) 拖出一根引线,并在 操作(Actions) 菜单中搜索并选择 Destroy Actor 函数,然后将 Get All Actors of Class 节点的输出执行引脚连接到 For Each Loop with Break 节点的 执行引脚(the Execution Pin) 。
-
接下来,将For Each Loop with Break的 循环主体(Loop Body) 执行引脚连接到 销毁Actor(Destroy Actor) 输入执行引脚。
-
编译(Compile) 并 保存(save) 。
完成的蓝图
设置场景
现在已经完成了玩家角色所需的功能创建,可以调用Bp_Spawner的SpawnActor函数,接下来将需要选择Bp_Spawner在关卡中的路径。
-
在 内容浏览器(Content Browser) 中,将 Bp_ActorSpawner 的实例拖动到关卡中。
-
选择 PIE (在编辑器中运行),以测试你的Bp_ActorSpawner。
最终结果
在编辑器中进行测试时,如果按 1 键,Actor生成器类将在关卡中生成Actor。如果决定按 2 键,则关卡中的所有ActorsToSpawn都将被销毁。
创建要生成的Actor
-
首先创建一个新的 第三人称C++游戏项目 ,并启用 初学者内容包(Starter Content) 。将该项目命名为 SpawnDestroy 。
-
从 C++类向导(C++ Class Wizard) 中新建名为 ActorToSpawn 的 Actor 类。
-
在ActorToSpawn.h的类默认值中,实现以下内容。
protected: UPROPERTY(EditAnywhere, BlueprintReadWrite) class USphereComponent* SphereComp; UPROPERTY(EditAnywhere, BlueprintReadWrite) UStaticMeshComponent* StaticMeshComp; UPROPERTY(EditAnywhere, BlueprintReadWrite) class UParticleSystemComponent* ParticleComp;
-
导航至ActorToSpawn.cpp并声明以下类库。
#include "Components/SphereComponent.h" #include "Particles/ParticleSystemComponent.h"
-
在 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); }
-
编译 你的代码。
-
在编辑器中,导航到 C++类文件夹(C++ classes folder) ,然后右键点击你的 ActorToSpawn 。在上下文菜单中,选择 基于ActorToSpawn创建蓝图类(Create Blueprint class based on ActorToSpawn) 。
已完成的Bp_ActorToSpawn将如下图所示。
已完成代码
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生成器。
-
从 C++类向导(C++ Class Wizard) 中新建名为 ActorSpawner 的 Actor 类。
-
在ActorSpawner.h的类默认值中,实现以下代码。
public: UFUNCTION() void SpawnActor(); protected: UPROPERTY(EditAnywhere,BlueprintReadWrite) class UBoxComponent* SpawnVolume;
-
导航至ActorSpawner.cpp,并添加以下类库
#include "Components/BoxComponent.h" #include "ActorToSpawn.h"
-
在 AActorSpawner::AActorSpawner 构造函数中实现以下代码。
AActorSpawner::AActorSpawner() { RootComponent = CreateDefaultSubobject<USceneComponent>(TEXT("DefaultSceneRoot")); SpawnVolume = CreateDefaultSubobject<UBoxComponent>(TEXT("SpawnVolume")); SpawnVolume->AttachToComponent(RootComponent, FAttachmentTransformRules::KeepRelativeTransform); }
-
为 AActorSpawner::SpawnActor 类方法实现以下代码。
void AActorSpawner::SpawnActor() { FVector SpawnLocation = GetActorLocation(); FRotator SpawnRotation = GetActorRotation(); GetWorld()->SpawnActor<AActorToSpawn>(SpawnLocation,SpawnRotation); }
-
编译 你的代码。
-
在 内容浏览器(Content Browser) 中,导航至 C++类文件夹(C++ classes folder) ,然后右键点击 ActorSpawner 类,在 C++类操作(C++ Class Actions) 上下文菜单中,选择 基于ActorSpawner创建蓝图类(Create Blueprint class based on ActorSp awner) (此处的ActorSpawner名为 Bp_ActorSpawner )。
完成后的蓝图看起来应该类似于下图。
已完成代码
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函数的能力。
-
导航至 编辑(Edit) > 项目设置(Project Settings) > 引擎(Engine) > 输入(Input) ,然后在 绑定(Bindings) > 操作(Action) 映射(mappings) 类别中,点击 + 按钮 额外添加名为SpawnActors和DestroyActors的两个映射。
-
将 SpawnActors 操作键设置为数字 1 键,然后将 DestroyActors 操作键映射设置为数字 2 键。
-
打开你的ThirdPersonCharacter.h文件并声明以下类声明。
protected: void SpawnActors(); void DestroyActors();
-
导航至你的ThirdPersonCharacter.cpp,并添加以下类库。
#include "Kismet/GameplayStatics.h" #include "ActorSpawner.h" #include "ActorToSpawn.h"
GameplayStatics中包含可以从蓝图和C++调用的强大Gameplay工具函数。如需更多信息,请参见 GameplayStatics 的以下API文档。
-
为你的 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(); } }
-
导航至 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在关卡中的位置。
-
从 内容浏览器(Content Browser) 中,点击 Bp_ Spawner 的实例并将其拖动到关卡中。
-
选择 PIE (在编辑器中运行)以测试你的生成器。
最终结果
在编辑器中测试时,如果你按 1 键,Actor生成器类将生成其Actor以生成到关卡中。如果决定按 2 键,则关卡中的所有ActorsToSpawn都将被销毁。