diff --git a/MCPForUnity/Runtime/Helpers/UnityObjectIdCompat.cs b/MCPForUnity/Runtime/Helpers/UnityObjectIdCompat.cs index a10a99167..3a0ea6cfa 100644 --- a/MCPForUnity/Runtime/Helpers/UnityObjectIdCompat.cs +++ b/MCPForUnity/Runtime/Helpers/UnityObjectIdCompat.cs @@ -1,8 +1,10 @@ using UnityEngine; #if UNITY_EDITOR -using System.Reflection; using UnityEditor; #endif +#if UNITY_6000_6_OR_NEWER +using System.Collections.Generic; +#endif namespace MCPForUnity.Runtime.Helpers { @@ -16,6 +18,18 @@ namespace MCPForUnity.Runtime.Helpers /// public static class UnityObjectIdCompat { +#if UNITY_6000_6_OR_NEWER + // 6000.6 stubs out both EditorUtility.InstanceIDToObject(int) and EntityId's + // implicit int->EntityId conversion (both throw NotImplementedException at + // runtime despite existing in the API surface - verified against 6000.6.0f1). + // The only working reverse path is EntityIdToObject(EntityId) fed a value built + // via EntityId.FromULong(ulong), which needs the full 64-bit id, not the + // truncated int this class hands out. So we cache the full value behind the + // truncated int at mint time and look it up here instead of trying to + // reconstruct it from the int alone. + private static readonly Dictionary _fullIdCache = new Dictionary(); +#endif + /// /// Returns a session-scoped int handle for the object. On 6.5+ truncates the /// EntityId's underlying ulong; lossy but stable within a session and preserves @@ -30,40 +44,35 @@ public static int GetInstanceIDCompat(this Object obj) } #if UNITY_6000_5_OR_NEWER - return (int)EntityId.ToULong(obj.GetEntityId()); + ulong full = EntityId.ToULong(obj.GetEntityId()); + int truncated = (int)full; +#if UNITY_6000_6_OR_NEWER + _fullIdCache[truncated] = full; +#endif + return truncated; #else return obj.GetInstanceID(); #endif } #if UNITY_EDITOR -#if UNITY_6000_6_OR_NEWER - private static MethodInfo _instanceIdToObject; - private static bool _instanceIdToObjectInitialized; -#endif - /// /// Resolves an int instance ID handle back to a UnityEngine.Object. /// Pre-6.0 : EditorUtility.InstanceIDToObject(int) /// 6.0–6.5 : EditorUtility.EntityIdToObject(int) (implicit int→EntityId cast) - /// 6.6+ : reflection on InstanceIDToObject(int) — the API still exists at runtime - /// but is obsolete-as-error; reflection bypasses CS0619 until the public - /// EntityId(int) ctor stabilizes. + /// 6.6+ : EditorUtility.EntityIdToObject(EntityId.FromULong(full)) using the + /// full 64-bit value cached in GetInstanceIDCompat, since the int-only + /// paths (including the implicit int→EntityId cast) are unimplemented + /// stubs on this Unity version. Only resolves ids minted this session. /// public static Object InstanceIDToObjectCompat(int instanceId) { #if UNITY_6000_6_OR_NEWER - if (!_instanceIdToObjectInitialized) + if (_fullIdCache.TryGetValue(instanceId, out ulong full)) { - _instanceIdToObject = typeof(EditorUtility).GetMethod( - "InstanceIDToObject", - BindingFlags.Public | BindingFlags.Static, - null, - new[] { typeof(int) }, - null); - _instanceIdToObjectInitialized = true; + return EditorUtility.EntityIdToObject(EntityId.FromULong(full)); } - return _instanceIdToObject?.Invoke(null, new object[] { instanceId }) as Object; + return null; #elif UNITY_6000_3_OR_NEWER return EditorUtility.EntityIdToObject(instanceId); #else