Lua如何使一个脚本在不同的脚本加载中保持其值?
我目前遇到的问题是有几个敌人共享同一个A.I.脚本,但还有另一个对象会执行不同的操作。脚本中的函数被称为AILogic。我希望这些敌人能够独立移动,但这很难。我尝试了以下方法:
1)在敌人的构造函数中调用dofile
,然后在每个游戏循环的Update
函数中调用它的脚本函数。问题是Lua只使用最后一个构造的敌人的脚本,所以所有敌人在Update
函数中运行相同的脚本。因此,我描述的这个对象不使用相同的A.I.脚本正在使用其他敌人的脚本。
2)在Update
函数中调用dofile
,然后立即调用它的脚本函数。问题是dofile
在每个对象的更新函数中都被调用,因此在AILogic函数运行并更新该脚本的数据后,当为另一个敌人调用dofile时整个过程会被重置。我最大的问题在于是否有一种方法可以保留脚本中的值,即使我切换到运行不同的脚本。
我已经阅读了关于Lua函数环境的文章,但我不确定如何正确实现它们。这是正确的方向吗?任何建议都将不胜感激,谢谢。
编辑:我还考虑在Lua脚本之外创建一个单独的地方来存储数据。
编辑2:添加了一些示例代码。(只是用于获得功能运行的测试)。
-- 粘液的脚本
local count = 0;
function AILogic(Slime)
-- 让史莱姆在圆形(四边形)中移动
if count < 4 then
Slime: MoveDir(0);
elseif count < 8 then
Slime: MoveDir(2);
elseif count < 12 then
Slime: MoveDir(1);
elseif count < 16 then
Slime: MoveDir(3);
else
count = 0;
end
count = count + 1;
end
原文链接 https://stackoverflow.com/questions/2353431
lua 解释器将每行作为单独的代码块运行,这意味着局部变量只在该行中有效,因此示例代码不能像原样运行。要么一次性运行所有代码(没有换行),不使用局部变量,或者在 do ... end
块中运行。
至于开篇的问题,如果你想共享完全相同的函数(即运行时完全相同的函数),则函数需要将数据作为参数传递。但是,如果您可以使用相同的代码但不同的(运行时)函数,则可以使用闭包来保存本地/个体数据。
local function make_counter()
local count = 0
return function ()
local c = count
count = count + 1
return c
end
end
c1 = make_counter()
c2 = make_counter()
c3 = make_counter()
print(c1())
print(c1())
print(c1())
print(c1())
print(c2())
print(c3())
print(c2())
print(c3())
print(c2())
print(c3())
或者,您可以每次调用函数时玩弄其环境,但这只对某些情况有效(取决于函数的内部实现)。
- 如何在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 模式将字符串(嵌套数组)转换为真正的数组?
这个问题的官方参考文献是链接文本。简单解释一下,我们将从网站中的以下代码开始:
a = 1 local newgt = {} -- create new environment setmetatable(newgt, {__index = _G}) setfenv(1, newgt) -- set it
第一行设置了(全局)变量“a”。您可以将其视为为代码设置默认值。(请记住,Lua中除非您使用“local”声明它们,否则所有变量都是全局的。)
下一行创建了一个表,这将是您的新环境。它是局部的,只能在您执行的函数/块中使用,因此不会被任何其他运行的程序所破坏。
第三行是魔法的开端。要理解它,您必须理解元方法。然而在本质上,您正在使用Lua的元魔法来确保在您即将使用的函数环境中未定义的全局名称在您之前的全局环境的上下文中解析。基本意思是,如果你在你的函数环境中使用了一个没有定义的名字,Lua就会自动地搜索你曾经拥有的全局环境中的名字。(简言之,是继承。)
第四行是你想要的地方。Setfenv(1,...)表示这将为您当前的函数更改环境。(对于调用函数,您可以使用2,对于调用函数的调用程序,您可以使用3等。一直往上。)第二参数是您刚刚设置的表格,包括旧行为的继承。您的函数现在正在执行一个新的全局环境中。它有旧环境中所有的名称和值方便使用(包括函数和您放置在其中的全局变量“a”)。但是如果您写入一个名称,则不会覆盖全局状态。它将覆盖您的本地副本。
考虑以下后续代码:
a = 10 b = 20
现在,您已经使您的函数环境表如下所示:
您的“全局”环境简而言之只包含两个变量:a(值为10)和b(值为20)。当您稍后访问“a”时,您将获得您的本地副本,其中包括10个旧全局值存储在您的元表中,现在已被掩盖,并且仍设置为1-如果您访问“b”,您将获得20,即使最初的全局状态可能甚至没有变量“b”可访问。您仍然能够访问此点之前定义的所有函数等。
编辑以添加调试OP问题的测试代码。
我将以下代码放入“junk.lua”中:
a = 1 local newgt = {} setmetatable(newgt, {__index = _G}) setfenv(1, newgt) print(a) a = 10 print(a) print(newgt)
它的输出如下:
$ lua junk.lua 1 10 table: 0x976d040
这是使用Lua 5.1.4。您看到的输出是什么?