Actor介绍和作用
- Actor类是游戏中一切实体Actor的基类(继承UObject)。
- 代表着游戏中的一个实体或物体。
- 是可见的角色、道具、敌人、NPC、触发器等。
- 可以在游戏世界中被放置、创建和操作。
- 需要挂载组件的时候,你才应该继承自Actor类。
- 运行中通过网络来复制属性和函数调用
Actor的行为表现
- 在游戏世界中的位置(位置矢量)和变换(旋转和缩放)
- 组件系统:Actor由一个或多个组件组成,每个组件代表Actor的一个功能或特性。
- 组件可以附加和管理Actor的行为、外观和交互。
- 通过脚本或视觉蓝图来定义其行为和交互。
- 控制Actor的移动、动画、碰撞、触发事件等,能够响应玩家的输入、与其他Actor进行交互。
- 碰撞和触发器:设置碰撞体积和形状,导致伤害、触发事件或改变游戏状态。
Actor的常用函数
- BeginPlay():第一次被放置到场景中并准备开始游戏时被调用。
- Tick() :它在每一帧中被调用,用于更新 Actor 的逻辑和状态。
- OnActorBeginOverlap() 和 OnActorEndOverlap():碰撞事件的回调函数
- Destroy() :用于销毁当前的 Actor。
- SetActorLocation() 和 SetActorRotation():设置 Actor 的位置和旋转。
- SetActorHiddenInGame() 可以设置 Actor 在游戏中是否隐藏。
- GetWorld() 返回当前 Actor 所属的 World 对象。
- GetOwner() 返回当前 Actor 的所有者 Actor。
- GetActorScale3D() 和 SetActorScale3D() 用于获取和设置 Actor 的缩放值。
Actor的优秀子类
- AStaticMeshActor(内部包含UStaticMeshComponent): 呈现具有实体属性的静态网格模型。
- ACharacter: 继承APawn, 具有角色属性和动画的角色.
- AProjectile: 用于表示游戏中的抛射物或子弹的 Actor 子类
- ATriggerVolume: 继承AVolume, 用于创建触发器区域的 Actor 子类
- APlayerStart:指定玩家初始或重生位置的 Actor 子类
- ACameraActor:(内部包含CameraComponent), 控制摄像机位置、旋转和视角。
Actor的创建
- 创建方式:
- 1 从磁盘加载(Load From Disk): 用于已经在关卡中的Actor(LoadMap, 关卡流送)
- 2 在编辑器PIE中运行: Actor从编辑器中复制而来,并非从磁盘中加载。
- 3 代码生成: 调用 UWorld::SpawnActor(才会有World::OnActorSpawned 回调)
- 4 延迟生成: SpawnActorDeferred 生成流程性Actor,允许在蓝图构建脚本之前进行额外设置。
- 多种创建的Actor的销毁路径是相同的
Actor EndPlay的全部情形:
- 1 对Destroy显式调用。
- 2 "在编辑器中运行(Play in Editor)"终结。
- 3 关卡过渡(无缝行程或加载地图)。
- 4 包含Actor的流送关卡被卸载。
- 5 Actor的生命周期已过。
- 6 应用程序关闭(全部Actor被销毁)。
- Actor将被标记为 RF_PendingKill,在下个垃圾回收周期中,UE会将其从内存中解除。
Actor的回收函数
- UObject::BeginDestroy - 利用此机会释放内存并处理其他多线程资源。大多数Gameplay功能应在EndPlay中处理。
- UObject::IsReadyForFinishDestroy - GC调用,以确定对象是否可以永久解除分配或延迟对象销毁。
- UObject::FinishDestroy - 释放内部数据结构。内存释放前的最后一次调用。
-
销毁和回收
销毁和回收
Actor的组件系统
- Actor包含一个或多个Actor组件
- 组件控制Actor的移动方式,渲染等行为、外观和其他属性。
Actor的创建和配置
- 编辑器中直接摆放
- 通过C++代码运行时动态生成
- 编辑器可见性 和 灵活性和可编程性 不同
- 直接摆放 适合于静态场景布置和设计,对于位置、外观和属性相对固定。
Actor的交互和行为
- DECLARE_EVENT来关心Actor的事件,并进行绑定.
- DECLARE_MULTICAST_DELEGATE 多播委托
- DECLARE_DYNAMIC_MULTICAST 动态多播委托(支持蓝图)
- public 的方法直接调用
Actor的优化和性能
- 包括减少组件数量、使用合适的碰撞设置等。
- 对Actor的生命周期合理管理,避免资源泄漏和性能问题。
#pragma once
#include "CoreMinimal.h"
#include "GameFramework/Actor.h"
#include "Materials/Material.h"
#include "Components/PointLightComponent.h"
#include "Components/SphereComponent.h"
#include "Components/StaticMeshComponent.h"
#include "MyActor.generated.h"
- 头文件包含注意: #include "MyActor.generated.h" 必须在最后一行
UCLASS()
class AMyActor : public AActor
{
GENERATED_BODY()
public:
// 声明事件
DECLARE_EVENT(AMyActor, FMyCrashEvent);
// 外部使用此函数来绑定和广播
FMyCrashEvent& OnCrashed() { return CrashEvent; }
// 事件内部封装
private:
FMyCrashEvent CrashEvent;
// 事件回调函数
UFUNCTION()
void HandleCrashEvent();
public:
AMyActor();
// Called every frame
virtual void Tick(float DeltaTime) override;
UFUNCTION()
void OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor,
class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult);
UFUNCTION()
void OnOverlapEnd(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor,
class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex);
/** 切换光照组件的可见性*/
UFUNCTION()
void ToggleLight();
- 上半部分声明事件和时间的回调函数
- 下半部分声明了tick 和 重叠的开始和结束的委托函数
// Called when the game starts or when spawned
virtual void BeginPlay() override
{
Super::BeginPlay();
UE_LOG(LogTemp, Warning, TEXT("BeginPlay"));
}
virtual void EndPlay(const EEndPlayReason::Type EndPlayReason) override
{
Super::EndPlay(EndPlayReason);
UE_LOG(LogTemp, Warning, TEXT("EndPlay"));
}
virtual void BeginDestroy() override
{
Super::BeginDestroy();
UE_LOG(LogTemp, Warning, TEXT("BeginDestroy"));
}
virtual void FinishDestroy() override
{
Super::FinishDestroy();
UE_LOG(LogTemp, Warning, TEXT("FinishDestroy"));
}
- Actor的主要重载函数和执行顺序
/// <summary>
/// Actor的成员对象
/// </summary>
public:
// 点光源组件
UPROPERTY(VisibleAnywhere, Category = "Switch Components")
class UPointLightComponent* PointLight1;
/** 点光源的光照强度 */
UPROPERTY(VisibleAnywhere, Category = "Switch Variables")
float DesiredIntensity;
// 球体碰撞体组件
UPROPERTY(VisibleAnywhere, Category = "Switch Components")
class USphereComponent* Sphere1;
// 静态网格体组件
UPROPERTY(VisibleAnywhere, Category = "Switch Components")
class UStaticMeshComponent* MeshComponent1;
};
- 本Actor的成员对象
AMyActor::AMyActor()
{
PrimaryActorTick.bCanEverTick = true;
// 光源强度
DesiredIntensity = 3000.0f;
// 创建点光源(create,SetVisibility,RootComponent相关)
PointLight1 = CreateDefaultSubobject<UPointLightComponent>(TEXT("PointLight1"));
PointLight1->Intensity = DesiredIntensity;
PointLight1->SetVisibility(true);
// 设为根组件
SetRootComponent(PointLight1); // RootComponent = PointLight1;
// 创建静态网格体组件(先设StaticMesh,再设置材质)
MeshComponent1 = CreateDefaultSubobject<UStaticMeshComponent>(TEXT("MeshComponent"));
// 查询和设置网格
static ConstructorHelpers::FObjectFinder<UStaticMesh> DefaultMeshAsset(TEXT("/Engine/BasicShapes/Sphere"));
if (DefaultMeshAsset.Succeeded())
{
MeshComponent1->SetStaticMesh(DefaultMeshAsset.Object);
}
// 查询和设置材质
static ConstructorHelpers::FObjectFinder<UMaterial> DefaultMaterialAsset(TEXT("/Engine/EngineMaterials/ScreenMaterial"));
if (DefaultMaterialAsset.Succeeded())
{
UMaterial* DefaultMaterial = (UMaterial*)DefaultMaterialAsset.Object;
MeshComponent1->SetMaterial(0, DefaultMaterial);
}
// 附加到根组件
MeshComponent1->SetupAttachment(RootComponent);
MeshComponent1->SetVisibility(true);
// 创建球形碰撞体
Sphere1 = CreateDefaultSubobject<USphereComponent>(TEXT("Sphere1"));
Sphere1->InitSphereRadius(250.0f);
Sphere1->SetupAttachment(RootComponent);
Sphere1->SetVisibility(true);
// 注册进入和离开重叠时的回调
Sphere1->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnOverlapBegin);
Sphere1->OnComponentEndOverlap.AddDynamic(this, &AMyActor::OnOverlapEnd);
// 关心碰撞事件
OnCrashed().AddUObject(this, &AMyActor::HandleCrashEvent); // C++
OnCrashed().AddUFunction(this, FName("HandleCrashEvent")); // todo 测试蓝图
}
- 构造函数中创建和添加组件
- 注册碰撞的进入和离开回调
- 注册碰撞事件的回调函数 X 2
void AMyActor::OnOverlapBegin(class UPrimitiveComponent* OverlappedComp, class AActor* OtherActor,
class UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult)
{
if (OtherActor && (OtherActor != this) && OtherComp)
{
ToggleLight();
}
OnCrashed().Broadcast();
}
// 碰撞处理事件
void AMyActor::HandleCrashEvent()
{
UE_LOG(LogTemp, Warning, TEXT("HandleCrashEvent be Called"));
}
- 碰撞开始的函数执行,并广播自定义事件:碰撞处理事件
网友评论