- Home /
How does Unity retain UnityEngine.Object references?
I was pleasantly surprised when the following logic appears to work without any issues. I was expecting the original game object reference to break (or become null
) but somehow it proceeds to work.
public class MyEditorWindow : EditorWindow {
[MenuItem("Example/My Editor Window")]
public static void Display() {
EditorWindow.GetWindow<MyEditorWindow>();
}
public GameObject referenceToPrefab;
void OnGUI() {
referenceToPrefab = EditorGUILayout.ObjectField(referenceToPrefab, typeof(GameObject), false) as GameObject;
if (GUILayout.Button("Do Something")) {
DoSomething();
EditorGUIUtility.ExitGUI();
}
}
public void DoSomething() {
// Create instance of referenced prefab
GameObject go = PrefabUtility.InstantiatePrefab(referenceToPrefab) as GameObject;
go.hideFlags = HideFlags.HideAndDontSave;
// Change fields/properties of instantiated prefab
go.isStatic = !go.isStatic;
go.tag = "EditorOnly";
// Add a child object
GameObject child = new GameObject("New Child");
child.hideFlags = HideFlags.HideAndDontSave;
child.transform.parent = go.transform;
// Replace original instance of prefab with the changed one
PrefabUtility.ReplacePrefab(go, referenceToPrefab);
DestroyImmediate(go);
// Just for the fun of it, this works! how?
// Remember, this is still the original prefab reference!
Debug.Log(referenceToPrefab.tag); // EditorOnly
}
}
Q1. How does Unity achieve this under the hood?
Q2. Does it use a larger data type for references that keep track of the asset GUID?
Q3. If that is so, does this mean that non UnityEngine.Object
references waste memory?
To me the only way this would seem possible would be if Unity was somehow replacing the previous object instance using the exact same memory address.
I tried to reproduce this using unsafe pointers, but with regular C# you cannot get a pointer to an object reference (aka managed type). Is it possible that Unity is doing something similar?
I would imagine that it is to do with the instance ID that is used by Unity - this does change for us - but internally I imagine it is used to keep permanent references using some magic we don't get to access.
For instance when I keep hold of object references in Unity Serializer I have to use GUIDs that I manage for objects - but internally when the scene is loaded you can also use the InstanceID of any GameObject to track things. Interestingly InstanceIDs are negative for items created at run time and positive for assets and scene objects that are part of the project.
Answer by Kryptos · Jul 07, 2012 at 05:59 PM
The reason is that the garbage collector do not destroy anything immediately. And you're just trying to access a variable which value still exists in memory. (On top of that the value type is a string, which are handled very differently than other type, because they use shared memory).
Try the same but instead of accessing a variable, call a method. You should get an exception.
Nope, methods are still working and seem to reflect the state of the new version of the prefab. The only other alternative is that Unity is perfor$$anonymous$$g a deep copy using $$anonymous$$arshal
... (a class that I have long forgotten)
Answer by davient · Jun 12, 2014 at 09:50 AM
I believe this is because you are now only Destroying the copy of go
created by PrefabUtility.ReplacePrefab
From the documentation: http://docs.unity3d.com/ScriptReference/PrefabUtility.ReplacePrefab.html
PrefabUtility.ReplacePrefab static
GameObject ReplacePrefab(GameObject go, Object targetPrefab, ReplacePrefabOptions options = ReplacePrefabOptions.Default);
Description Replaces the targetPrefab with a copy of the game object hierarchy go.
Therefore:
PrefabUtility.ReplacePrefab(go, referenceToPrefab);
replaces the reference go
with a copy of referenceToPrefab
So running DestroyImmediate(go);
only destroys that copy and referenceToPrefab.tag
remains valid.
Your answer
Follow this Question
Related Questions
Instantiate in Editor 1 Answer
Very Slow (hang) gameobject TO prefab operation with lot of child objects 0 Answers
Why my prefab is auto changing? 3 Answers