Use case 1: Link between gameobjects in scene
--- !u!1 &330585543 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component:
Transform data:
--- !u!4 &330585546 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 330585543} m_LocalRotation: {x: 0, y: 0, z: 0, w: 1} m_LocalPosition: {x: 0, y: 1, z: -10} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children:
--- !u!4 &1429936258 Transform: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} m_GameObject: {fileID: 1429936256} -> This refers to the transform's gameobject data reference m_LocalRotation: {x: -0, y: -0, z: -0, w: 1} m_LocalPosition: {x: 0.2898221, y: -23.73114, z: -48.733814} m_LocalScale: {x: 1, y: 1, z: 1} m_ConstrainProportionsScale: 0 m_Children: [] m_Father: {fileID: 330585546} m_RootOrder: 0 m_LocalEulerAnglesHint: {x: 0, y: 0, z: 0}
--- !u!1 &1429936256 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component:
Now, we have a link between the gameobject and the transform and their children. So for game object the children link are found using the transform data. So the way to traverse is: GameObject -> Transform -> Children -> -> Transform -> GameObject, now we append the gameobject1 child info with the gameobject2. This is the way to traverse the hierarchy to find the parent-child relationship between scene objects.
Use case 2:
Prefab in root, with no children & no overrides:
--- !u!1001 &1482527665 PrefabInstance: m_ObjectHideFlags: 0 serializedVersion: 2 m_Modification:
m_TransformParent: {fileID: 0}
m_Modifications:
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 61c90d4029
, type: 3}
There are no additional artifacts that unity generates, so in this use case, since the 'm_TransformParent' is 0, the prefab is in the root of the scene, with no custom scene objects as children + no overrides.
Use case 3:
Prefab in root with overrides:
--- !u!1001 &1482527665
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_SourcePrefab: {fileID: 100100000, guid: 61c90d4029
, type: 3}
--- !u!1 &1482527666 stripped
GameObject:
m_CorrespondingSourceObject: {fileID: 5118133154516674719, guid: 61c90d4029
,
type: 3}
m_PrefabInstance: {fileID: 1482527665}
m_PrefabAsset: {fileID: 0}
--- !u!65 &1482527667
BoxCollider:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
m_GameObject: {fileID: 1482527666}
m_Material: {fileID: 0}
m_IsTrigger: 0
m_Enabled: 1
serializedVersion: 2
m_Size: {x: 1, y: 1, z: 1}
m_Center: {x: 0, y: 0, z: 0}
Here in this use case, prefab has a override of a box collider, in that case unity would generate a ghost gameobject with prefab instance reference, where the box collider would have reference of gameobject. The way to note this is to identify if the gameobject data is stripped, then ideally just assume that the gameobject is a ghost created for prefab. It wouldn't have components list of identify the components that are attached on this prefab. So, we iterate through components which have m_GameObject and identify gameobject, and then implicitly see if the gameobject is stripped, then we identify its prefab instance.
Use case 4:
Prefab with a scene object as child:
--- !u!1001 &1482527665
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 61c90d4029
, type: 3}
--- !u!4 &1482527666 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 7908724477659422290, guid: 61c90d4029
,
type: 3}
m_PrefabInstance: {fileID: 1482527665}
m_PrefabAsset: {fileID: 0}
--- !u!1 &309364077
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
Here, the prefab has a child which is a scene object called cube. Here note, a ghost transform is generated against the prefab. The way the link works is the Cube (GameObject) -> Cube (Transform) -> Check m_Father property -> Find related transform -> See if the transform property is stripped -> If stripped, then it is a ghost. Since we identified it is a ghost, we find the transform's 'm_PrefabInstance' and identify what is the prefab instance that this transform is related to. Now due to this, we can identify that this is a prefab with a scene object (Cube) as child.
Use case 5:
Prefab with a prefab as child:
--- !u!1001 &1482527665
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 0}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 61c90d4029
, type: 3}
--- !u!4 &1482527666 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 7908724477659422290, guid: 61c90d4029
, type: 3}
m_PrefabInstance: {fileID: 1482527665}
m_PrefabAsset: {fileID: 0}
--- !u!1001 &617805067
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 1482527666}
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 7cf72a5773
, type: 3}
Here one prefab instance has reference of another prefab instance. Here, the way we identify the relationship is by finding the 'm_TransformParent' property. If it is not 0, then it means the prefab has a parent. If we check the parent, which is linked to a stripped transform, we know that the transform is related to a prefab. We can then find the prefab instance. This is the way to traverse the prefab hierarchy.
Use case 6:
Prefab with scene object as parent:
--- !u!1001 &1482527665
PrefabInstance:
m_ObjectHideFlags: 0
serializedVersion: 2
m_Modification:
m_TransformParent: {fileID: 491276561}
m_Modifications:
m_RemovedComponents: []
m_SourcePrefab: {fileID: 100100000, guid: 61c90d4029
, type: 3}
--- !u!4 &1482527666 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 7908724477659422290, guid: 61c90d4029
,
type: 3}
m_PrefabInstance: {fileID: 1482527665}
m_PrefabAsset: {fileID: 0}
--- !u!1 &491276560
GameObject:
m_ObjectHideFlags: 0
m_CorrespondingSourceObject: {fileID: 0}
m_PrefabInstance: {fileID: 0}
m_PrefabAsset: {fileID: 0}
serializedVersion: 6
m_Component:
Here while parsing through gameobject, if we identify, the trasform has a child, and that child's transform is stripped, that means, the transform is related to a prefab. We can then find the prefab instance. This is the way to traverse the prefab hierarchy.
Use case 7:
Prefab with the scene object as child for one of the prefab's children:
--- !u!1 &5604345 GameObject: m_ObjectHideFlags: 0 m_CorrespondingSourceObject: {fileID: 0} m_PrefabInstance: {fileID: 0} m_PrefabAsset: {fileID: 0} serializedVersion: 6 m_Component:
874028b39d
, type: 3}
--- !u!4 &920412709 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 8145956705230478064, guid: 874028b39d
,
type: 3}
m_PrefabInstance: {fileID: 920412706}
m_PrefabAsset: {fileID: 0}To identify the parent child relationship, where the father of a scene object is prefab and that object can be 'n'th child of the prefab, we use the following steps:
Step 1: Find "PEACE" and its Parent in SampleScene.unity
First, we locate the "PEACE" GameObject in the scene file to find its direct parent.
--- !u!4 &5604346 Transform: # ... m_GameObject: {fileID: 5604345} m_Father: {fileID: 920412709} m_RootOrder: 0
- Parent ID: The m_Father is 920412709.
- Sibling Index: The m_RootOrder is 0.
This gives us the last number in our sequence: (?-?-0).
Step 2: Identify the Parent (920412709) in SampleScene.unity
Now, we look for the object with ID 920412709 in the scene file.
--- !u!4 &920412709 stripped
Transform:
m_CorrespondingSourceObject: {fileID: 8145956705230478064, guid: 874028b39d
, type: 3}
m_PrefabInstance: {fileID: 920412706}
m_PrefabAsset: {fileID: 0}
Step 3: Find the Corresponding Transform in Parent.prefab
We now switch to the Parent.prefab file and search for the Transform with ID &8145956705230478064.
--- !u!4 &8145956705230478064 Transform: # ... m_GameObject: {fileID: 1790231484505338027} m_Father: {fileID: 1455291841571425918} m_RootOrder: 0
This gives us the second number in our sequence: (?-0-0).
Step 4: Find the Next Parent (1455291841571425918) in Parent.prefab
We continue up the hierarchy within the prefab file, looking for the Transform with ID &1455291841571425918.
--- !u!4 &1455291841571425918 Transform: # ... m_GameObject: {fileID: 8435291834557686729} m_Father: {fileID: 6729460392160249717} m_RootOrder: 0
This gives us the first number in our sequence: (0-0-0).
Final Verification: The Prefab Root
To be certain, we can check the final parent, Transform &6729460392160249717.
--- !u!4 &6729460392160249717 Transform:
m_GameObject: {fileID: 5669290172027642543} m_Father: {fileID: 0} m_RootOrder: 0
Its m_Father is {fileID: 0}, which signifies that it is the root Transform of the prefab, as it has no parent. Its GameObject (5669290172027642543) is named "Parent".
By parsing the files and following the m_Father and m_RootOrder references, we have programmatically confirmed that the deep sibling index of the "PEACE" GameObject is indeed (0-0-0).
Conclusion:
So essentially, it is beneficial to resolve the parent-child relationship between normal game objects in the scene using m_Parent logic. Whenever, we deal with a prefab instance, we create a relationship of child-parent between the prefab instance and it's found normal scene object parent. The transforms can be stripped out of the prefab instances in the final output, since the relationship is already resolved. In instances where a scene object has a prefab as a parent, we add the deep sibling index json property, which exactly tells where does the scene object exist in the prefab hierarchy within scene. So irrespective of which sibling index's child the scene object is, we add it always to the root of the prefab data object and add children with the deep sibling index data. Finally, one more pass of run through in the left over data, to see if any gameobject is missed out, then they are marked as orphans and exported. Now, since this is done, we append the components name to the component section of every gameobject that has been identified and created a virtual tree out of. Ultimately, we parse through our collated data, and find the m_RootObjects in the root objects found and sort the objects in root based on them. Note: When extracting information from prefab's modification, check if it has value of 'm_IsActive' in 'm_Modifications' inside m_Modification object of PrefabInstance, we need only this value and 'm_RemovedComponents' property to be exported from the prefab instance.