UE4 从UProperty到FProperty
UE4 在4.25中,进行了一些非常重要的改进。 其中就有FProperty。
一.老旧的结构体系
UE4中带有前缀U的类是UObject派生类。每个UObject都有一个与之对应的UClass,这个UClass保存了所有的反射系统相关的信息,描述了各个Property之间的内存布局和关系;通过UClass可以遍历所有的序列化属性;通过Object对象的实例化地址就可以将相应的Property的值取出来,进行读写操作。
UClass保留了这个对象的结构信息。它在内部拥有成员的元素列表,例如UFunction,UEnum,UProperty等。它们一起作用来提供“反射”机制。从命名不难看出UClass 和下文中的UProperty,都是从UObject继承而来,主要是为了使用Object的GC功能。
UProperty将变量定义为类的组成部分。这也是我们这次的重点内容。
不管我们是在蓝图中还是在C++中,属性都是由我们的UProperty来指定的。这些属性包括蓝图变量和节点,以及执行节点的返回值。
二.反射
我们将C++编译成exe文件。编译器将C++中的信息翻译成了机器语言。我们本身的函数名称在编译时将会被替换和省略。因此你不能在自己的程序中使用字符串"HogeHogeFunc"来处理任何事情。反射是静态或者动态的去构造这一映射信息,并且在运行时使用他们。UE4是静态反射的。
在UE4中,我们在通过他特殊的宏,将所需要反射的数据进行标记,从而自动的生成供运行时查询的信息。
从而其生成了一些额外的信息。
三.反射案例
四.FProperty
在创建类时,会生成大量属性,包括蓝图类。有些类型将可能有几十万多个UProperty,因为所有的UProperty继承自UObject,因此会产生各种各样的开销。这一特性对整个引擎影响及其广泛,包括额外的内存空间,UProperty构建/销毁成本,垃圾回收性能。
从4.25开始,此UProperty已完全更改为FProperty。 前缀“F”说明其不再继承UObject。UProperty类的定义仍然存在,但它只用于在将早期版本中创建的资源转换为FProperty做一次。
这是4.24的继承关系。
这是4.25的继承关系
由于Field与UObject和UField大多数函数拥有相同的名称,因此当您更新引擎时,只需将其从UxxProperty重命名为FxxProperty即可。
五.改善点
内存消耗减少
在整个应用程序中使用的UObject中内存占用中,Property占40%以上,根据情况也有超过60%的程度。特别是在包含多个函数调用的蓝图很多的情况下。在ThirdPersonTemplate中,UE4.24的UObject合计有5万多个,其中70%左右是Property。这些消耗直接没了。
由于继承了UObject,因此每个属性不再需要超过100个字节的额外内存。 虽然每个容量都是微乎其微的,但由于数量众多,有时会减少数十MByte或更多的内存使用量。
使用宏调用8个BoolProperty返回值的函数2304次。
如前所述,由于不适用NewObject而是C++的New和Delete,因此生成和销毁特性也变得简单和快速。同样,您还可以缩短应用程序的启动时间。
六.结论
4.25 UProperty变成了FProperty
- 继承UObject后的开销不见了
- 提高了引擎启动时间
- GC处理时间明显改善
- 内存使用量的减少
- 打包后包体体积减少