- Home /
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
Answer by TowerOfBricks · May 12, 2011 at 04:20 PM
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.
Answer by Eric5h5 · Nov 22, 2010 at 09:41 AM
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.
You're right, but unfortunately Unity IDE doesn't show the generated code for IDE manipulations, and sometimes it's very hard to find a way to access a particular object in code. For example, I want to access one of my AnimationState objects, but I don't know how to! Here is my original question: http://answers.unity3d.com/questions/822543/how-to-access-animaionstate-in-mecanim.html
So, I thought maybe I can access it at runtime, by its instance ID.
But how would you get this instance ID in the first place? You'd have to call GetInstanceID on... a reference to the object. And if you have a reference to the object, you don't need to look it up by its ID.
Answer by yclick · Jan 18, 2019 at 11:35 AM
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 });
}
Oh, that's kinda neat that they actually implemented the "FindObjectFromInstanceID" method in the runtime (though as a private method). To improve performance i would recommend to get the methodinfo in the static constructor of your helper class and store it in a static private field. Likewise you could store the object parameter array as well and just replace the id when calling the method. Though this approach is still not garbage free since we need to box the integer in order to add it to the object array.
However this can be prevented by creating a delegate for the method. That way we can store a "direct" reference to the static method in a delegate
Something like this:
// not tested
public static class UnityObjectHelper
{
private static Func<int, UnityEngine.Object> m_FindObjectFromInstanceID = null;
static UnityObjectHelper()
{
var methodInfo = typeof(UnityEngine.Object)
.Get$$anonymous$$ethod("FindObjectFromInstanceID",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
if (methodInfo == null)
Debug.LogError("FindObjectFromInstanceID was not found in UnityEngine.Object");
else
m_FindObjectFromInstanceID = (Func<int, UnityEngine.Object>)Delegate.CreateDelegate(typeof(Func<int, UnityEngine.Object>), method);
}
public static UnityEngine.Object FindObjectFromInstanceID(int aObjectID)
{
if (m_FindObjectFromInstanceID == null)
return null;
return m_FindObjectFromInstanceID(aObjectID);
}
}
Now we have a garbage free solution and we can simply call
UnityObjectHelper.FindObjectFromInstanceID(objectID);
Answer by tgraupmann · Apr 05, 2013 at 02:27 AM
I ended up caching an instance dictionary which works just fine accessing instanceIDs from remote computers.
https://www.youtube.com/playlist?list=PL4mjXeDqRBMS5dFZvqV8NDkOz5ZXXTRiq
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;
}
This is just what I'm about to test! Thank u for doing this for me 8)
Answer by HiQdaRe · May 17, 2012 at 07:11 AM
GetInstanceID() get be used to compare two objects and decide if they are the same instance. For example:
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.
Storing the instance ID to later retrieve the same instance does not make sense : I disagree.
I am just researching now how to find a gameObject based on its ID. Why? Well I want to send a hit event through a network, all clients need to know the gameObject that was hit, and it is not possible to send a hit.collider in a RPC call. And yes, I need the hit event to be conducted by the master(is$$anonymous$$ine), not by each client.
It looks like the HashTable/Dictionary method is the only way for me to proceed.
Edit :
However, my next concern is that objects on different clients will have different unique IDs (something else I have to make a project for just to test ....). It's easy for network synced objects with a ViewID, but not for gameObjects that are already in the scene.
UnityEngine.Object instance id's are probably guaranteed to be 1-to-1 between the ID's and the objects they represent, but only within the context of the current session the game is running:
On ONE computer.
ONLY for the duration that the game is running.
Further, and instance ID can only be sure to match a given object while that object exists.
In other words, for any given object:
When closing and reopening the game, it may be assigned a different ID than what it was when you closed it.
When you destroy and recreate an object, it probably will not have the same ID.
When running two separate instances of the game at the same time, such as when playing a multiplayer game with two clients, the IDs may be different between game instances.
And the implications are, respectively, that Object ID's cannot be used as references to objects for:
Saving and loading the objects in your game world between closing and reopening the game.
Saving and loading the objects in your game world without closing and reopening the game, unless no objects to be saved/loaded are created or destroyed.
Networking information between the server and client about objects.
Instead, you'll have to manually create your own IDs. Depending on how you write the IDs you can widen the context in which they can be used to reference objects. For example, Unity's GUID system uses a very long sequence of hexidecimal (64*4 bits?) that is generated randomly for each object that uses one. It is so long that the chance of two objects using the same ID by accident, anywhere in the world, is theoretically nearly 0. These guids are virtually guaranteed to reference one object and only one object anywhere at any time. Overkill for game networking, perhaps.
generate your own members of unique ids' (guid) and handle them yourself as the instance id (while "may" be unique) are not between sessions (hence, instance id).
I've found this to be much more reliable and would allow you to handle direct communication and state management.
Your answer
Follow this Question
Related Questions
Play multiple reversed animations with animation.PlayQueued 0 Answers
2d character flipping and conditionally walking backwards 0 Answers
C#:"w" and "s" switch roles w/ transform.rotation of 180 0 Answers
Get TouchScreenKeyboard instance from when clicking InputField on Mobile 2 Answers
SimpleMove Without Gravity 1 Answer