24 UE5 AActor简介

Actor介绍和作用

  • Actor类是游戏中一切实体Actor的基类(继承UObject)。
  • 代表着游戏中的一个实体或物体。
  • 是可见的角色、道具、敌人、NPC、触发器等。
  • 可以在游戏世界中被放置、创建和操作。
  • 需要挂载组件的时候,你才应该继承自Actor类。
  • 运行中通过网络来复制属性和函数调用
image.png

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"));
}

  • 碰撞开始的函数执行,并广播自定义事件:碰撞处理事件
最后编辑于
?著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,029评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,238评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,576评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,214评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,324评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,392评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,416评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,196评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,631评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,919评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,090评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,767评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,410评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,090评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,328评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,952评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,979评论 2 351

推荐阅读更多精彩内容