Godot游戏Mod系统动态加载DLL执行方法时触发受保护内存违规
Godot C# Mod系统调用_Ready方法触发内存访问错误
场景概述
在Godot中开发游戏Mod系统,允许Mod开发者使用C#编写代码并编译为DLL,由游戏加载后执行其中方法。
加载与调用代码
程序集加载代码
string dll = // 绝对路径... if (File.Exists(dll)) { return Assembly.LoadFrom(dll); }
Mod方法调用代码
private void ExecuteModMethod(Mod mod, string methodName, object[] methodParameters) { if (!useMods) return; Type type = mod.Assembly.GetType(mod.Name+".Main"); if (type == null) return; MethodInfo method = type.GetMethod(methodName); mod.Instance = Activator.CreateInstance(type); if (method == null) return; method.Invoke(mod.Instance, methodParameters); }
Mod示例代码
using Godot; namespace TestMod { public class Main { //Called when the game is loaded public void _Ready() { GD.Print("Hello from the mod!"); } } }
错误信息
调用Mod中Main类的_Ready方法时,触发致命错误:
Fatal error. System.AccessViolationException: Attempted to read or write protected memory. This is often an indication that other memory is corrupt.
备注
- 清楚该做法存在风险,自行处理,无需提及安全性问题。
- dll路径、
type、method和mod.Instance均不为空,排除这些环节的问题。
解决办法
1. 确保版本完全匹配
Mod编译使用的Godot版本、.NET运行时版本必须与主游戏完全一致,包括Godot SDK的补丁版本、.NET框架版本(如都是.NET 6)。版本不匹配会导致Godot API绑定失效,触发内存访问错误。
2. 让Mod类继承Godot基类并使用Godot初始化流程
Godot的C# API依赖自身的脚本上下文,直接用Activator.CreateInstance创建的实例没有经过Godot的初始化,调用GD类等API时会访问无效内存。
- 修改Mod代码,让
Main类继承自Node或Reference,并重写_Ready方法:using Godot; namespace TestMod { public class Main : Node { public override void _Ready() { GD.Print("Hello from the mod!"); } } } - 修改调用逻辑,改用Godot的实例创建方式,比如通过
GD.Load<Script>()加载类型后调用New()方法创建实例:// 替代Activator.CreateInstance的示例代码 Script modScript = GD.Load<Script>($"res://Mods/{mod.Name}/Main.cs"); mod.Instance = modScript.New();
3. 调整程序集加载方式
尝试使用Assembly.LoadFile替代Assembly.LoadFrom,加载时确保Mod程序集能正确引用主游戏中的Godot核心程序集,避免上下文冲突。
4. 捕获调用栈定位问题
在Visual Studio中附加到游戏进程,启用调试模式,捕获错误的完整调用栈,明确是哪一行代码触发的内存错误,便于精准排查。
内容的提问来源于stack exchange,提问作者GoogleCoder
相关产品推荐
相关产品推荐

