如何将Lua变量直接映射到C++变量

How to directly map a Lua variable to a C++ variable?

本文关键字:变量 直接映射 C++ Lua      更新时间:2023-10-16

我正在C++中开发一个游戏引擎,使用Lua来定义NPC。

我可以这样定义一个原型NPC:

orc =
{
    name = "Generic Orc",
    health = 100
}
function orc:onIdle()
    print("Orc idles...")
end

然后用CCD_ 1生成一个"兽人"实例。这是一个C++函数,它从给定的表中读取health和name等值,用给定的值在C++中创建一个Entity对象,此外还为特定的NPC创建一个Lua表。

现在,我想在Lua中的orc.health变量和C++中相应Entity对象的mHealth成员变量之间建立直接连接,这样我就可以在Lua分配一个值,并立即在C++中使用它,反之亦然。

这可能吗?或者我必须使用setter/getter函数吗?我看了一眼轻量级用户数据,并在Lua中存储了一个指向C++变量的指针,但无法赋值。

这是可能的。我假设entitySpawn返回C++为实体创建的表。我还假设您可以从C++中公开一个函数,该函数接受实体的表并返回当前运行状况,同样用于设置。(您可以使用指向C++对象的轻用户数据指针作为该表的成员来实现这一点。)

所以丑陋的方式看起来是这样的:

local myOrc = entitySpawn(orc)
local curHealth = getEntityHealth(myOrc)
setEntityHealth(myOrc, curHealth + 10)

为了让它更漂亮,我们可以用跖骨玩得开心。首先,我们将放置我们关心的所有属性的访问器。

entityGetters = {
    health = getEntityHealth,
    -- ...
}
entitySetters = {
    health = setEntityHealth,
    -- ...
}

然后,我们将创建一个元表,使用这些函数来处理属性分配。

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创建entityGettersentitySettersentitySpawn(orc)0表,以及__index__newindex元方法,如果您觉得这更干净的话,但总体思路是一样的。

我没有时间给你任何代码,但请记住orc.healthorc["health"]是一样的;即orc是表,"health"是元素。

考虑到这一点,您可以更改表的indexnewindex元方法,使其具有自己的特定行为。将你的"真实"兽人实例存储为一些私有元数据,然后使用它进行更新。