FObjectInitializer
用CreateDefaultSubobject创建对象
template
TReturnType* CreateDefaultSubobject
UObject::CreateDefaultSubobject
从当前线程的栈顶弹出ObjInitializer。
调用它的CDSub函数。
FObjectInitializer::CreateDefaultSubobject
子对象不能在UObject构造函数之外创建。UObject构造子对象不能使用new或放置new操作符创建。
调用StaticConstructObject_Internal函数
Defaults对象,指出了该子对象应该怎样复制谁
可以是其原型对象,也可以是其类默认对象
InitProperties函数
这个函数干的事情是将对象的属性全都拷贝一份
遍历的是存储在UClass中的属性列表。
是否是临时子对象
!(是否需要初始化非Native类)&&
属性是否可以用PostConstructLink链进行初始化
不需要初始化非Native类,且可以用PostConstructLink链进行初始化:
不是:遍历从最子类到基类的属性的链表PropertyLink
如果属性不是临时属性,或者即使是临时属性,
但是不持有一个被实例化了的Component的引用
利用内存复制操作,将DefaultData
拷贝一份给当前属性。
是:遍历需要后构造函数初始化的属性链表PostConstructLink
判断该属性是否可以使用PostConstructLink链进行初始化:
不可以:遍历从最子类到基类的属性的链表PropertyLink
如果属性不是临时属性,或者即使是临时属性,
但是不持有一个被实例化了的Component的引用
待初始化的属性是否是临时属性 && 是否允许从类默认对象CDO中拷贝?
是:利用内存复制操作,将CDO
拷贝一份给当前属性
反之:利用内存复制操作,将DefaultData
拷贝一份给当前属性。
可以:遍历需要后构造函数初始化的属性链表PostConstructLink
是否可以使用PostConstructLink链进行初始化
InitSubobjectProperties函数
这个函数会遍历ComponentInitis,对每个子对象
都调用InitProperties,为它们都初始化属性。
UClass::InstanceSubobjectTemplates函数
遍历类中的RefLink列表,对里面的每个属性调用
FProperty : :InstanceSubobjects函数
FProperty下的该函数为空,留给子类实现,
这里我取FObjectProperty为例讲解
调用InstanceGraph->InstancePropertyValue函数
调用GetInstancedSubobject函数
如果返回值不为INVALID_OBJECT
才会使用它来作为属性的新值。
如果源对象不为空,且当前正在实例化的组件也不为空。
是:如果SourceSubobject包含在SourceRoot中,抑或是允许自我引用(比如委托),那么就代表允许实例化
不允许:返回 INVALID_OBJECT
是运行时创建的:返回CurrentValue,即不改变该组件此时的值。
不是运行时创建的:如果该对象应该加载到客户端vs服务器vs编辑器
获取源组件的Outer对应的对象实例SubobjectOuter
某些情况下可能还需要为其递归调用GetInstancedSubobject函数来实例化它
如果是的话,就用StaticFindObjectFast找到的子对象值作为返回值。
(这个返回值可能又在底下判断是否是原型时被改变)
是:返回nullptr
并不是:如果此时返回值并不为空,则调用StaticConstructObject_Internal创建实例组件
没有这个需求:返回CurrentValue
否:返回INVALID_OBJECT
如果搜索到了:
(如果在FObjectInstancingGraph中
搜索到了与该组件模板对应的唯一实例的话)
直接返回搜索到的实例。
如果正在从磁盘加载目的对象树的根对象,且该子对象的类持有其它组件的引用的话
对这个实例调用ConditionalPostLoadSubobjects函数
调用UObject::PostLoadSubobjects函数
否:返回INVALID_OBJECT
Obj->PostInitProperties函数
Class->PostInitInstance(Obj)函数
值得注意的是,一个UObject拥有OuterPrivate,ClassPrivate等属性
但是却不会保存自身的原型对象是什么,也不会保存自身拥有的子对象的引用
想要知道这两项信息都只能通过函数去查找。
FObjectInstancingGraph与FObjectInitializer的关系:
对象初始化器保存有一个对象实例图的成员变量。
而对象实例图中保存了当前对象的所有子对象各自到各自的源对象之间的映射。
相当于是构建了一个对象树中的“对象子树”。 我们上面说到UObject不保存
自身的子对象,父对象这些对象树相关的信息。这里猜测就是用这个对象实例图保存的。
关于初始化和实例化在这里的区别:
初始化属性的时候执行的都是内存复制:这实际上是一种浅复制。
而实例化的时候可能会调用到StaticConstructObject_Internal函数,递归地构造子对象。
这是一种深复制。
作者:知乎-DarkFlameMaster
https://zhuanlan.zhihu.com/p/422510443