#c# #lua #moonsharp
#c# #lua #moonsharp
Вопрос:
Я создаю некоторый пользовательский интерфейс для игры, над которой я сейчас работаю на C #, и хочу предоставить все вплоть до 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 #, который доступен для Lua через MoonSharp API. Он работает должным образом при работе непосредственно с объектом и имеет такие функции, как SetPos, setColor и т.д.
UIElement предназначен для того, чтобы быть моим «классом» в Lua для переноса и расширения моего объекта C #.
Когда я создаю экземпляр UIElement в другом месте скрипта и пытаюсь вызвать функцию (например, SetPos ), она правильно попадает в функцию __index . Однако вызов rawget всегда возвращает nil . Это также не похоже на BLU_UIElement . Я уже пробовал что-то очень простое, например, добавить значение string ID в конструктор и попытаться получить его в rawget в функции __index , но он также возвращает nil .
Я предполагаю, что я просто делаю что-то неправильно, настраивая метастабилизатор либо для класса, либо для самого объекта, но я не совсем уверен, в чем проблема. Я искал здесь: http://lua-users.org/wiki/ObjectOrientationTutorial чтобы получить представление о том, что я делаю не так, но мне ничего не приходит в голову.
Я ценю любые рекомендации по этому поводу, я смотрел на это пару дней, не разбираясь в этом, и поиск в Интернете, как правило, просто показывает код, аналогичный тому, что я уже делаю.
Ответ №1:
Я должен признать, что я не совсем уверен, чего вы пытаетесь достичь, написав свой класс-оболочку на 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 #, или есть причина, которая запрещает это?
Комментарии:
1. Я хотел выполнить основную часть работы в Lua по двум причинам. Большая проблема заключается в том, что это делает систему пользовательского интерфейса немного более модульной, поэтому, если мы меняем движки или языки, единственное, что нужно изменить, это один базовый класс, определенный в C #, в то время как все остальные вещи, определенные в Lua, остаются неизменными. Вторая причина заключается в том, что я работаю с некоторыми некодерами в моей команде. Они открыты для редактирования файлов Lua и создания новых классов или функций в соответствии со своими потребностями. Однако они нервничают, когда кто-то просит их коснуться кода.
Ответ №2:
У меня был друг, у которого гораздо больше опыта работы с метатаблицами Lua, чем у меня, взгляните. Публикую ответ здесь на случай, если он поможет кому-либо еще.
Проблема заключалась в том, что я пытался использовать таблицу UIElement как в качестве таблицы «class», так и в качестве метатаблицы «object». При вызове rawget внутри функции __index он пытался найти что-то в таблице UIElement вместо собственной таблицы, созданной в UIElement.new() . Разделение этих двух таблиц на отдельные таблицы (одна для класса, одна для объекта metatable) исправило ситуацию.
Вот мой обновленный и рабочий код:
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