diff --git a/Assets/Packages/com.cosminb.unity-internals/Runtime~/Internal/BlittableArrayWrapper.cs b/Assets/Packages/com.cosminb.unity-internals/Runtime~/Internal/BlittableArrayWrapper.cs index 5b3d224..a8fa25b 100644 --- a/Assets/Packages/com.cosminb.unity-internals/Runtime~/Internal/BlittableArrayWrapper.cs +++ b/Assets/Packages/com.cosminb.unity-internals/Runtime~/Internal/BlittableArrayWrapper.cs @@ -28,7 +28,9 @@ public enum UpdateFlags /// /// Converts the native data to a NativeArray without copying. - /// The caller is responsible for disposing the NativeArray. + /// WARNING: This wraps Unity-owned memory. The returned NativeArray must NOT + /// be disposed — use Allocator.None so that Dispose() is a no-op. If you need + /// a NativeArray you can safely dispose, use instead. /// [MethodImpl(MethodImplOptions.AggressiveInlining)] public NativeArray ToNativeArray(Allocator allocator) where T : unmanaged @@ -42,13 +44,14 @@ public NativeArray ToNativeArray(Allocator allocator) where T : unmanaged int elementSize = UnsafeUtility.SizeOf(); int elementCount = size / elementSize; - // Create NativeArray that wraps the data + // Wrap Unity-owned memory with Allocator.None so Dispose() won't + // attempt to free native memory we don't own. var nativeArray = NativeArrayUnsafeUtility.ConvertExistingDataToNativeArray( - data, elementCount, allocator); + data, elementCount, Allocator.None); #if ENABLE_UNITY_COLLECTIONS_CHECKS // Set safety handle for the native array - NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref nativeArray, + NativeArrayUnsafeUtility.SetAtomicSafetyHandle(ref nativeArray, AtomicSafetyHandle.Create()); #endif diff --git a/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityExposed.cs b/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityExposed.cs index 4016316..f53415b 100644 --- a/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityExposed.cs +++ b/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityExposed.cs @@ -17,11 +17,16 @@ public static class UnityExposed /// /// Gets the marshalled Unity object pointer. This avoids allocations compared to reflection. + /// The Cecil processor detects whether the target Unity version uses the pre-6000.3 + /// signature (int, Type, out bool) or the 6000.3+ signature (int, out bool) for the + /// internal GetPtrFromInstanceID call and emits the correct IL accordingly. /// public static IntPtr MarshalUnityObject(UnityEngine.Object obj) { // This will be replaced by Cecil to access obj.m_CachedPtr directly - // and call Unity's internal GetPtrFromInstanceID if needed + // and call Unity's internal GetPtrFromInstanceID if needed. + // The Cecil processor auto-detects the GetPtrFromInstanceID signature at + // build time, so the same source works for both pre-6000.3 and 6000.3+. throw new NotImplementedException("Assembly not processed by Cecil. Run ProcessAssembly.sh"); } diff --git a/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityVersionChecker.cs b/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityVersionChecker.cs index 7e08f5d..2abda1e 100644 --- a/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityVersionChecker.cs +++ b/Assets/Packages/com.cosminb.unity-internals/Runtime~/UnityVersionChecker.cs @@ -8,17 +8,27 @@ namespace ExposedBindings { /// /// Checks Unity version compatibility for the internal bindings. + /// The Cecil processor auto-detects internal API signatures at build time, + /// so the DLL must be rebuilt via ProcessAssembly.sh when crossing major + /// version boundaries (e.g. 6000.0 -> 6000.3). /// #if UNITY_EDITOR [InitializeOnLoad] #endif public static class UnityVersionChecker { - private const string TARGET_UNITY_VERSION = "6000.0.31f1"; - private const int TARGET_MAJOR = 6000; - private const int TARGET_MINOR = 0; - private const int TARGET_PATCH = 31; - + // Minimum supported version — anything older is unsupported. + private const string MIN_UNITY_VERSION = "6000.0.31f1"; + private const int MIN_MAJOR = 6000; + private const int MIN_MINOR = 0; + private const int MIN_PATCH = 31; + + // Maximum version the Cecil processor has been validated against. + // Bump this when verifying a new Unity release. + private const string MAX_VALIDATED_VERSION = "6000.3.99f1"; + private const int MAX_MAJOR = 6000; + private const int MAX_MINOR = 3; + static UnityVersionChecker() { CheckUnityVersion(); @@ -30,33 +40,31 @@ static UnityVersionChecker() public static void CheckUnityVersion() { var currentVersion = Application.unityVersion; - + if (!ParseUnityVersion(currentVersion, out int major, out int minor, out int patch)) { Debug.LogWarning($"[ExposedBindings] Could not parse Unity version: {currentVersion}. " + - $"This library was built for Unity {TARGET_UNITY_VERSION}."); + $"Minimum supported: {MIN_UNITY_VERSION}."); return; } - // Check if version is older than target - if (major < TARGET_MAJOR || - (major == TARGET_MAJOR && minor < TARGET_MINOR) || - (major == TARGET_MAJOR && minor == TARGET_MINOR && patch < TARGET_PATCH)) + // Check if version is older than minimum + if (major < MIN_MAJOR || + (major == MIN_MAJOR && minor < MIN_MINOR) || + (major == MIN_MAJOR && minor == MIN_MINOR && patch < MIN_PATCH)) { - Debug.LogError($"[ExposedBindings] Unity version {currentVersion} is older than the minimum supported version {TARGET_UNITY_VERSION}. " + + Debug.LogError($"[ExposedBindings] Unity version {currentVersion} is older than the minimum supported version {MIN_UNITY_VERSION}. " + "The internal bindings may not work correctly."); return; } - // Warn if version is newer - if (major > TARGET_MAJOR || - (major == TARGET_MAJOR && minor > TARGET_MINOR) || - (major == TARGET_MAJOR && minor == TARGET_MINOR && patch > TARGET_PATCH)) + // Warn if version is beyond validated range + if (major > MAX_MAJOR || + (major == MAX_MAJOR && minor > MAX_MINOR)) { - Debug.LogWarning($"[ExposedBindings] This library was built for Unity {TARGET_UNITY_VERSION}, " + - $"but you are using {currentVersion}. " + - "Unity's internal signatures may have changed. " + - "Please test thoroughly and consider updating the bindings if issues occur."); + Debug.LogWarning($"[ExposedBindings] Unity {currentVersion} is newer than the last validated version ({MAX_VALIDATED_VERSION}). " + + "Internal signatures may have changed — rebuild with ProcessAssembly.sh against your Unity install " + + "and test thoroughly."); } } @@ -72,7 +80,7 @@ private static bool ParseUnityVersion(string versionString, out int major, out i if (string.IsNullOrEmpty(versionString)) return false; - // Unity version format: "6000.0.31f1" or "2022.3.10f1" + // Unity version format: "6000.0.31f1" or "6000.3.2f1" var parts = versionString.Split('.'); if (parts.Length < 3) return false; @@ -83,12 +91,12 @@ private static bool ParseUnityVersion(string versionString, out int major, out i if (!int.TryParse(parts[1], out minor)) return false; - // Extract patch number (remove 'f1' suffix) + // Extract patch number (remove 'f1', 'b1', 'a1' suffix) var patchStr = parts[2]; - var fIndex = patchStr.IndexOf('f'); - if (fIndex > 0) + var suffixIndex = patchStr.IndexOfAny(new[] { 'f', 'b', 'a' }); + if (suffixIndex > 0) { - patchStr = patchStr.Substring(0, fIndex); + patchStr = patchStr.Substring(0, suffixIndex); } if (!int.TryParse(patchStr, out patch)) @@ -103,38 +111,39 @@ private static bool ParseUnityVersion(string versionString, out int major, out i public static VersionCompatibility GetCompatibility() { var currentVersion = Application.unityVersion; - + if (!ParseUnityVersion(currentVersion, out int major, out int minor, out int patch)) { return new VersionCompatibility { IsCompatible = false, CurrentVersion = currentVersion, - TargetVersion = TARGET_UNITY_VERSION, + MinVersion = MIN_UNITY_VERSION, + MaxValidatedVersion = MAX_VALIDATED_VERSION, Message = "Could not parse Unity version" }; } - bool isOlder = major < TARGET_MAJOR || - (major == TARGET_MAJOR && minor < TARGET_MINOR) || - (major == TARGET_MAJOR && minor == TARGET_MINOR && patch < TARGET_PATCH); + bool isOlder = major < MIN_MAJOR || + (major == MIN_MAJOR && minor < MIN_MINOR) || + (major == MIN_MAJOR && minor == MIN_MINOR && patch < MIN_PATCH); - bool isNewer = major > TARGET_MAJOR || - (major == TARGET_MAJOR && minor > TARGET_MINOR) || - (major == TARGET_MAJOR && minor == TARGET_MINOR && patch > TARGET_PATCH); + bool isBeyondValidated = major > MAX_MAJOR || + (major == MAX_MAJOR && minor > MAX_MINOR); - bool isExactMatch = major == TARGET_MAJOR && minor == TARGET_MINOR && patch == TARGET_PATCH; + bool isInRange = !isOlder && !isBeyondValidated; return new VersionCompatibility { IsCompatible = !isOlder, - IsExactMatch = isExactMatch, - IsNewer = isNewer, + IsInValidatedRange = isInRange, + IsBeyondValidated = isBeyondValidated, CurrentVersion = currentVersion, - TargetVersion = TARGET_UNITY_VERSION, + MinVersion = MIN_UNITY_VERSION, + MaxValidatedVersion = MAX_VALIDATED_VERSION, Message = isOlder ? "Unity version is older than minimum supported version" : - isNewer ? "Unity version is newer than target version - internals may have changed" : - "Unity version matches target version" + isBeyondValidated ? "Unity version is newer than last validated version — rebuild recommended" : + "Unity version is within validated range" }; } @@ -144,11 +153,12 @@ public static VersionCompatibility GetCompatibility() public struct VersionCompatibility { public bool IsCompatible; - public bool IsExactMatch; - public bool IsNewer; + public bool IsInValidatedRange; + public bool IsBeyondValidated; public string CurrentVersion; - public string TargetVersion; + public string MinVersion; + public string MaxValidatedVersion; public string Message; } } -} \ No newline at end of file +} diff --git a/Assets/Packages/com.cosminb.unity-internals/package.json b/Assets/Packages/com.cosminb.unity-internals/package.json index 785398b..3651e3a 100644 --- a/Assets/Packages/com.cosminb.unity-internals/package.json +++ b/Assets/Packages/com.cosminb.unity-internals/package.json @@ -1,8 +1,8 @@ { "name": "com.cosminb.unity-internals", - "version": "1.0.0", + "version": "1.1.0", "displayName": "Exposed Bindings", - "description": "Exposes Unity internal bindings for high-performance native array operations. Built for Unity 6000.0.31f1. Source code is available in the Runtime~ folder for reference and modification.", + "description": "Exposes Unity internal bindings for high-performance native array operations. Supports Unity 6000.0.31f1 through 6000.3.x. Source code is available in the Runtime~ folder for reference and modification.", "unity": "6000.0", "unityRelease": "31f1", "dependencies": { diff --git a/CecilProcessor/Program.cs b/CecilProcessor/Program.cs index 02178bd..8f712c3 100644 --- a/CecilProcessor/Program.cs +++ b/CecilProcessor/Program.cs @@ -102,7 +102,7 @@ static void ProcessAssembly(string inputPath, string outputPath, AddMarshalUnityObjectMethod(assembly, exposedType, coreModule); ReplaceImageConversionMethod(assembly, exposedType, imageConversionModule, unitySpanWrapper, ourSpanWrapper); ReplaceAssetBundleMethods(assembly, exposedType, assetBundleModule, unitySpanWrapper, ourSpanWrapper); - ReplaceEncodingMethods(assembly, exposedType, imageConversionModule); + ReplaceEncodingMethods(assembly, exposedType, imageConversionModule, coreModule); // Remove System.Private.CoreLib reference (added by dotnet SDK but not needed in Unity) var coreLibRef = assembly.MainModule.AssemblyReferences.FirstOrDefault(r => r.Name == "System.Private.CoreLib"); @@ -154,7 +154,11 @@ static void AddMarshalUnityObjectMethod(AssemblyDefinition assembly, TypeDefinit return; } - // Find GetPtrFromInstanceID method + // Find GetPtrFromInstanceID method. + // The signature changed in Unity 6000.3: + // Pre-6000.3: IntPtr GetPtrFromInstanceID(int instanceID, Type objectType, out bool isMonoBehaviour) + // 6000.3+: IntPtr GetPtrFromInstanceID(int instanceID, out bool isMonoBehaviour) + // We detect the parameter count at processing time and emit the correct IL. var getPtrMethod = unityObjectType.Methods.FirstOrDefault(m => m.Name == "GetPtrFromInstanceID"); if (getPtrMethod == null) { @@ -162,6 +166,11 @@ static void AddMarshalUnityObjectMethod(AssemblyDefinition assembly, TypeDefinit return; } + bool hasTypeParameter = getPtrMethod.Parameters.Count == 3; + Console.WriteLine(hasTypeParameter + ? " Detected GetPtrFromInstanceID(int, Type, out bool) — pre-6000.3 signature" + : " Detected GetPtrFromInstanceID(int, out bool) — 6000.3+ signature"); + // Clear existing method body method.Body.Instructions.Clear(); method.Body.Variables.Clear(); @@ -195,38 +204,42 @@ static void AddMarshalUnityObjectMethod(AssemblyDefinition assembly, TypeDefinit il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Beq_S, needsInstanceIdLabel); - + // m_CachedPtr is valid, return it il.Emit(OpCodes.Ldloc_0); il.Emit(OpCodes.Ret); // m_CachedPtr is zero, need to use instance ID il.Append(needsInstanceIdLabel); - + // Call GetInstanceID() to get the instance ID var instanceIdLocal = new VariableDefinition(assembly.MainModule.TypeSystem.Int32); method.Body.Variables.Add(instanceIdLocal); - + il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Call, assembly.MainModule.ImportReference(getInstanceIdMethod)); il.Emit(OpCodes.Stloc, instanceIdLocal); - + // Check if instance ID == 0 var instanceIdNotZeroLabel = il.Create(OpCodes.Nop); il.Emit(OpCodes.Ldloc, instanceIdLocal); il.Emit(OpCodes.Brtrue_S, instanceIdNotZeroLabel); - + // Instance ID is 0, return IntPtr.Zero il.Emit(OpCodes.Ldc_I4_0); il.Emit(OpCodes.Conv_I); il.Emit(OpCodes.Ret); - + // Instance ID is not 0, call GetPtrFromInstanceID il.Append(instanceIdNotZeroLabel); il.Emit(OpCodes.Ldloc, instanceIdLocal); - - // For simplicity, pass null for Type (Unity will handle it) - il.Emit(OpCodes.Ldnull); + + // Pre-6000.3: pass null for the Type parameter that was removed in 6000.3 + if (hasTypeParameter) + { + il.Emit(OpCodes.Ldnull); + } + il.Emit(OpCodes.Ldloca_S, isMonoBehaviourLocal); il.Emit(OpCodes.Call, assembly.MainModule.ImportReference(getPtrMethod)); il.Emit(OpCodes.Ret); @@ -485,11 +498,9 @@ static void ProcessAssetBundleMethod(AssemblyDefinition assembly, AssemblyDefini Console.WriteLine($"Processed {methodName}"); } - static void ReplaceEncodingMethods(AssemblyDefinition assembly, TypeDefinition exposedType, AssemblyDefinition imageConversionModule) + static void ReplaceEncodingMethods(AssemblyDefinition assembly, TypeDefinition exposedType, AssemblyDefinition imageConversionModule, AssemblyDefinition coreModule) { - // Find Unity's BlittableArrayWrapper type - it's in CoreModule - var coreModulePath = Path.Combine(Path.GetDirectoryName(imageConversionModule.MainModule.FileName), "UnityEngine.CoreModule.dll"); - var coreModule = AssemblyDefinition.ReadAssembly(coreModulePath); + // Reuse the already-loaded CoreModule to find BlittableArrayWrapper var unityBlittableWrapper = coreModule.MainModule.GetType("UnityEngine.Bindings.BlittableArrayWrapper"); if (unityBlittableWrapper == null) diff --git a/ProcessAssembly.sh b/ProcessAssembly.sh index 0410e26..657e818 100755 --- a/ProcessAssembly.sh +++ b/ProcessAssembly.sh @@ -1,8 +1,14 @@ #!/bin/bash # Build script for processing Unity internal bindings assembly with Cecil - -UNITY_PATH="/Applications/Unity/Hub/Editor/6000.0.31f1" +# +# Usage: +# ./ProcessAssembly.sh # uses default Unity path +# ./ProcessAssembly.sh /path/to/unity/editor # custom Unity install +# UNITY_PATH=/path/to/unity ./ProcessAssembly.sh # via env var + +# Accept Unity path as first argument, fall back to env var, then to default. +UNITY_PATH="${1:-${UNITY_PATH:-/Applications/Unity/Hub/Editor/6000.0.31f1}}" PROJECT_PATH="$(pwd)" ASSEMBLY_NAME="ExposedBindings" @@ -10,6 +16,23 @@ echo "=== ExposedBindings Assembly Processor ===" echo "Unity Path: $UNITY_PATH" echo "Project Path: $PROJECT_PATH" +# Resolve the managed assemblies directory (macOS vs Windows layout) +if [ -d "$UNITY_PATH/Unity.app/Contents/Managed/UnityEngine" ]; then + MANAGED_DIR="$UNITY_PATH/Unity.app/Contents/Managed" + ENGINE_DIR="$MANAGED_DIR/UnityEngine" +elif [ -d "$UNITY_PATH/Editor/Data/Managed/UnityEngine" ]; then + MANAGED_DIR="$UNITY_PATH/Editor/Data/Managed" + ENGINE_DIR="$MANAGED_DIR/UnityEngine" +else + echo "Error: Could not locate Unity managed assemblies under $UNITY_PATH" + echo "Tried:" + echo " $UNITY_PATH/Unity.app/Contents/Managed/UnityEngine (macOS)" + echo " $UNITY_PATH/Editor/Data/Managed/UnityEngine (Windows)" + exit 1 +fi + +echo "Managed Dir: $MANAGED_DIR" + # Step 1: Build the Cecil processor echo "" echo "Step 1: Building Cecil processor..." @@ -32,8 +55,8 @@ rm -rf "$TEMP_BUILD" mkdir -p "$TEMP_BUILD/TempAssembly" cd "$TEMP_BUILD/TempAssembly" -# Create project file -cat > TempAssembly.csproj << 'EOF' +# Create project file — references are resolved from the detected Unity install +cat > TempAssembly.csproj << CSPROJ_EOF netstandard2.1 @@ -43,29 +66,29 @@ cat > TempAssembly.csproj << 'EOF' - /Applications/Unity/Hub/Editor/6000.0.31f1/Unity.app/Contents/Managed/UnityEngine/UnityEngine.CoreModule.dll + ${ENGINE_DIR}/UnityEngine.CoreModule.dll - /Applications/Unity/Hub/Editor/6000.0.31f1/Unity.app/Contents/Managed/UnityEngine/UnityEngine.AssetBundleModule.dll + ${ENGINE_DIR}/UnityEngine.AssetBundleModule.dll - /Applications/Unity/Hub/Editor/6000.0.31f1/Unity.app/Contents/Managed/UnityEngine/UnityEngine.ImageConversionModule.dll + ${ENGINE_DIR}/UnityEngine.ImageConversionModule.dll - /Applications/Unity/Hub/Editor/6000.0.31f1/Unity.app/Contents/Managed/Unity.Collections.dll + ${MANAGED_DIR}/Unity.Collections.dll - /Applications/Unity/Hub/Editor/6000.0.31f1/Unity.app/Contents/Managed/mscorlib.dll + ${MANAGED_DIR}/mscorlib.dll - /Applications/Unity/Hub/Editor/6000.0.31f1/Unity.app/Contents/Managed/System.dll + ${MANAGED_DIR}/System.dll - /Applications/Unity/Hub/Editor/6000.0.31f1/Unity.app/Contents/Managed/System.Core.dll + ${MANAGED_DIR}/System.Core.dll -EOF +CSPROJ_EOF # Copy source files from package Runtime~ directory cp -r "$PROJECT_PATH/Assets/Packages/com.cosminb.unity-internals/Runtime~"/* . @@ -110,7 +133,8 @@ echo "2. Unity will automatically reimport it" echo "3. Test the functionality with the TestUnityInternalBindings MonoBehaviour" echo "" echo "All methods processed successfully:" -echo " ✓ MarshalUnityObject - Direct access to Unity object pointers without allocations" -echo " ✓ ImageConversion_LoadImage_Injected - Direct Span-based image loading" -echo " ✓ AssetBundle_LoadFromMemoryAsync_Internal_Injected - Async bundle loading from Span" -echo " ✓ AssetBundle_LoadFromMemory_Internal_Injected - Sync bundle loading from Span" \ No newline at end of file +echo " - MarshalUnityObject - Direct access to Unity object pointers without allocations" +echo " - ImageConversion_LoadImage_Injected - Direct Span-based image loading" +echo " - AssetBundle_LoadFromMemoryAsync_Internal_Injected - Async bundle loading from Span" +echo " - AssetBundle_LoadFromMemory_Internal_Injected - Sync bundle loading from Span" +echo " - Texture encoding methods (PNG, JPG, TGA, EXR)" diff --git a/README.md b/README.md index 2764028..6a2957c 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ ### High-Performance Unity Internal Bindings for Zero-Allocation Operations - [![Unity](https://img.shields.io/badge/Unity-6000.0.31f1-black.svg?style=flat&logo=unity)](https://unity3d.com/) + [![Unity](https://img.shields.io/badge/Unity-6000.0_|_6000.3-black.svg?style=flat&logo=unity)](https://unity3d.com/) [![C#](https://img.shields.io/badge/C%23-11.0-239120.svg?style=flat&logo=c-sharp)](https://docs.microsoft.com/en-us/dotnet/csharp/) [![IL2CPP](https://img.shields.io/badge/IL2CPP-Supported-00D4AA.svg?style=flat)](https://docs.unity3d.com/Manual/IL2CPP.html) [![Cross Platform](https://img.shields.io/badge/Platform-iOS_Android_WebGL_Windows_macOS_Linux-blue.svg?style=flat)](https://unity.com/) @@ -42,7 +42,7 @@ The `Runtime~` folder (with `~` suffix) prevents Unity from compiling the source ## Requirements -- Unity 6000.0.31f1 or later +- Unity 6000.0.31f1 through 6000.3.x (Cecil processor auto-detects internal API signatures) - .NET 6.0 SDK (for Cecil processing) - Mono.Cecil NuGet package @@ -84,16 +84,18 @@ Alternatively, add directly to your `Packages/manifest.json`: ### Post-Installation: Processing the Assembly -**Note:** The package includes a pre-built `ExposedBindings.dll` that works with Unity 6000.0.31f1+. +**Note:** The package includes a pre-built `ExposedBindings.dll` that was processed against Unity 6000.0.31f1. -If you need to rebuild for a different Unity version: +If you are on Unity 6000.3.x or a different version, you **must** rebuild the assembly: 1. Copy `ProcessAssembly.sh` and `CecilProcessor/` from this repository to your project root 2. Run: ```bash chmod +x ProcessAssembly.sh - ./ProcessAssembly.sh + # Pass your Unity editor path (auto-detects macOS/Windows layout): + ./ProcessAssembly.sh "/Applications/Unity/Hub/Editor/6000.3.0f1" ``` + The Cecil processor will auto-detect which internal signatures your Unity version uses and emit the correct IL. ## Usage Examples @@ -123,7 +125,18 @@ The library uses Mono.Cecil to: - **Platforms**: Android, WebGL, macOS, Windows, Linux, iOS - **Build Types**: Mono and IL2CPP -- **Unity Version**: 6000.0.31f1 and later +- **Unity Version**: 6000.0.31f1 through 6000.3.x (validated) + +### Unity 6000.3 (Unity 6.3) Notes + +Unity 6000.3 changed the internal signature of `UnityEngine.Object.GetPtrFromInstanceID`: + +| Version | Signature | +|---------|-----------| +| 6000.0 - 6000.2 | `IntPtr GetPtrFromInstanceID(int instanceID, Type objectType, out bool isMonoBehaviour)` | +| 6000.3+ | `IntPtr GetPtrFromInstanceID(int instanceID, out bool isMonoBehaviour)` | + +The Cecil processor detects the parameter count at build time and emits the correct IL, so the same source works across both version ranges. If you upgrade Unity, just re-run `ProcessAssembly.sh` against the new editor install. ## Performance Benefits @@ -173,19 +186,24 @@ If you want to modify the library or rebuild for a different Unity version: # Make the script executable chmod +x ProcessAssembly.sh -# Run the processor +# Run the processor (defaults to 6000.0.31f1, or pass your Unity path): ./ProcessAssembly.sh +./ProcessAssembly.sh "/Applications/Unity/Hub/Editor/6000.3.0f1" + +# Or via environment variable: +UNITY_PATH="/path/to/editor" ./ProcessAssembly.sh ``` This will: - Build the CecilProcessor from source -- Compile the source code from `Runtime~/` -- Process the assembly with Cecil to inject IL code +- Compile the source code from `Runtime~/` +- Auto-detect internal API signatures from your Unity install +- Process the assembly with Cecil to inject the correct IL - Output `ExposedBindings.dll` to the `Plugins/` folder ### Customizing for Different Unity Versions -1. Update Unity path in `ProcessAssembly.sh` if needed -2. Modify `CecilProcessor/Program.cs` if internal signatures changed +1. Pass your Unity editor path to `ProcessAssembly.sh` (macOS and Windows layouts auto-detected) +2. The Cecil processor inspects method signatures at build time — no manual code changes needed for known API variations 3. Test thoroughly on your target Unity version ### Build and Distribution (For Maintainers)