如何用Harmony修改Unity异步方法自动生成类中的参数?
解决Unity异步方法中嵌套枚举器类的Harmony补丁问题
下面是几个可行的方案,直接针对你的场景:
1. 直接定位自动生成的嵌套类方法
编译器生成的异步枚举器类名称带尖括号,但可以通过反射精准定位,不用依赖MethodType.Enumerator,步骤如下:
- 获取外层
GameNetworkManager类的类型 - 遍历它的嵌套类型,找到名称匹配
<StartHost>d__79的类(注意名称可能随编译器版本、方法签名变化,要和dotPeek里的一致) - 从该嵌套类中取出
MoveNext方法,给这个方法打Harmony补丁
示例代码:
var outerType = typeof(GameNetworkManager); var nestedEnumeratorType = outerType.GetNestedTypes(BindingFlags.NonPublic | BindingFlags.Instance) .First(t => t.Name == "<StartHost>d__79"); var moveNextMethod = nestedEnumeratorType.GetMethod("MoveNext", BindingFlags.Public | BindingFlags.Instance); // 打Harmony补丁 Harmony.CreateAndPatchAll(moveNextMethod, typeof(YourPatchClass));
在补丁里,你可以通过ILGenerator修改SteamMatchmaking.CreateLobbyAsync调用的第4个参数,或者用Harmony的Prefix/Postfix配合MethodBase拦截参数。
2. 直接拦截SteamMatchmaking.CreateLobbyAsync方法
既然目标是修改它的第4个参数,不如跳过中间的异步方法,直接给SteamMatchmaking.CreateLobbyAsync打全局补丁:
- 找到对应重载的方法签名
- 写一个
Prefix补丁,在调用前修改参数值,还可以通过堆栈判断是否是GameNetworkManager.StartHost发起的调用,避免影响其他场景
示例代码:
[HarmonyPatch(typeof(SteamMatchmaking), nameof(SteamMatchmaking.CreateLobbyAsync))] static class CreateLobbyPatch { static bool Prefix(ref ELobbyType lobbyType, ref int maxMembers, ref string lobbyName, ref int targetParam) { // 判断是否是目标异步方法发起的调用 var stackTrace = new StackTrace(); var callingMethod = stackTrace.GetFrame(1)?.GetMethod(); if (callingMethod?.DeclaringType?.Name == "<StartHost>d__79" && callingMethod.Name == "MoveNext") { // 修改第4个参数为目标值 targetParam = 你的自定义值; } return true; // 继续执行原方法 } }
这种方法更直接,不需要处理复杂的异步枚举器类,容错性更高。
3. 修复MethodType.Enumerator的使用问题
如果坚持用MethodType.Enumerator,可能是方法签名匹配错误。异步方法的生成类MoveNext是实例方法,要确保HarmonyPatch属性正确配置:
- 目标类型设为
GameNetworkManager - 指定
methodName为StartHost - 添加
methodType: MethodType.Enumerator,同时要匹配异步方法的返回值重载(比如Task或Task<T>)
如果仍报错,说明Harmony无法正确解析自动生成的枚举器类,这时用第一种反射定位的方法更可靠。
内容的提问来源于stack exchange,提问作者redassser
相关产品推荐
相关产品推荐

