unity core-prefab

添加prefab:

添加一个组件到prefab,需要通过将组件对应的对象存在磁盘种后,再标记为prefab的一个部分。这部分在prefab.cpp中

prefab删除

prefab删除一个对象的方式是分两种情况,第一种就是这个对象再prefab中还存在则通过放到PrefabModification::RemovedComponents的移除对象池中,并设置prefab是脏的状态。在之后的状态下移除。另一种就是missing的情况下通过BaseObject的DestroySingleObject来移除。他是通过加锁后在另一个线程删掉object的。

BaseObject的删除过程。

存储:

当要保存prefab的时候会执行PrefabCreation.cpp的SavePrefab_Internal。首先他会寻找是否存在这个名字和路径下的prefab了,如果存在会先删掉。

然后分几种情况保存,一个是在assets中的,一个在实例化树中的,还有一种在失去关联的时候保存的。

然后创建id和meta

然后保存的时候分两种情况。

一种是在实例化树中保存的或者是失去关联关系的,这种情况下直接拷贝出副本来执行。

另一种是在assets里保存的,这种他要在PersistentManager::GetInstanceIDsAtPath中遍历所有文件

找到所有相关的prefab都设置一遍

然后让实例化出来的prefab执行awake并且刷新属性,

然后会对克隆出来的对象设置属性。

在InheritGameObjectAndTransformProperties设置属性,包括gameobject属性,component属性以及transform属性

然后在InheritMonoBehaviours中保存脚本数据

然后把克隆的数据写objectsToWrite中,

最后写object,实际就是序列化文件。

prefab的实例化:

在PrefabInstance.cpp中实现。实例化就相当于放在了场景中,这一步是需要拷贝源prefab的,在保存prefab的时候也会执行

将位置,大小,锚定点之类的拷贝一份到实例化文件。如果prefab源文件保存,这些实例化的文件需要重新awake,然后会更新数据。

Instance回滚:

instance还有回滚功能,在prefabInstance的RevertPrefabInstance实现,也就是在撤销的时候处理,先通过传进来的object转到prefabinstance来确定是否属于prefabinstance,通过GetObjectDataArrayFromPrefabRoot来收集哪些是已有的哪些是新增的,RevertInstantiatedAssetReferencesToParentObject回滚使用的material。

然后首先通过std::reverse逆转addObjects,然后对数据一个一个删除。最后通过RevertAllButDefaultPrefabOverrides来回滚rootTransform,rootRectTransform和rootGO。

如果是没链接上的则直接链接上的对象就可以了。他链接上的方法是找到源prefab,然后赋值一下prefab数据。

链接prefab:

在启动场景的时候,构建app的时候,保存场景的时候都会链接prefab,比如在启动场景时执行LoadSceneOperation::CompleteAwakeSequence(),在editor下会会执行UnpackAllPrefabInstances

到PrefabConnection.cpp里执行UnpackAllPrefabInstances,获取所有prefab的实例,并对每个进行解压,

如果这个prefab是属于kPrefabUnpackMode_OuterRoot,也就是解析外层的模式下则执行TransferModifiedPropertiesForUnpack,执行到TransferModifiedPropertiesFromNestedInstancesInAssetToNewInstancesForUnpack。这里主要对prefab被修改的部分修正。

然后kPrefabUnpackMode_OuterRoot模式执行TransferRemovedComponentsForUnpack,执行到TransferRemovedComponentsFromNestedInstancesInAssetToNewInstancesForUnpack,对需要移除的对象放到移除队列。

猜你喜欢

转载自blog.csdn.net/llsansun/article/details/126652657