SpringRTS/Gadgets 中的 Lua
Gadgets 是脚本文件,必须由所有玩家提供。这就是为什么 Gadgets 在模组和地图中使用的原因,因为它们应该始终具有完全相同的数据。Gadgets 可以从同步和异步模式中使用调用和回调,但你需要一种特殊的方法来让同步和异步代码相互通信。
制作 Gadget 时,始终将同步代码与异步代码分开。可以使用以下方法实现:
if (gadgetHandler:IsSyncedCode()) then
-- Synced code here --
else
-- Unsynced code here --
end
这样可以确保代码块位于正确的位置。不使用 gadgetHandler:IsSyncedCode() 将导致代码在同步和异步模式下都执行。这种情况在很多情况下会导致错误,因此不建议这样做。请指定代码是在同步模式下使用还是异步模式下使用。
制作 Gadget 时,始终将游戏事件(UnitCreated()、UnitDestroyed() 等)放置在同步代码块中,而仅与 Lua 图形相关的事件应放置在异步代码块中。
确定某项操作是否应该放置在异步代码或同步代码中的一种简单方法是,判断代码是否应该对所有用户产生相同的效果,还是只对您产生效果。Lua 图形放置在异步代码中的原因是,即使一名用户没有获得正确的图形,也不意味着其他玩家也会遇到相同的问题。因此,这样做可以使游戏流程顺畅。例如,如果 UnitDestroyed() 位于异步代码中,那么电脑较慢的玩家可能会延迟收到事件,从而导致游戏不可玩,因为他的事件会延迟。
在同步和异步代码之间通信的一种方法是使用全局变量。我们使用 Lua 中的 _G 表将变量添加为全局变量
_G.variable=variable --we assign variable to the global table
下面演示了通过全局变量进行同步/异步通信
--SYNCED CODE
if (gadgetHandler:IsSyncedCode()) then
local number = 10 -- declaring local variable 'number'
function gadget:SomeSyncedCallin(...)
number=number+1 -- increment variable's value by one
_G.number=number -- save the new value into a global variable
end
else
--UNSYNCED CODE
function gadget:Update(...) -- here goes some unsynced callin. we use Update to see the result in real time
Spring.Echo(SYNCED.number) -- print the global variable's value on screen
end
end
在示例中,我们在同步代码部分声明了一个局部变量,并在同步模式下尝试更改它的值。然后,我们将该值保存为全局变量。之后,如果我们想在异步代码中读取该值,只需使用 "SYNCED." 表即可。
第二种方法是使用 SendToUnsynced() 函数。