我正在为当前正在使用C#开发的游戏创建一些UI,并希望将所有内容公开给Lua,以便我的美术师可以进行细微调整而无需执行任何代码。我正在使用MoonSharp将Lua脚本集成到我的项目中。
这是我的UIElement包装类当前拥有的内容:
UIElement = {};
UIElement.__index = UIElement;
setmetatable( UIElement, {
__index = function( self, key )
local codeElement = rawget( self, "__codeElement" );
local field = codeElement and codeElement[key];
if type( field ) == "function" then
return function( obj, ... )
if obj == self then
return field( codeElement, ... );
else
return field( obj, ... )
end
end;
else
return field;
end
end,
__call = function( cls, ... )
return cls.new( ... );
end,
} );
function UIElement.new()
local self = setmetatable( {}, UIElement );
self.__codeElement = BLU_UIElement.__new();
return self;
end
BLU_UIElement 是我的C#类,该类通过MoonSharp API向Lua公开。直接与对象一起使用时,它可以正常工作,并具有SetPos,SetColor等功能。
UIElement 旨在成为Lua中包装和扩展C#对象的“类”。
当我在脚本的其他地方实例化UIElement并尝试调用一个函数(例如SetPos)时,它确实正确地进入了__index函数。但是,rawget调用始终返回nil。它似乎也不特定于BLU_UIElement。我已经尝试了一些非常简单的方法,例如在构造函数中添加字符串ID值,并尝试在__index函数中将其原始获取,但是它也会返回nil。
我假设我只是在做一些错误的事情,在类或对象本身上设置了元稳定器,但是我不确定问题出在哪里。我一直在这里寻找:http://lua-users.org/wiki/ObjectOrientationTutorial,以获取关于我做错了什么的想法,但我没有发现任何事情。
我很高兴对此有任何指导,我已经花了几天的时间来研究它,但仍未弄清楚,而在线搜索通常只会显示与我已经在做的类似的代码。
答案 0 :(得分:0)
我必须承认,我不确定是否要通过在LUA(而不是C#)中编写包装类,然后公开该类型来实现的目标,但是我注意到了这一点:
对我来说 NativeClass .__ new()从未在MoonSharp中解决,就像您尝试在
self.__codeElement = BLU_UIElement.__new();
由于这个原因,我为本机类创建了自定义构造函数,并将它们作为委托传递给全局命名空间(尽管必须注册其类型)。看起来很像您通常会构造一个对象。只是没有新的关键字:
在C#中
public NativeClass{
public static NativeClass construct()
{
return new NativeClass();
}
}
将静态方法作为委托传递给脚本:
script["NativeClass"] = (Func<NativeClass>)NativeClass.construct;
然后您可以在MoonSharp中创建一个新的实例,
x = NativeClass()
编辑:所以没有读到您尝试使用字符串执行此操作。也许您应该考虑不在LUA中编写包装类,而在C#中编写,还是有理由禁止这样做?
答案 1 :(得分:0)
我有一个朋友,对Lua的元数据的了解远比对我的了解多。如果答案对其他人有帮助,请在此处发布答案。
问题是我试图将UIElement表既用作“类”表又用作“对象”元表。在__index函数中调用rawget时,它试图在UIElement表中查找内容,而不是在UIElement.new()中创建的self表中查找内容。将这两个拆分成不同的表(一个用于类,一个用于对象元表)可以解决问题。
这是我更新后的有效代码:
UIElement = {};
setmetatable( UIElement, {
__call = function( cls, ... )
return cls.new( ... );
end,
} );
UIElement.objectMetaTable = {
__index = function( self, key )
local objectValue = rawget(self, key);
if objectValue ~= nil then
return objectValue;
end
local classValue = UIElement[key];
if classValue ~= nil then
return classValue;
end
local codeElement = rawget(self, "__codeElement");
if codeElement then
return codeElement[key];
end
end,
};
function UIElement.new()
local newInstance = setmetatable( { id = "blah" }, UIElement.objectMetaTable );
newInstance.__codeElement = BLU_UIElement.__new();
return newInstance;
end