如何解决Mono类库与Mono运行时不同步问题(Unity模组开发)
问题:MelonLoader模组触发Unity JsonUtility内部调用解析失败及Mono运行时同步错误
环境与问题概述
- 使用工具:MelonLoader v0.6.6
- 游戏环境:Unity 2021.3.16f1 开发的ATLYSS
- 核心问题:模组多数功能正常,但部分函数调用失败,报错无法解析对"UnityEngine.JsonUtility::FromJsonInternal"的内部调用,同时提示Mono运行时与类库不同步,涉及程序集
E:\Steam Games\steamapps\common\ATLYSS\ATLYSS_Data\Managed\UnityEngine.JSONSerializeModule.dll,最终导致模组崩溃 - 已尝试无效方案:切换多种.NET版本(含Unity推荐的.NET Standard 2.1)、使用MelonLoader模板生成项目、手动添加程序集引用、安装多个Mono版本
- 时序相关线索:曾将JSON解析代码从
OnPreInitialization()移至OnInitializeMelon()解决过一次,但Harmony前缀补丁仍触发错误
触发错误的最简代码
using MelonLoader; using HarmonyLib; using UnityEngine; [assembly: MelonInfo(typeof(ServerCapModifier.Core), "ServerCapModifier", "1.5.0", "Stunted Raccoon", null)] [assembly: MelonGame("KisSoft", "ATLYSS")] namespace ServerCapModifier { public class Core : MelonPlugin { [HarmonyPatch(typeof(AtlyssNetworkManager), nameof(AtlyssNetworkManager.OnStartServer))] public static class AtlyssNetworkManager_OnStartServer { public static void Prefix(ref AtlyssNetworkManager __instance) { Melon<Core>.Logger.Msg("Called OnStartServer prefix"); } } } }
可行解决方案
1. 延迟Harmony补丁注册时机
由于时序问题是核心怀疑点,避免在游戏程序集未完全加载时注入补丁:
- 移除补丁类上的自动注册特性,改为在
OnLateInitializeMelon()或OnSceneLoaded()阶段手动注册:
public override void OnLateInitializeMelon() { base.OnLateInitializeMelon(); // 手动注册补丁,确保JSON模块已加载完成 HarmonyInstance.PatchAll(typeof(AtlyssNetworkManager_OnStartServer)); }
- 同时删除补丁类的
[HarmonyPatch]特性,防止自动提前注册。
2. 手动加载并绑定目标程序集
在模组初始化时,显式加载游戏自带的JSON序列化模块,避免Mono加载错误版本:
using System.Reflection; public override void OnInitializeMelon() { base.OnInitializeMelon(); string jsonAssemblyPath = @"E:\Steam Games\steamapps\common\ATLYSS\ATLYSS_Data\Managed\UnityEngine.JSONSerializeModule.dll"; Assembly jsonAssembly = Assembly.LoadFrom(jsonAssemblyPath); if (jsonAssembly != null) { Melon<Core>.Logger.Msg("成功加载UnityEngine.JSONSerializeModule.dll"); // 显式获取JsonUtility类型,绑定到正确程序集 Type jsonUtilityType = jsonAssembly.GetType("UnityEngine.JsonUtility"); } }
3. 调整MelonLoader运行时配置
- 打开游戏目录下的
MelonLoader.cfg配置文件:- 将
UseGameMono设置为true,强制使用游戏自带的Mono运行时 - 将
MonoRuntimeVersion设置为与Unity 2021.3.16f1匹配的版本(推荐6.12.0.186)
- 将
4. 反射调用绕过编译时绑定
如果补丁中需要使用JsonUtility,通过反射调用方法,避免编译时绑定错误的程序集:
public static void Prefix(ref AtlyssNetworkManager __instance) { Melon<Core>.Logger.Msg("Called OnStartServer prefix"); // 反射获取JsonUtility及FromJson方法 Type jsonUtilityType = Type.GetType("UnityEngine.JsonUtility, UnityEngine.JSONSerializeModule"); MethodInfo fromJsonMethod = jsonUtilityType?.GetMethod("FromJson", BindingFlags.Public | BindingFlags.Static, new Type[] { typeof(string), typeof(Type) }); if (fromJsonMethod != null) { // 示例调用,替换为你的实际需求 object result = fromJsonMethod.Invoke(null, new object[] { "{\"key\":\"value\"}", typeof(YourCustomType) }); } }
内容的提问来源于stack exchange,提问作者Stunted Raccoon
相关产品推荐
相关产品推荐

