1

我正在为我目前正在使用 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了解我做错了什么,但我没有任何反应。

我很欣赏这方面的任何指导,我已经看了几天没有弄清楚,并且在线搜索通常只显示与我已经在做的类似的代码。

4

2 回答 2

0

我不得不承认,我不完全确定,通过在 LUA 而不是 C# 中编写包装类然后公开该类型来尝试实现什么,但我注意到了这一点:

对我来说NativeClass .__new() 从来没有像你试图在 MoonSharp 中那样成功

self.__codeElement = BLU_UIElement.__new();

出于这个原因,我为我的本机类创建了自定义构造函数,并将它们作为委托传递给全局命名空间(尽管它的类型必须被注册)。它看起来很像您通常会构造一个对象。只是没有 new 关键字:

在 C# 中

public NativeClass{

   public static NativeClass construct()
   {
      return new NativeClass();
   }

}

将静态方法作为委托传递给脚本:

script["NativeClass"] = (Func<NativeClass>)NativeClass.construct;

然后你可以在 MoonSharp 中创建一个这样的新实例:

x = NativeClass()

编辑:所以没有读到你试图用一个字符串来做到这一点。也许您应该考虑不在 LUA 中而是在 C# 中编写包装类,或者是否有禁止这样做的原因?

于 2019-05-14T10:45:39.353 回答
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
于 2019-05-15T06:10:19.140 回答