UE_C++ —— Objects

扫测资讯 2025-02-08 00:07   109 0

目录

一,UCLASS 宏

二,Properties 和 Function 类型

三,UObject 创建

四,UObjects 提供的功能

五,Unreal Header Tool

六,头文件格式

七,Updating Objects

八,Destroying Objects


引擎所有对象的基类都是 UObject UCLASS 宏用于标记UObject的子类,以便UObject handling system识别它们;

一,UCLASS 宏

UCLASS 宏为 UObject 提供了一个 UCLASS 引用,用于描述它在虚幻引擎中的类型(Unreal-based typ);每个 UCLASS 都保留一个CDO( Class Default Object )的对象;CDO 本质上是一个默认"模板"对象,由类构建函数生成,之后就不再修改;

可为指定对象获取其 UCLASS 和 CDO,通常它们都是只读类型;使用 GetClass() 函数即可随时访问对象实例的 UCLASS ;

UCLASS 包含定义类的属性properties和函数functions,是标准C++代码可用的普通C++变量和函数,但被引擎特定的元数据所标记(控制在对象系统中的行为);

注,UObject 类还可包括仅限本地的属性(没有用 UFUNCTION 或者 UPROPERTY 标识符标记用于反射),仅被specifier宏标记的函数和属性会被列举在对应的 UCLASS 中;

二,Properties 和 Function 类型

UObjects 可有成员变量(properties)或任意类型的函数,为便于引擎识别和操纵这些变量和函数,需以特殊的宏来标记并符合一定类型的标准;

三,UObject 创建

UObjects 不支持构造器参数,所有的C++ UObject都会在引擎启动的时候初始化,引擎会调用其默认构造器;如没有默认的构造器,那么 UObject 将不会编译;

UObject 构造器应该轻量化,仅用于设置默认值和子对象,构造时不应该调用其它功能;对于Actor和Actor组件,初始化功能应该输入 BeginPlay() 方法;

UObjects 应该仅在运行时使用 NewObject 构建,或者将 CreateDefaultSubobject 用于构造器;

NewObject<class> 使用所有可用创建选项的可选参数创建一个新实例;
CreateDefaultSubobject<class> 创建一个组件或者子对象,可提供创建子类和返回父类的方法;

注,UObjects不要使用new操作符,所有的UObjects都应由引擎管理内存和垃圾回收;

四,UObjects 提供的功能

此系统的使用不强制要求,甚至有时不适合使用,但却存在以下益处:

  • 垃圾回收
  • 引用更新
  • 反射
  • 序列化
  • 默认属性变化自动更新
  • 自动属性初始化
  • 自动编辑器整合
  • 运行时类型信息可用
  • 网络复制

注,大部分益处适用于 UStructs(有与UObject 一样的反射和序列化能力);UStruct 被当作数值类型处理并且不会垃圾回收;

五,Unreal Header Tool

为利用 UObject 派生类型所提供的功能,需要在头文件上为这些类型执行一个预处理步骤,以核对需要的信息;该预处理步骤由 UnrealHeaderTool(简称 UHT)执行;UObject 派生的类型需要遵守特定的结构;

六,头文件格式

UObject 在源(.cpp)文件中的实现与其他 C++ 类相似,其在头(.h)文件中的定义必须遵守特定的基础结构,以便在引擎中正常使用;使用编辑器的"New C++ Class"命令是设置格式正确头文件的最简单方法;

UObject 派生类的基础头文件可能看起来与此相似,假定 UObject 派生物被称为 UMyObject,其创建时所在的项目被称为 MyProject:

#pragma once

#include 'Object.h'
#include 'MyObject.generated.h' //此行预计为最后一个#include指令,如头文件需要知道其他类,可在文件中的任意位置提前声明或在 MyObject.generated.h 上;

UCLASS() //使引擎能识别 UMyObject,支持大量参数类说明符(确定类功能开关);
class MYPROJECT_API UMyObject : public UObject //将UMyObject类公开到其他模块,则需要指定 MYPROJECT_API
{
	GENERATED_BODY() //此宏不获取参数,但会对类进行设置,以支持引擎要求的基础结构;所有UCLASS和USTRUCT均有此要求

};

七,Updating Objects

Ticking 代表虚幻引擎中对象的更新方式,所有Actors均可在每帧被 tick,便于执行必要的更新计算或操作;

Actor 和 Actor组件在注册时会自动调用它们的 Tick 函数,然而, UObjects 不具有内建的更新能力;在必须的时候,可以使用 inherits 类说明符从 FTickableGameObject 继承即可添加此能力; 这样即可实现 Tick() 函数,引擎每帧都将调用此函数;

注,大部分游戏内对象都是Actor ,可以按用户设置的最短间隔tick,而不是每帧tick;

八,Destroying Objects

对象不被引用后,垃圾回收系统将自动进行对象销毁;这意味着没有任何 UPROPERTY 指针、引擎容器、 TStrongObjectPtr 或类实例会拥有任何对它的强引用;

垃圾回收器运行时,未引用对象将被从内存中移除;此外,函数 MarkPendingKill() 可在对象上直接调用。此函数将把指向对象的所有指针设为 NULL ,并从全局搜索中移除对象;对象将在下一次垃圾回收过程中被完全删除;

  • Object->MarkPendingKill() 已被 Obj->MarkAsGarbage() 所替代;这个新的函数现在仅用于追踪旧对象;如果 gc.PendingKillEnabled=true ,那么所有标记为 PendingKill 的对象会被垃圾回收器自动清空并销毁;

  • 强引用会将 UObject 保留;如果不想让这些引用保留 UObject,那么这些引用应该转换来使用弱指针,或者变为一个普通指针由程序员手动清除(如对性能有较高要求的话);

  • IsValid() 用于检查它是 null 还是垃圾,但是大部分情况下 IsValid 可以被更正规的编程规则替换,比如在调用 OnDestroy 事件时将指针清除至 Actor;

  • 如禁用了 PendingKill() MarkGarbage() 将会提醒对象的所有者该对象将要被销毁,但是对象本身直到所有对它的引用都解除之后才会被垃圾回收;

  • 对于 Actor,即使 Actor 被调用了 Destroy() ,并且被从关卡中移除,它还是会等到所有对它的引用都解除之后才会被垃圾回收;

  • 已有的用于 nullptr 的检查应该被 IsValid() 调用所替代,除非进行手动清除,因为指针不再会被垃圾回收器通过 MarkPendingKill() 自动清除;