【转载】UE4 从 UProperty 到 FProperty

847 阅读3分钟

版权声明:本文为CSDN博主「Papals」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。

原文链接:blog.csdn.net/qq_23030843…

UE4 在 4.25 中,进行了一些非常重要的改进。 其中就有 FProperty

一. 老旧的结构体系

image.png

UE4 中带有前缀 U 的类是 UObject 派生类。每个 UObject 都有一个与之对应的 UClass

  • 这个 UClass 保存了所有的反射系统相关的信息,描述了各个 Property 之间的内存布局和关系
  • 通过 UClass 可以遍历所有的序列化 Property
  • 通过 Object 对象的实例化地址就可以将相应的 Property 的值取出来,进行读写操作

image.png

UClass 保留了这个对象的结构信息。它在内部拥有成员的元素列表,例如 UFunctionUEnumUProperty 等。它们一起作用来提供 “反射” 机制。从命名不难看出 UClass 和下文中的 UProperty,都是从 UObject 继承而来,主要是为了使用 Object 的 GC 功能。

image.png

UProperty 将变量定义为类的组成部分。这也是我们这次的重点内容。

image.png

不管我们是在蓝图中还是在 C++ 中,属性都是由我们的 UProperty 来指定的。这些属性包括 蓝图变量节点 ,以及 执行节点的返回值

image.png

二. 反射

我们将 C++ 编译成 exe 文件。编译器将 C++ 中的信息翻译成了机器语言。我们本身的函数名称在编译时将会被替换和省略。因此你不能在自己的程序中使用字符串 "HogeHogeFunc" 来处理任何事情。反射是静态或者动态的去构造这一映射信息,并且在运行时使用他们。UE4 是静态反射的。

image.png

image.png

在 UE4 中,我们在通过他特殊的宏,将所需要反射的数据进行标记,从而自动的生成供运行时查询的信息。

image.png

从而其生成了一些额外的信息。

image.png

image.png

三. 反射案例

image.png

image.png

四. FProperty

在创建类时,会生成大量属性,包括蓝图类。有些类型将可能有几十万多个 UProperty,因为所有的 UProperty 继承自 UObject,因此会产生各种各样的开销。这一特性对整个引擎影响及其广泛,包括额外的内存空间UProperty 构建/销毁成本垃圾回收性能

从 4.25 开始,此 UProperty 已完全更改为 FProperty。 前缀 “F” 说明其不再继承UObjectUProperty 类的定义仍然存在,但它只用于在将早期版本中创建的资源转换为FProperty 做一次。

这是 4.24 的继承关系。

image.png

这是 4.25 的继承关系

image.png

由于 Field 与 UObjectUField 大多数函数拥有相同的名称,因此当您更新引擎时,只需将其从 UxxProperty 重命名为 FxxProperty 即可。

image.png

五. 改善点

内存消耗减少

在整个应用程序中使用的 UObject 中内存占用中,Property 占 40% 以上,根据情况也有超过 60% 的程度。特别是在包含多个函数调用的蓝图很多的情况下。在 ThirdPersonTemplate 中, UE 4.24 的 UObject 合计有 5 万多个,其中 70% 左右是 Property 。这些消耗直接没了。

image.png

由于继承了 UObject,因此每个属性不再需要超过 100 个字节的额外内存。 虽然每个容量都是微乎其微的,但由于数量众多,有时会减少数十 MB 或更多的内存使用量。

使用宏调用 8 个 BoolProperty 返回值的函数 2304 次。

image.png

image.png

如前所述,由于不适用 NewObject 而是 C++ 的 NewDelete,因此生成和销毁特性也变得简单和快速。同样,您还可以缩短应用程序的启动时间。

image.png

image.png

六. 结论

4.25 UProperty 变成了 FProperty

  • 继承 UObject 后的开销不见了
  • 提高了引擎启动时间
  • GC 处理时间明显改善
  • 内存使用量的减少
  • 打包后包体体积减少