You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

使用MoonSharp在Lua中遍历C#字典遇类型转换异常求助

解决MoonSharp中IDictionary无法自动转为Lua表的问题

我之前也踩过MoonSharp类型转换的类似坑,你遇到的ScriptRuntimeException: bad argument #1 to 'next' (table expected, got userdata)错误,主要是因为MoonSharp的自动类型转换没有正确识别你的IDictionary实例,下面是几个常见的原因和对应的解决办法:

1. 未注册CLR集合类型的转换支持

MoonSharp默认不会自动处理所有CLR集合类型的转换,你需要手动注册DictionaryIDictionary的类型转换器,或者直接启用标准集合的转换支持。

在初始化Lua环境的时候,添加这段代码:

// 一次性启用当前程序集中所有CLR类型的UserData支持(包括集合)
UserData.RegisterAssembly();

// 或者精准注册你用到的字典类型
UserData.RegisterType(typeof(Dictionary<int, Entity>));
UserData.RegisterType(typeof(IDictionary<int, Entity>));

注册之后,MoonSharp就会知道如何把你的Entities字典转换成Lua可识别的表结构了。

2. 只读接口类型导致转换失效

MoonSharp对接口类型的自动转换支持不如具体类稳定,虽然你的Entities实际实例是Dictionary<int, Entity>,但声明为IDictionary<int, Entity>可能会让MoonSharp无法正确识别它的集合特性。

你可以尝试把字段声明改成具体的实现类:

public readonly Dictionary<int, Entity> Entities = new Dictionary<int, Entity>();

之后再重新注册类型,Lua环境就能正确解析并转换这个字典了。

3. 检查World对象的暴露方式

如果World是通过UserData暴露给Lua的,要确保Entities字段是公共可访问的,并且MoonSharp能正确解析它的类型。你可以先在Lua里打印type(World.Entities),如果输出是userdata,说明转换确实没生效,这时候就需要回到前面的类型注册步骤排查。

另外,确认你是通过正确的方式把World实例传给Lua的,比如:

script.Globals["World"] = yourWorldInstance;

4. 手动转换为MoonSharp Table(兜底方案)

如果上面的方法都不奏效,你可以手动把字典转换成MoonSharp的Table对象,再暴露给Lua:

var luaTable = new Table(yourLuaScriptInstance);
foreach (var kvp in yourWorldInstance.Entities)
{
    luaTable[kvp.Key] = kvp.Value;
}
yourLuaScriptInstance.Globals["Entities"] = luaTable;

之后在Lua里直接用for k,v in pairs(Entities) do -- something end就能正常遍历了。


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

火山引擎 最新活动