How to find object using instance ID ( taken from GetInstanceID)?

Hi,

GetInstanceID() returns an int, fine, but then how do I retrieve that object back using the Id I have stored? I can’t find any function in the help to do so? the only way I found is to scan all objects in the scene… real ugly? or the way to go?!?

I wonder what is the purpose of retrieving an instance Id if it’s not to reuse it. I am willing to learn the purpose of GetInstanceID and it’s intended usage.

Thanks for your help,
Jean

You can use EditorUtility.InstanceIDToObject if you only do it in the editor. It’s a pity it isn’t exposed in the UnityEngine namespace.

There aren't any functions to find objects by instance ID. It doesn't have any one specific purpose; it's up to you if you need a guaranteed unique ID for every object. You could potentially use a hashtable and store references to objects by their instance IDs that way.

public static UnityEngine.Object FindObjectFromInstanceID(int iid)
{
    return (UnityEngine.Object)typeof(UnityEngine.Object)
        .GetMethod("FindObjectFromInstanceID", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static)
        .Invoke(null, new object[] { iid });
}

I ended up caching an instance dictionary which works just fine accessing instanceIDs from remote computers.

I create the instance map as follows:

/// <summary>
/// Map instanceID to GameObjects
/// </summary>
Dictionary<int, GameObject> m_instanceMap = new Dictionary<int, GameObject>();

//record instance map
m_instanceMap.Clear();

List<GameObject> gos = new List<GameObject>();
foreach (GameObject go in Resources.FindObjectsOfTypeAll(typeof (GameObject)))
{
    if (gos.Contains(go))
    {
        continue;
    }
    gos.Add(go);
    m_instanceMap[go.GetInstanceID()] = go;
}

GetInstanceID() get be used to compare two objects and decide if they are the same instance. For example:

Note: code below is not C# but, now obsolete, JS-like Unity Script
function do(inst1: Object, inst2: Object) {
    if (inst1.GetInstanceID() != inst2.GetInstanceID()) {
        doSomething();
    }
}

Storing the instance ID to later retrieve the same instance does not make sense, since storing the object itself uses is more efficient. If you need this for serialization/deserialization you can work with Hashtables.

There’s always a way…
However this way works only in Unity3D Editor [not in player]

		public static bool ParseGameObject(string expression, out GameObject res){
			res = null;
			try{
				var exp = expression.Replace("$", "");
				var i = 0;
				if(int.TryParse(exp, out i)){
					//GameObject Reference Id
					var rid = "{\"Reference\":{\"instanceID\":" + exp + "}}";
					Debug.Log(rid);
					var rq = JsonUtility.FromJson<GameObjectReference>(rid);
					res = rq.Reference;
				}
				else{
					if(exp.Contains("/")){
						var ss = exp.Split('/');
						var i1 = int.Parse(ss[0]);
						var i2 = int.Parse(ss[1]);
						var rid = "{\"Reference\":{\"m_FileID\":" + i1 + ", \"m_PathID\":" + i2 + "}}";
						Debug.LogWarning(rid);
						var rq = JsonUtility.FromJson<GameObjectReference>(rid);
						res = rq.Reference;
						return true;
					}
					//GameObject Name
					var obj = GameObject.Find(exp);
					res = obj;
				}
				return true;
			}
			catch(System.Exception ex){
				Debug.Log (ex.ToString ());
				return false;
			}
		}

As you can see above there’s also a solution using m_FileID which works for players [at least for Win/Linux/Mac]
Below is my translation method

	public static string GetGameObjectReference(GameObject obj){
			var r = new GameObjectReference {Reference = obj};

			var json = JsonUtility.ToJson (r);
			Debug.Log (json);
			#if UNITY_EDITOR
			var rst = JsonUtility.FromJson<GameObjectEditorReference>(json);
			return rst.Reference.instanceID.ToString();
			#else
			var rst = JsonUtility.FromJson<GameObjectPlayerReference>(json);
			return rst.Reference.m_FileID + "/" + rst.Reference.m_PathID;
			#endif
		}

GameObject<…>Reference are structural classes used to store some data

[System.Serializable]
	public class GameObjectReference{

		public GameObject Reference;

	}

	[System.Serializable]
	public class GameObjectEditorReference{
		public EditorReferenceRef Reference;

		[System.Serializable]
		public class EditorReferenceRef{
			public int instanceID;
		}
	}

	[System.Serializable]
	public class GameObjectPlayerReference{

		public PlayerReferenceRef Reference;

		[System.Serializable]
		public class PlayerReferenceRef{
			public int m_FileID;
			public int m_PathID;
		}
	}

This is not fast way, however it’s working way.
You can cut it from my code [this is a solution to parse [refId] string into GameObject or [m_FileID]/[m_PathID] into GameObject or just a $[name] into GameObject

Sorry to comment on such an old thread, but I came here looking for an answer so I will leave the answer for others:

It is weird that this is a part of Resources, and not GameObject, but that is probably because it returns and Object which you can then cast to a GameObject.

I have used it in code like the following:

 MyScript? script = null;
 GameObject? obj = Resources.InstanceIDToObject(unityInstanceID) as GameObject;

if (obj == null)
{
    Debug.LogError("Cound not convert Unity GameObject InstanceID to a valid GameObject");
}
else
{
    script = obj.GetComponent<MyScript>();
}

I hope this helps anyone who comes here looking for an answer.