UE4 UPROPERTY与反射、垃圾回收
为了搞清楚加不加 UPROPERTY
有什么区别,查阅了很多和 UPROPERTY
有关的资料,官方文档和社区维基提到跟反射以及垃圾回收有关系,而很多教学视频和文章都只是在介绍 UPROPERTY
的说明符怎么用……
反射
反射是指计算机程序在运行时可以访问、检测和修改它本身状态或行为的一种能力。
相关:
- 反射式编程 - 维基百科
- 为什么语言里要提供「反射」功能?
- Programming Concepts: Type Introspection and Reflection - Aaron Krauss
- Unreal Property System (Reflection)
UE4使用其自己的反射实现来支持动态功能,如垃圾回收、序列化、网络复制和蓝图/C++通信。这些功能是可选的,意味着您必须将正确的标记(如 UCLASS()
、 UPROPERTY()
等)添加到类型,否则虚幻将忽略它们,而不会为它们生成反射数据。
垃圾回收
在UE4垃圾回收程序中,有一个概念叫做根集。该根集基本上是一个对象列表,这些对象是回收程序知道将不会被垃圾回收的对象。只要根集中的某个对象到一个对象存在引用路径,就不会对所涉及对象进行垃圾回收。如果某个对象不存在到根集的此类路径,则称为无法访问,将会在下次运行垃圾回收程序时将其回收(删除)。引擎按特定的时间间隔运行垃圾回收程序。
相关:
UPROPERTY
UPROPERTY
标记的变量将被纳入虚幻引擎的反射系统。
如果需要序列化(例如保存游戏时要记录的数据)、网络复制(例如多人游戏时服务器要发送给客户端的数据)或者蓝图/C++通信(例如在蓝图中编辑),那么应该为变量添加 UPROPERTY
。
如果不需要上述的功能,那么应该考虑垃圾回收。对于弱引用(也就是说,有一个指向对象的引用,但并不拥有该对象,因此不负责管理该对象的生命周期),可以使用 TWeakObjectPtr
,而不需要添加 UPROPERTY
。对于强引用,则应该添加 UPROPERTY
。
关于强引用使用 UPROPERTY
的情况,不同的类型又有些许不同的作用:
- 非
Actor*
和ActorComponent*
类型的对象:添加UPROPERTY
的作用是将它们添加到根集中。否则,由于它们不是根集的一部分,垃圾回收程序可能会检测到这些对象无法访问,并将其销毁,导致指针变成悬空指针。 Actor*
和ActorComponent*
类型的对象:虽然它们直接链接到根集上,但是为了在它们被销毁时将引用它们的指针置为空指针,仍然需要添加UPROPERTY
。
如果对象是容器类型则需要根据存储的对象来判断是否需要为容器添加 UPROPERTY
。
相关:
UE4 UPROPERTY与反射、垃圾回收
https://dullsword.github.io/2021/12/26/UE4-UPROPERTY与反射、垃圾回收/