I had run into a situation while working on an editor tool. I needed to reference GameObjects in a scene across editing sessions in a weird way. So, if I have a reference to a scene object, open a new scene, then reopen the original scene, my reference was broken because it’s actually a new instance of the object.
If you put the inspector into debug mode, you can see the Local Identifier In File field under the Instance ID. This integer stays the same across editing sessions. But, as detailed here in a feedback request by D-Lask, there’s no function to get that ID for scene objects: http://feedback.unity3d.com/suggestions/scene-object-local-file-id-from-instance-id
UnityEditor.Unsupported.GetLocalIdentifierInFile(int instanceId) always returns zero for scene objects just like D-Lask says.
After some digging, though, I came up with this.
PropertyInfo inspectorModeInfo =
typeof(SerializedObject).GetProperty("inspectorMode", BindingFlags.NonPublic | BindingFlags.Instance);
SerializedObject serializedObject = new SerializedObject(unityObject);
inspectorModeInfo.SetValue(serializedObject, InspectorMode.Debug, null);
SerializedProperty localIdProp =
serializedObject.FindProperty("m_LocalIdentfierInFile"); //note the misspelling!
int localId = localIdProp.intValue;
Basically, setting a property called inspectorMode on a SerializedObject instance enables two extra serialized properties: m_InstanceID and m_LocalIdentfierInFile. Please note that “identifier” is misspelled.
New objects have a Local ID value of zero, and get a non-zero value after the scene is saved.
Wow man, thanks a lot for sharing your solution, it is exactly what I needed! I needed a way to uniquely identify GameObjects, and this really helps me out. Great job on finding this
No problem! Hope it helps. One day, I hope Unity makes some nicer way for editor extensions to refer to scene objects across editing sessions. For now, though, this is workable.
Happy to share. My favorite thing about Unity is the openness of the community. Game development is traditionally so closed off and secretive, and I don’t think that way.
Now for the shameless plug. I needed the local ID for a tool I just released on the asset store called JumpTo. It’s a kind of favorites tool for GameObjects and assets. I’m using the local ID to save scene object links to a file. The next time you load that scene, the JumpTo links load with it. It works okay, but it’s quirky.
Well I figured out an workaround, basicly just make a copy when being in Unity and use the Serialization to get the copy back from the scene file:
(don’t forget to use [Serializable] on the class)
/// <summary>
/// This is a copy of the "m_localIndentiferInFile"
/// </summary>
[SerializeField]
private int
persistentID = -1;
Then use the code from “thelackey3326” on top to get the “m_LocalIdentfierInFile” [I like the misspelling… I wonder if it will be fixed in Untiy 5? ] , but make sure it has the if for Unity_Editor otherwise you can’t create a build!
/// <summary>
/// Init this instance, it's public so it can be called from a InspectorScript
/// </summary>
public void init ()
{
#if UNITY_EDITOR
PropertyInfo inspectorModeInfo = typeof(UnityEditor.SerializedObject).GetProperty ("inspectorMode", BindingFlags.NonPublic
| BindingFlags.Instance);
UnityEditor.SerializedObject serializedObject = new UnityEditor.SerializedObject (comp);
inspectorModeInfo.SetValue (serializedObject, UnityEditor.InspectorMode.Debug, null);
UnityEditor.SerializedProperty localIdProp = serializedObject.FindProperty ("m_LocalIdentfierInFile")
//Debug.Log ("found property: " + localIdProp.intValue);
persistentID = localIdProp.intValue;
#endif
}
And at last create an InspectorScript which uses OnEnable() to call the init() method.
public void OnEnable ()
{
myPersist.init ();
}
This only works once the Scene is saved (before there is no “m_LocalIdentfierInFile” meaning it is == 0) and it also means, you have create a gameobject (or drag’n’drop a prefabe), save the scene and click at least ONCE on the Gameobject! (Which isn’t tooo nice… but with this Has anyone successfullly used SaveAssetsProcessor? - Questions & Answers - Unity Discussions you could proably hook into saving and then call all instances).
Update, make sure to include the line “UnityEditor.EditorUtility.SetDirty (this);” after setting the persistentID (workaround) to prevent overriding from a prefab!
(see blog post)
I used the info provided in this thread as part of a project of mine. First off, thanks!
I tested the tool with the Unity 5 beta today and it seems that the m_LocalIdentfierInFile property has the value 0 for objects that do not differ from their prefab/asset counterpart. This is rendering the tool completely useless in Unity 5.
Can anyone confirm if this is regular Unity 5 behaviour?
Maybe even if this is intended?
I usually had the value 0 when creating a prefab, the scene has to be saved first to get a “m_LocalIdentfierInFile”, that’s why I meantioned the save hook… I don’t know how it is in Unity 5 though…
I got a Unity 5 beta key so that I could test JumpTo. Well, it doesn’t save links to scene instance prefabs or their children for exactly the reason that FlaSh.G describes above. They simply don’t have a “local identifier in file.” Scene files no longer serialize a prefab into the scene file, so there is no “local” instance to speak of.
If you add a prefab to your scene, save the scene, then open the scene file in a text editor (of course, it has to be saved in text format), then you can find the prefab by its GUID, which can be found in the prefab’s meta file. In the scene file, there will be an entry for your prefab that starts with “Prefab:” and any modifications will be listed underneath.
So that means that, when a scene is loaded, any prefabs in the scene (that aren’t broken links in red) are actually being instantiated from the prefab file and then modified according to the data saved to the scene.
A coworker of mine had mentioned a few days ago that he had read about this change, and it made me wonder if JumpTo would be broken for Unity 5. Sadly, yes, one of its most attractive features no longer works in 5!
Looks like we still can get the Local Identifier In File of the scene prefabs in Unity 5 - we need to get the prefab object first using the PrefabUtility.GetPrefabObject().
It works fine for my purposes (I need to store id to be able to select desired object even if there are few other objects with same path and name nearby).
It’s not the same though. I’m less interested in the prefab the object is linked to, but rather the object itself. If multiple GameObjects are linked to the same prefabs, there still seems to be no way to perfectly identify the object. So if the objects have values that differ from the prefab original, we cannot tell which prefab instance that is.
Maybe I’m missing something or just making something stupid, but I just tried my method on such setup:
prefab file
scene with 4 instances of prefab
2 instances differ from prefab file asset (changed some values in components)
2 instances are totally untouched instances
Well that’s interesting… I will fiddle around with this for a bit and see if this actually works again. Saving a scene in text format yielded for me that it might indeed. Thanks for the info!