You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

C#中强制重写不可修改非虚方法?游戏DLC开发技术求助

非虚方法的子类逻辑替换方案(C#游戏DLC场景)

方案一:用Harmony进行方法钩子(游戏开发常用)

这是Unity等游戏DLC开发里最通用的解决方案,无需修改原生代码:

  • 导入Harmony库(可通过NuGet或Unity Package Manager安装)
  • 编写钩子代码拦截Player.RedBooster方法,按需替换调用逻辑:
using HarmonyLib;

[HarmonyPatch(typeof(Player), nameof(Player.RedBooster))]
public static class PlayerRedBoosterPatch
{
    // 拦截原方法,自定义执行逻辑
    static bool Prefix(Booster booster)
    {
        if (booster is PerpetualBooster perpetualBooster)
        {
            // 调用子类自定义的walk逻辑
            perpetualBooster.CustomWalk();
            return false; // 跳过原方法的执行
        }
        return true; // 非子类实例,执行原方法逻辑
    }
}
  • 在DLC初始化时启动Harmony:
var harmony = new Harmony("com.yourdlc.namespace");
harmony.PatchAll();

方案二:反射修改IL实现(无第三方库)

如果不想依赖第三方库,可手动通过反射修改Player.RedBooster的IL代码,实现类型判断与逻辑分支:

using System.Reflection;
using System.Reflection.Emit;
using System.Runtime.InteropServices;

// 获取原生方法的MethodInfo
var redBoosterMethod = typeof(Player).GetMethod(nameof(Player.RedBooster), BindingFlags.Public | BindingFlags.Instance);

// 创建动态方法替换原逻辑
var dynamicMethod = new DynamicMethod(
    "RedBoosterHook", 
    null, 
    new Type[] { typeof(Player), typeof(Booster) }, 
    typeof(Player).Module
);
var il = dynamicMethod.GetILGenerator();

// 判断传入的Booster是否为PerpetualBooster实例
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Isinst, typeof(PerpetualBooster));
var executeOriginal = il.DefineLabel();
il.Emit(OpCodes.Brfalse_S, executeOriginal);

// 是子类实例,调用自定义walk方法
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Castclass, typeof(PerpetualBooster));
il.Emit(OpCodes.Callvirt, typeof(PerpetualBooster).GetMethod(nameof(PerpetualBooster.CustomWalk), BindingFlags.Public | BindingFlags.Instance));
il.Emit(OpCodes.Ret);

// 非子类实例,执行原方法逻辑
il.MarkLabel(executeOriginal);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Call, redBoosterMethod);
il.Emit(OpCodes.Ret);

// 替换原方法的实现指针
var methodPtr = redBoosterMethod.MethodHandle.GetFunctionPointer();
Marshal.WriteIntPtr(methodPtr, dynamicMethod.MethodHandle.GetFunctionPointer());

注意:该方案需要掌握基础IL知识,且不同.NET版本可能存在兼容性差异,需在目标游戏环境中充分测试。

方案三:适配器包装(仅适用于可控实例场景)

如果你的DLC可以控制传入Player.RedBooster的Booster实例,可通过适配器包装子类逻辑:

public class PerpetualBoosterAdapter : Booster
{
    private readonly PerpetualBooster _target;

    public PerpetualBoosterAdapter(PerpetualBooster target)
    {
        _target = target;
    }

    // 结合方案二的IL修改,让Player调用适配器时触发子类逻辑
}

此方案局限性较大,仅适用于你能完全掌控Booster实例创建与传递的场景。

内容的提问来源于stack exchange,提问作者Gloups

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 19:50:12