Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Feature Request Expose `Object.FindObjectFromInstanceID(int instanceID)` API

Discussion in 'Scripting' started by Enderlook, May 17, 2023.

  1. Enderlook

    Enderlook

    Joined:
    Dec 4, 2018
    Posts:
    44
    When working with code that must run in Burst or Job Systems, instances id came very handy, as they are unmanaged and works seamlessly with those techs.
    However, when you need to take back those ids to actual objects... there is simply no API for doing it.
    Instead, we must find our own solutions, such as using reflection (and risking an API change) or iterating over each reachable object in the scene/game and retrieving its instanceID in order to build and cache a table, which is probably less performant.

    Exposing this API would come very handy for this scenarios.
     
  2. Yuchen_Chang

    Yuchen_Chang

    Joined:
    Apr 24, 2020
    Posts:
    105
    Does the
    Object.FindObjectFromInstanceID
    works different from
    Resources.InstanceIDToObject
    ? (There's also InstanceIDToObjectList(), that accepts NativeArray<int>)
     
  3. Enderlook

    Enderlook

    Joined:
    Dec 4, 2018
    Posts:
    44
    Honestly, I didn't know about the existence of that API, I didn't expect it to be found in the `Resources` class rather than `Object`.
    Interestingly, they map to different native functions:

    Code (CSharp):
    1. [MethodImpl(MethodImplOptions.InternalCall)]
    2. [FreeFunction("Resources_Bindings::InstanceIDToObject")]
    3. public static extern Object InstanceIDToObject(int instanceID);
    4.  
    5. [MethodImpl(MethodImplOptions.InternalCall)]
    6. [FreeFunction("UnityEngineObjectBindings::FindObjectFromInstanceID")]
    7. [VisibleToOtherModules]
    8. internal static extern Object FindObjectFromInstanceID(int instanceID);
    9.  
    Not sure if there is any difference indeed.

    Thanks for the info!

    By the way, the `Resources.InstanceIDToObjectList(NativeArray<int>, List<Object>)` looks very useful, though it's a pity it doesn't have a `Resources.InstanceIDToObjectList(NativeArray<int>, Span<Object>)` overload.
    Not only that would allow using arrays, which have lower indirections when reading from our side, but to freely cast the object. After all, if you want for example a `List<Collider>`, you must make a second list, copy and cast the result.
    Instead, with spans you can take a span from `Collider[]` and use unsafe code to transmute it into `Span<Object>`. As long as all the instances ids you pass are mapped into `Collider`s, it would be safe, and you would save both the second allocation, the copy, and the cast check.

    (Surprisingly, Unity doesn't do that for internal methods, such as `Object.FindObjectsOfType<T>()` which allocates two arrays, and cast and copy each item one by one).
     
    Yuchen_Chang and tsukimi like this.
  4. Enderlook

    Enderlook

    Joined:
    Dec 4, 2018
    Posts:
    44
    Having as overrides `Resources.InstanceIDToObjectList(NativeArray<ColliderHit>, List<Collider>)` and `Resources.InstanceIDToObjectList(NativeArray<RaycastHit>, List<Collider>)` (or better with the usage of spans) would also come in handy to avoid having to copy the ids to an intermediate array.