diff --git a/Runtimes/Unity/BepInEx.Unity.IL2CPP/IL2CPPChainloader.cs b/Runtimes/Unity/BepInEx.Unity.IL2CPP/IL2CPPChainloader.cs index 1ccfb9e..5fcdb35 100644 --- a/Runtimes/Unity/BepInEx.Unity.IL2CPP/IL2CPPChainloader.cs +++ b/Runtimes/Unity/BepInEx.Unity.IL2CPP/IL2CPPChainloader.cs @@ -83,23 +83,19 @@ public class IL2CPPChainloader : BaseChainloader if (methodName == "Internal_ActiveSceneChanged") try { - if (ConfigUnityLogging.Value) - { - Logger.Sources.Add(new IL2CPPUnityLogSource()); - - Application.CallLogCallback("Test call after applying unity logging hook", "", LogType.Assert, - true); - } - + // Unhook up front so the detour fires once even if setup below throws. unhook = true; + // Isolated so a missing-interop JIT failure happens inside the try (caught), not in OnInvokeMethod itself. + SetupUnityLogging(); + Il2CppInteropManager.PreloadInteropAssemblies(); Instance.Execute(); } catch (Exception ex) { - Logger.Log(LogLevel.Fatal, "Unable to execute IL2CPP chainloader"); + Logger.Log(LogLevel.Fatal, "Unable to execute IL2CPP chainloader, no plugins will be loaded"); Logger.Log(LogLevel.Error, ex); } @@ -115,6 +111,17 @@ public class IL2CPPChainloader : BaseChainloader return result; } + // JIT-compiled only when called here, so OnInvokeMethod needs no interop assemblies present to JIT. + private static void SetupUnityLogging() + { + if (!ConfigUnityLogging.Value) + return; + + Logger.Sources.Add(new IL2CPPUnityLogSource()); + + Application.CallLogCallback("Test call after applying unity logging hook", "", LogType.Assert, true); + } + protected override void InitializeLoggers() { base.InitializeLoggers();