这是可能的。我假设 entitySpawn 返回 C++ 为实体创建的表。我还将假设您可以从 C++ 公开一个函数,该函数接受一个实体的表并返回当前的运行状况,并且类似地用于设置。 (您可以使用指向 C++ 对象的轻量级 userdata 指针作为该表的成员来实现。)
所以丑陋的方式看起来像这样:
local myOrc = entitySpawn(orc)
local curHealth = getEntityHealth(myOrc)
setEntityHealth(myOrc, curHealth + 10)
为了让这个更漂亮,我们可以在元表中找到一些乐趣。首先,我们将为我们关心的所有属性放置访问器。
entityGetters = {
health = getEntityHealth,
-- ...
}
entitySetters = {
health = setEntityHealth,
-- ...
}
然后我们将创建一个metatable,它使用这些函数来处理属性分配。
entityMetatable = {}
function entityMetatable:__index(key)
local getter = entityGetters[key]
if getter then
return getter(self)
else
return nil
end
end
function entityMetable:__newindex(key, value)
local setter = entitySetters[key]
if setter then
return setter(self, value)
end
end
现在您需要让entitySpawn 分配元表。您可以使用 lua_setmetatable 函数来执行此操作。
int entitySpawn(lua_State* L)
{
// ...
// assuming that the returned table is on top of the stack
lua_getglobal(L, "entityMetatable");
lua_setmetatable(L, -2);
return 1;
}
现在你可以写得很好了:
local myOrc = entitySpawn(orc)
myOrc.health = myOrc.health + 10
请注意,这要求entitySpawn 返回的表不 具有健康属性集。如果是这样,则永远不会针对该属性咨询元表。
您可以使用 C++ 而不是 Lua 创建 entityGetters、entitySetters 和 entityMetatable 表,以及 __index 和 __newindex 元方法,如果您觉得这样更简洁的话,但总体思路是一样的。