Choose your operating system:
Windows
macOS
Linux
每当项目变复杂后,你会发现在场景中查找 Actor 会变得愈发困难。场景中往往可以有数以百计的Actor,包括关卡模型和几何体、NPC、敌人、可交互对象、可拾取对象等。 在虚幻编辑器中工作时,你可以使用 世界大纲 视图来定位某个Actor。
在世界大纲视图中选中某个Actor,然后点击关卡视图,双击该Actor或直接按下 F ,可直接将窗口 对准 该Actor。
请参阅 世界大纲视图 了解在场景中定位Actor的方法。
选择实现方法:
Blueprints
C++
项目设置
在本教程中,你将使用 Get All Actors of Class 节点在关卡中找到Actor。此节点受到调用时,它将检索关卡指定类(Class)中的所有Actor,并将它们放置在 数组(Array) 中。然后,你可以根据筛选条件从该数组中检索Actor。然后,你可以访问Actor的属性,或者根据你要实现的功能以某种方式修改它们。
-
首先,点击 新建(New) > 游戏(Games) > 第三人称(ThirdPerson) > 蓝图项目带初学者内容包(Blueprint Project With Starter Content) ,创建名为 FindingActors 的项目。
-
找到 编辑(Edit) > 项目设置(Project Settings) > 引擎(Engine) > 输入(Input) > 绑定(Bindings) > 操作映射(Action Mappings) ,然后点击 添加(Add) ( + ),创建名为 FindActorPressed 的新操作映射,然后将 关键值 设置为 1 。
在本教程中,你将使用 Gameplay静态类库(Gameplay Statics Class Library) ( Get All Actors of Class 节点)在关卡中找到 Actor 。此函数(节点)受到调用时,它将检索关卡指定 类(Class) 中的所有Actor,并将它们放置在 数组(Array) 中。然后,你可以根据筛选条件从该数组中检索全部Actor或一个Actor。然后,你可以访问Actor的属性,或者根据你要实现的功能以某种方式修改它们。
-
首先,点击 新建(New) > 游戏(Games) > 第三人称(ThirdPerson) > C++ 项目 带 初学者内容包 ( C++ Project With Starter Content ),创建名为 FindingActors 的项目。
-
找到 编辑(Edit) > 项目设置(Project Settings) > 引擎(Engine) > 输入(Input) > 绑定(Bindings) > 操作映射(Action Mappings) ,然后点击 添加(Add) ( + ),创建名为 FindActorPressed 的新操作映射,然后将 关键值 设置为 1 。
创建火焰Actor
初学者内容包(Starter Content) 文件夹提供了完整的FireEffect Actor,其中包括表示火焰效果的 粒子组件(Particle Component) 和用于声音效果的 音频组件(Audio Component) 。此Actor将用作从Get All Actors of Class节点查找的Actor基类。
-
找到 内容(Content) > StarterContent > 蓝图(Blueprints) ,然后将 Blueprint_Effect_Fire 实例拖到世界中。
-
点击 添加/导入(Add/Import) 按钮 可以 创建 新C++类(New C++ Class) ,然后从 选择父类(Choose a Parent Class) 菜单中,选择 Actor ,创建名为 FireEffect 的新Actor类。
-
在FireEffect.h中,声明以下内容:
public: //获取火焰音效音频组件。 UAudioComponent* GetFireAudioComponent() const { return FireAudioComponent; } //获取火焰效果粒子系统组件。 UParticleSystemComponent* GetParticleFireComponent() const { return ParticleFireComponent; } protected: UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UParticleSystemComponent* ParticleFire; UPROPERTY(EditDefaultsOnly, BlueprintReadWrite) UAudioComponent* FireAudio;
-
找到
FireEffect.cpp
文件并添加以下类库:#include "Particles/ParticleSystemComponent.h" #include "Components/AudioComponent.h"
-
在FireEffect构造函数中,实现以下代码:
AFireEffect::AFireEffect() { // 将此Actor设置为每帧调用更新函数()。 如果不需要此特性,可以关闭以提升性能。 PrimaryActorTick.bCanEverTick = true; ParticleFire = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("P_Fire")); FireAudio = CreateDefaultSubobject<UAudioComponent>(TEXT("Fire Audio")); ParticleFire->SetupAttachment(RootComponent); FireAudio->AttachToComponent(ParticleFire,FAttachmentTransformRules::KeepRelativeTransform); }
-
编译 你的代码。
-
找到 内容浏览器(Content Browser) > C++类(C++ Classes) > FindingActors ,右键点击 FireEffect Actor, 创建 名为 BP_FireEffect 的基于FireEffect的蓝图类。
-
在 BP_FireEffect 的 类默认值(Class Defaults) 中,点击 组件(Components) 面板中的 粒子火焰(Particle Fire) ,然后找到 细节(Details) 面板,在 粒子(Particles) 类别下,打开 模板(Template) 下拉菜单并选择 P_Fire 。
-
点击 组件(Components) 面板中的 火焰音频(Fire Audio) ,然后找到 细节(Details) 面板。从 音效(Sound) 类别打开 音效(Sound) 变量下拉菜单,然后选择 Fire01_Cue 。
-
点击 编译(Compile) 和 保存(Save) 。
已完成代码
FireEffectActor.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "FireEffect.generated.h"
UCLASS()
class FINDINGACTORS_API AFireEffect : public AActor
{
GENERATED_BODY()
public:
// 为此Actor的属性设置默认值
AFireEffect();
UAudioComponent* GetFireAudioComponent() const { return FireAudioComponent; }
UParticleSystemComponent* GetParticleFireComponent() const { return ParticleFireComponent; }
protected:
// 当游戏开始或生成时调用
virtual void BeginPlay() override;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
UParticleSystemComponent* ParticleFireComponent;
UPROPERTY(EditDefaultsOnly, BlueprintReadWrite)
UAudioComponent* FireAudioComponent;
public:
// 每一帧都调用
virtual void Tick(float DeltaTime) override;
};
FireEffectActor.cpp
#include "FireEffect.h"
#include "Particles/ParticleSystemComponent.h"
#include "Components/AudioComponent.h"
// 设置默认值
AFireEffect::AFireEffect()
{
// 将此Actor设置为每帧调用更新函数()。 如果不需要此特性,可以关闭以提升性能。
PrimaryActorTick.bCanEverTick = true;
ParticleFireComponent = CreateDefaultSubobject<UParticleSystemComponent>(TEXT("P_Fire"));
FireAudioComponent = CreateDefaultSubobject<UAudioComponent>(TEXT("Fire Audio"));
ParticleFireComponent->SetupAttachment(RootComponent);
FireAudioComponent->AttachToComponent(ParticleFireComponent,FAttachmentTransformRules::KeepRelativeTransform);
}
// 当游戏开始或生成时调用
void AFireEffect::BeginPlay()
{
Super::BeginPlay();
}
// 每一帧都调用
void AFireEffect::Tick(float DeltaTime)
{
Super::Tick(DeltaTime);
}
第三人称角色:设置FindingActor Pressed Event
-
找到 内容(Content) > ThirdPersonBp > 蓝图(Blueprints) 文件夹,并双击 ThirdPersonCharacter 打开其 类默认值(Class Defaults) 。
-
右键点击 事件图表(Event Graph) ,然后在 操作(Actions) 菜单中搜索 FindActorPressed 操作键事件。
-
在 FindActorPressed 节点键事件,从 Pressed 引脚拖出,然后从 操作(Actions)菜单 搜索 Get All Actors Of Class 节点。
-
在 Get All Actors of Class 节点内,点击 Actor类(Actor Class) ,然后在下拉列表中选择 Blueprint_Effect_Fire 类。
-
从 Out Actors 引脚拖出,然后在 操作(Actions) 菜单中搜索 ForEachLoop 。
-
从 Get All Actors Of Class 节点的 执行(Execution) 引脚拖出,并将其插入 For Each Loop 节点的 执行(Exec) 引脚。
-
从 ForEachLoop 节点拖出 数组元素(Array Element) 引脚,然后在 操作(Actions) 菜单中搜索 Get P_Fire 。
-
从 数组元素(Array Element) 引脚拖出,并在 操作(Actions) 菜单中搜索 Get Fire Audio 。
-
从 P Fire 引脚拖出,然后在 操作(Actions) 菜单中搜索 Deactivate 节点。
-
从 火焰音频(Fire Audio) 引脚拖出,并将其连接到 Deactivate 节点的 目标(Target) 引脚。
-
点击 编译(Compile) 和 保存(Save) 。
-
在 内容浏览器(Content Browser) 中,找到 C++类(C++ Classes) > FindingActors ,双击 FindingActorsCharacter 打开
FindingActorsCharacter.h
文件。 -
在 FindingActorsCharacter 类默认值中,声明以下内容:
protected: void OnFindActorPressed();
-
找到
FindingActorsCharacter.cpp
,并添加以下类库:#include "Kismet/GameplayStatics.h" #include "FireEffect.h" #include "Particles/ParticleSystemComponent.h" #include "Components/AudioComponent.h"
IWYU )依赖性模型。这意味着引擎的源代码只包含它需要编译的依赖性。有关更多文档,请参阅 !IWYU 。
-
通过声明以下代码来实现 OnFindActorPressed 的逻辑:
void AFindingActorsCharacter::OnFindActorPressed() { TArray<AActor*> ActorsToFind; if(UWorld* World = GetWorld()) { UGameplayStatics::GetAllActorsOfClass(GetWorld(), AFireEffect::StaticClass(), ActorsToFind); } for (AActor* FireEffectActor: ActorsToFind) { //这是否是类型FireEffect类的Actor? AFireEffect* FireEffectCast = Cast<AFireEffect>(FireEffectActor); if (FireEffectCast) { //获取粒子火焰组件并停用它。 FireEffectCast->GetParticleFireComponent()->Deactivate(); //获取火焰音频组件并停用它。 FireEffectCast->GetFireAudioComponent()->Deactivate(); } } }
-
找到 SetupPlayerInputComponent 方法,并声明以下代码:
void AFindingActorsCharacter::SetupPlayerInputComponent(class UInputComponent* PlayerInputComponent) { PlayerInputComponent->BindAction("FindActorPressed", IE_Pressed, this, &AFindingActorsCharacter::OnFindActorPressed); }
-
编译你的代码。
完成的蓝图
已完成代码
FindingCharacters.h
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Character.h"
#include "FindingActorsCharacter.generated.h"
UCLASS(config=Game)
class AFindingActorsCharacter : 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:
AFindingActorsCharacter();
/** 基础旋转速度,以度/秒为单位。其他单位可能会影响最终旋转速度。*/
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
float BaseTurnRate;
/** 基础向上看/向下看速度,以度/秒为单位。其他单位可能会影响最终速度。*/
UPROPERTY(VisibleAnywhere, BlueprintReadOnly, Category=Camera)
float BaseLookUpRate;
protected:
/** 重置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);
/** 当从玩家(Player)输入组件中按下输入(Input)键时调用 */
void OnFindActorPressed();
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; }
};
最终效果
-
找到 工具栏(Toolbar) ,并点击 运行(Play) ( PIE )。
当按下数字1键时,你应该注意到,火焰效果粒子将熄灭,并且不再听到从音频组件发出的音效。
-
找到 内容浏览器(Content Browser) ,将 BP_FireEffect 的一些实例拖入关卡。
-
找到 工具栏(Toolbar) ,并点击 运行(Play) ( PIE )。
-
当按下数字1键时,你应该注意到,火焰效果粒子将熄灭,并且不再听到从音频组件发出的音效。
通过标签获取特定Actor
你使用了Get All Actors of Class节点来获取指定类的Actor数组。但是,你也可以在Actor上使用 标签(Tags) ,根据不同的条件筛选数组结果,以便从数组中获取特定的Actor或单个Actor。示例,
-
找到 内容(Content)> StarterContent > 蓝图(Blueprints) ,并选择 Blueprint_Effect_Fire 。
-
在 细节(Details) 面板中,找到 标签(Tags) 分段,然后点击 添加(Add) ( + )将标签添加到Actor。
-
在 0 元素字段中,在文本字符串中输入" FindActorTag "。
-
在 MyCharacter 蓝图中,从 ForEachLoop 的 数组元素(Array Element) 引脚拖出,然后在 操作(Actions) 菜单中搜索 Get Tags 。
-
从 标签(Tags) 引脚拖出,然后在 操作(Actions) 菜单中搜索 Get 节点。
-
在图表中 右键点击 ,并在 操作(Actions) 菜单中搜索 Branch 节点。
-
从 Branch 节点的 条件(Condition) 引脚拖出,然后添加 Actor Has Tag 节点。
-
将 Get 节点的 输出(out) 引脚连接到 Actor Has Tag 节点上的 标签(Tag) 引脚。
-
将 ForEachLoop 节点的 数组元素(Array Element) 引脚连接到 Actor Has Tag 节点上的 目标(Target) 引脚。
-
从 ForEachLoop 引脚的 数组元素(Array Element) 拖出两次,获得 P_Fire 和 Fire Audio 节点,并将它们连接到 Deactivate 节点。
-
点击 编译(Compile) 和 保存(Save) 。
-
在 关卡视口(Level Viewport) 中选择你的 Blueprint_FireEffect 之一,然后在 细节(Details)面板 中,找到 标签(Tags) 变量,找到 FindActorTag 字段并打开下拉菜单,然后选择 删除(Delete) 删除标签变量。
为了演示功能,我们特意留下了一个没有标签的火焰效果。
-
找到 工具栏(Toolbar) ,按 运行(Play)(PIE) 。
你使用Gameplay静态库中的Get All Actors of Class函数来获取指定类的Actor数组。但是,你也可以在Actor上使用 标签(Tags) ,根据不同的条件筛选数组结果,以便从数组中获取特定的Actor或单个Actor。示例,
-
首先,找到 内容浏览器(Content Browser) > C++类(C++ Classes) 文件夹,然后双击 FireEffect Actor 打开其
FireEffect.cpp
文件。
-
在 FireEffect构造函数中 实现以下代码
AFireEffect::AFireEffect() { Tags.Add(FName("FindActorTag")); }
注意:标签是数组,是Actor类默认值的一部分,可以用于分组和分类。
-
编译 你的代码。
-
打开 BP_FireEffect ,然后在 细节(Details) 面板中找到 Actor 类别,你会注意到你的Actor标签已创建。
-
首先,找到 内容浏览器(Content Browser) > C++类(C++ Classes) 文件夹,然后双击 FindingActorsCharacter ,打开其
.cpp
文件。
-
在 OnFindActorPressed 方法中实现以下内容:
void AFindingActorsCharacter::OnFindActorPressed() { TArray<AActor*> ActorsToFind; //获取所有具有"FindActorTag"的FireEffect类的Actor UGameplayStatics::GetAllActorsOfClassWithTag(GetWorld(), AFireEffect::StaticClass(), FName("FindActorTag"),ActorsToFind); for (AActor* FireEffectActor: ActorsToFind) { AFireEffect* FireEffectCast = Cast<AFireEffect>(FireEffectActor); if (FireEffectCast) { FireEffectCast->GetParticleFireComponent()->Deactivate(); FireEffectCast->GetFireAudioComponent()->Deactivate(); } } }
-
编译 你的代码。
-
在 关卡视口(Level Viewport) 中选择你的 BP_FireEffect 实例之一,然后在 细节(Details) 面板中找到 标签(Tags) 变量,找到 FindActorTag 字段,打开旁边的下拉菜单删除变量。
-
找到 工具栏(Toolbar) ,按 运行(Play)(PIE) 。
最终效果
当按下数字1键时,你应该注意到,所有带有ActorsToFindTag的Bluprint_Fire_ Effect粒子均熄灭,而没有标签的火焰效果仍然存在。
当按下数字1键时,你应该注意到,所有带有FindActorsTag的BP_FireEffect粒子都熄灭,而没有标签的火焰效果仍然存在。