# Objects
Unreal有一个完备的系统来处理游戏对象,在Unreal中的所有对象的基类都是UObject。UCLASS宏可被用来标记从UObject继承的类,所以这个类能被UObject处理系统处理。
# UCLASS宏
UClASS宏让UObject能引用一个UCLASS,UCLASS是用来描述Unreal基类型的类,每个UCLASS都有一个称为"Class Default Object"的对象,简称为CDO。CDO是很重要的一个"模板"对象,由构造函数生成之后就不会改变了。UCLASS和CDO都可以恢复一个对象实例,但是它们一般被认为是只读的。一个对象实例的UCLASS可在任何时候通过GetClass()获取。
一个UCLASS包含了定义一个类的所需的属性和函数。可以使用原生C++正常函数和变量,但是如果使用Unreal指定元信息标记的,就可以在对象系统中控制它们的行为。
注意一个UObject类可以包括在UCLASS中并没有对应的原生属性。
# 属性和函数
UObject可以有很多成员变量(比如属性)或任意类型的函数。但是,为了让Unreal识别和操作这些变量或函数,必须使用特殊宏来标记它们,而且得遵从某些类型标准。
# 创建对象
有几种方法来创建UObject实例:
方法 | 描述 |
---|---|
NewObject<Class> | 从所有可用的选项中使用可选参数来创建实例,提供更大的灵活性。 |
new | 在一个较低的环境中构建对象,比如当构造器中需要参数时。 |
# UObjects提供的函数
并不是在所有的场景中都需要或者合适使用这个系统,但还是能做很多有用的事,包括:
- 垃圾回收
- 更新引用
- 反射
- 序列化
- 默认属性的自动更新
- 属性自动序列化
- 自动集成编辑器
- 运行时的类型信息
- 网络复制
# Unreal头文件工具
为了使用由UObject派生的类所继承的函数,需要在头文件处添加一步预处理,以核对所需信息,这步是通过UnrealHeaderTool(UHT)执行的。
UObject派生的类型有一种结构体,后面再说这个。
# 头文件格式
尽管一个UObject会在cpp文件中像其他C++类一样实现,它在头文件中的定义必须依附某个结构体来让它在Unreal中工作正常,使用编辑器的"New C++ Class"命令是最容易建立正确头文件格式的方法。一个派生于UObject类的基本头文件可能像下面这样,假设这个类被命名为UMyObject,它所在的工程是MyProject:
#pragma once
#include 'Object.h'
#include 'MyObject.generated.h'
/**
*
*/
UCLASS()
class MYPROJECT_API UMyObject : public UObject
{
GENERATED_BODY()
};
2
3
4
5
6
7
8
9
10
11
12
13
14
Unreal相关的部分是:
#include "MyObject.generated.h"
这行需要是头文件中#include指令里的最后一条,如果这个头文件需要知道其他类,它们可在文件中任何地方向前声明,或在包含MyObject.generated.h之前包含该文件。
UCLASS()
UCLASS宏让UMyObject类对Unreal是可见的,这个宏支持很多类说明符,能开启或关闭一些特性:
class MYPROJECT_API UMyObject : public UObject
如果MyProject工程希望把UMyObject类暴露给其他模块,指定MYPROJECT_API是很有必要的。这对于模块或插件是很有用的,因为它们会被游戏工程包含,需要故意暴露类在跨多个项目时来提供可解耦的工具函数库。
GENERATED_BODY()
这个宏不接收参数,但可以让类支持引擎要求的基础架构,所有的UCLASS都需要它。
# 更新对象
在Unreal中Ticking涉及到对象的更新,所有的对象有能力在每一帧tick,这让你来执行更新计算以及必要的动作。
对象并没有任何内置的更新能力,但是,这个能力可在需要的时候使用inherits类说明符继承自FTickableGameObject类。然后他们可以实现Tick()函数,这会被引擎在每一帧调用。注意游戏中的大部分对象都是Actors,它可在用户设置的最小间隔而不是非得在每一帧时Tick。
# 销毁对象
注意无论对象是否被垃圾回收,弱指针对它都没有影响。
在对象不再被变量引用时,对象会被垃圾回收系统自动销毁,这意味着没有UPROPERTY指针,或者引擎容器,或者智能指针实例有该对象的引用。当垃圾回收运行时,没有被引用的对象会被删除,另外,可在对象上直接调用MarkPendingKill()函数,这会让所有指向该对象的指针都设置为NULL,也会从全局搜索中移除对象,这样,对象会在下一次垃圾回收时被完全删除。