Lua嵌入C++中是否能够拥有持久局部变量?如果不能,那么有哪些脚本语言可以实现这点?
使用 LuaBind 将 Lua 嵌入我的 C++ 应用程序。我需要有跨越多个运行时的变量,不能被运行相同文件名的其他对象访问。
例如:假设我有一个名为 NPC 的类。一个 NPC 拥有一个字符串,即它运行的脚本的名称。当创建 NPC 时,会创建一个名为 Health 的变量。当 NPC 被击中时,它们会失去 5 点生命值。脚本应该像这样在 Lua 中:
local health = 10
function onHit()
health = health - 5
end
我所拥有的问题是运行这个脚本的每个 NPC 都没有自己的健康实例。例如,假设我创建 NPC A,并从其健康状况中减去 5 点。然后,我创建 NPC B。因为它将健康值重置为 10,所以如果我告诉 NPC A 打印健康值,它将给我返回 10,尽管它应该是 5。
如果我为每个对象拥有一个不同的 Lua 实例,那么它将按照这种方式工作,但我会同时拥有数百个实例,我理解这不是一个好事情。
是否有办法使变量在 Lua 中像这样工作?如果没有,是否有一种脚本语言能够以有效的方式工作?
以下是我正在测试的代码:
Lua:
local health = 10;
function onHit()
health = health - 5
print_out(health)
end
C++:
class NPC
{
public:
NPC(lua_State* inState);
void onHit();
const char* behavior;
lua_State* luaState;
};
NPC::NPC(lua_State* inState)
{
luaState = inState;
behavior = "testBehavior.lua";
luaL_dofile(luaState, behavior);
}
void NPC::onHit()
{
luaL_loadfile(luaState, behavior);
luabind::call_function<int>(luaState, "onHit");
}
void print_out(int number) {
cout << "Health : " << number << endl;
}
int main()
{
lua_State *myLuaState = luaL_newstate();
luabind::open(myLuaState);
luabind::module(myLuaState) [
luabind::def("print_out", print_out)
];
NPC test(myLuaState);
NPC test2(myLuaState);
test.onHit();
test2.onHit();
test.onHit();
lua_close(myLuaState);
}
可能看起来有点过头,但为什么不将所需的值存储在 SQLite 表中呢?
你可以去了解一下 Lua 的 闭包。它看起来像这样:
function healthPoints()
local health = 10
return function()
health = health - 5
return health
end
end
这样每个 NPC 都有自己的函数和计数器。每次他们被攻击时,只需调用 onHit 函数。使用方法如下:
npc1.onHit = healthPoints()
npc2.onHit = healthPoints()
npc1.onHit() -- 现在为 5,而 npc2 仍为 10
你可以像这样添加参数:
function healthPoints(hp)
local health = hp
return function(dmg)
health = health - dmg
return health
end
end
npc1.onHit = healthPoints(100)
npc1.onHit(-12)
我认为这值得一试。
参考一下,这是我正在测试的代码:
这里有很多问题。你不断地重新运行你的 Lua 脚本;这就是为什么它一直被重置的原因。另一个问题是,你的脚本正在创建一个全局函数,因此每次运行它时,你都会得到一个新的全局函数,它使用一个新的 local 变量。
停止使用全局变量。每个 NPC 都是一个独立的对象。因此,它需要有对象特定的数据。
behavior = "testBehavior.lua";
luaL_dofile(luaState, behavior);
这不会创建任何对象特定的数据。它只是运行一个 Lua 脚本,并完全放弃任何返回值。除非该脚本实际上将某些对象特定的内容全局存储,否则不会创建任何对象特定的数据。
你的 Lua 脚本需要返回一个包含对象特定数据的表格,该脚本需要这些数据来处理对象。脚本应该像这样:
local function onHit(self)
self.health = self.health - 5
end
return {
health = 10,
onHit = onHit,
}
你的 C++ 代码需要在 NPC 类中 存储 这个表格,然后使用它。这可以通过 Luabind 调用轻松完成。你的构造函数应该像这样:
NPC::NPC(lua_State* L)
{
behavior = "testBehavior.lua";
int err = luaL_loadfile(L, behavior);
//处理编译器错误。千万不要忘记这个!
luabind::object func = luabind::from_stack(L, -1);
lua_pop(L, 1);
luaData = func(); //为运行时错误捕获异常
lua_pop(L, 1);
}
在你的类中,不要有 lua_State* luaState,而要保留一个 luabind::object luaData。如果需要 lua_State,则可以从 luabind::object 中获取一个。
要调用你的 Lua onHit 函数,只需使用 luabind::object 接口:
void NPC::onHit()
{
luaData["onHit"](luaData);
}
请注意,你 不需要 重新运行 Lua 脚本。这就是你的问题所在。你只需调用 Lua 脚本已经定义的函数。
现在,你似乎希望使用局部变量而不是表格内存。这很好;这将防止 C++ 代码直接访问 health(除非使用技巧)。这会简化我们的代码,因为我们不必将 luaData 传递给 onHit。你可以在 Lua 中这样做:
local health = 10
local NPC = {}
function NPC.onHit()
health = health - 5
end
return NPC
NPC 构造函数不需要更改;只需要更改我们调用 onHit。
void NPC::onHit()
{
luaData["onHit"]();
}
如果你坚决要使用全局变量,你可以操纵环境,但这相当复杂。它将提供确保个别脚本调用之间的隔离。
- 如何将两个不同的lua文件合成一个 东西有点长 大佬请耐心看完 我是小白研究几天了都没搞定
- 如何在roblox studio中1:1导入真实世界的地形?
- 求解,lua_resume的第二次调用继续执行协程问题。
- 【上海普陀区】内向猫网络招募【Skynet游戏框架Lua后端程序员】
- SF爱好求教:如何用lua实现游戏内调用数据库函数实现账号密码注册?
- Lua实现网站后台开发
- LUA错误显式返回,社区常见的规约是怎么样的
- lua5.3下载库失败
- 请问如何实现文本框内容和某个网页搜索框内容连接,并把网页输出来的结果反馈到另外一个文本框上
- lua lanes多线程使用
- 一个kv数据库
- openresty 有没有比较轻量的 docker 镜像
- 想问一下,有大佬用过luacurl吗
- 在Lua执行过程中使用Load函数出现问题
- 为什么 neovim 里没有显示一些特殊字符?
- Lua比较两个表的值(不考虑键的顺序)
- 有个lua简单的项目,外包,有意者加微信 liuheng600456详谈,最好在成都
- 如何在 Visual Studio 2022 中运行 Lua 代码?
- addEventListener 返回 nil Lua
- Lua中获取用户配置主目录的跨平台方法
我不了解 Lua,所以我不能谈论那个。这个问题也标记了 Python。对于 Python,我认为你可以序列化所有重要的本地变量。
另外,您可以查看我的技巧,在此处持久化称为 PyDON 的字典:http://code.activestate.com/recipes/577508-pydon-an-alternative-to-xml/
还要检查这个,我认为这将更有帮助:如何将 Python 字典序列化为字符串,然后再转回字典?