using System.Collections.Generic; using Newtonsoft.Json; using Newtonsoft.Json.Linq; using UnityEngine; #if UNITY_6000_3_OR_NEWER using UnityEngine.Assemblies; #endif namespace Unity.Pipeline { /// /// Version-stable handle to a Unity object id. In 6000.4 Unity replaced the int instance id with /// (a ulong-backed handle), made Object.GetInstanceID() / /// EditorUtility.InstanceIDToObject(int) obsolete-as-error, and is removing the /// EntityId<->int conversions. This struct stores the concrete id type for the /// running editor — on 6000.4+, int below — and converts implicitly to /// it so it can be passed straight to Unity APIs. All version branching for object ids is confined /// here. It (de)serializes as a single JSON integer (the raw ulong on 6000.4+, the int below). /// [JsonConverter(typeof(ObjectIdConverter))] public readonly struct ObjectId : System.IEquatable { #if UNITY_6000_4_OR_NEWER readonly EntityId m_Value; public ObjectId(EntityId value) { m_Value = value; } public static implicit operator EntityId(ObjectId id) => id.m_Value; public static implicit operator ObjectId(EntityId value) => new ObjectId(value); /// Raw 64-bit id — the canonical wire / serialization form. public ulong RawValue => EntityId.ToULong(m_Value); public static ObjectId FromRaw(ulong raw) => new ObjectId(EntityId.FromULong(raw)); public bool Equals(ObjectId other) => m_Value.Equals(other.m_Value); public override int GetHashCode() => m_Value.GetHashCode(); #else readonly int m_Value; public ObjectId(int value) { m_Value = value; } public static implicit operator int(ObjectId id) => id.m_Value; public static implicit operator ObjectId(int value) => new ObjectId(value); /// Raw id — the canonical wire / serialization form. public long RawValue => m_Value; public static ObjectId FromRaw(long raw) => new ObjectId((int)raw); public bool Equals(ObjectId other) => m_Value == other.m_Value; public override int GetHashCode() => m_Value; #endif public override bool Equals(object obj) => obj is ObjectId other && Equals(other); public override string ToString() => RawValue.ToString(); /// Parse the canonical numeric form produced by . public static ObjectId Parse(string s) { #if UNITY_6000_4_OR_NEWER return FromRaw(ulong.Parse(s)); #else return FromRaw(long.Parse(s)); #endif } /// Try to parse the canonical numeric form produced by . public static bool TryParse(string s, out ObjectId id) { #if UNITY_6000_4_OR_NEWER if (ulong.TryParse(s, out var raw)) { id = FromRaw(raw); return true; } #else if (long.TryParse(s, out var raw)) { id = FromRaw(raw); return true; } #endif id = default; return false; } } /// JSON converter: an is a single integer on the wire. public sealed class ObjectIdConverter : JsonConverter { public override void WriteJson(JsonWriter writer, ObjectId value, JsonSerializer serializer) { writer.WriteValue(value.RawValue); } public override ObjectId ReadJson(JsonReader reader, System.Type objectType, ObjectId existingValue, bool hasExistingValue, JsonSerializer serializer) { var token = JToken.Load(reader); switch (token.Type) { case JTokenType.Integer: #if UNITY_6000_4_OR_NEWER return ObjectId.FromRaw(token.Value()); #else return ObjectId.FromRaw(token.Value()); #endif case JTokenType.String: return ObjectId.Parse((string)token); default: return default; } } } public static class PipelineUtils { public static string GetLoadedAssemblyPath(System.Reflection.Assembly a) { #if UNITY_6000_5_OR_NEWER return a.GetLoadedAssemblyPath(); #else return a.Location; #endif } public static System.Reflection.Assembly LoadFromBytes(byte[] bytes, byte[] pdb = null) { #if UNITY_6000_5_OR_NEWER return UnityEngine.Assemblies.CurrentAssemblies.LoadFromBytes(bytes, pdb); #else return System.Reflection.Assembly.Load(bytes, pdb); #endif } public static T[] FindObjectsByType() where T : Object { #if UNITY_6000_4_OR_NEWER return GameObject.FindObjectsByType(); #else return GameObject.FindObjectsByType(FindObjectsSortMode.None) ; #endif } public static IReadOnlyList GetLoadedAssemblies() { #if UNITY_6000_5_OR_NEWER return CurrentAssemblies.GetLoadedAssemblies(); #else return System.AppDomain.CurrentDomain.GetAssemblies(); #endif } /// The object's id as a version-stable (EntityId on 6000.4+, int below). public static ObjectId GetObjectId(Object obj) { #if UNITY_6000_4_OR_NEWER return new ObjectId(obj.GetEntityId()); #else return new ObjectId(obj.GetInstanceID()); #endif } #if UNITY_EDITOR /// Resolve a loaded/scene object from its , or null if not found. public static Object IdToObject(ObjectId id) { #if UNITY_6000_4_OR_NEWER return UnityEditor.EditorUtility.EntityIdToObject(id); #elif UNITY_6000_3_OR_NEWER // EntityIdToObject is the non-obsolete resolver from 6000.3, but the ulong-backed ObjectId // (GetRawData/FromULong) doesn't exist until 6000.4 — so ObjectId is still int-backed here and // we route the int through the (non-obsolete on 6.3) int->EntityId conversion. return UnityEditor.EditorUtility.EntityIdToObject((int)id); #else return UnityEditor.EditorUtility.InstanceIDToObject((int)id); #endif } #endif } }