0

我使用 Lua 作为我的游戏引擎逻辑。我的主要游戏循环没有在 Lua 中完成。只有场景层次结构中的特殊节点附加了 Lua 脚本。这些脚本每帧执行一次。我面临的问题是我需要将全局变量值从一帧保存到另一帧。

我的临时解决方案如下所示:

finish = useBool("finish", false)
timer = useInt("timer", 0)
showTimer = useBool("showTimer", true)
startTimer = useInt("startTimer", 0)
play0 = useBool("play0", false)
play1 = useBool("play1", false)
play2 = useBool("play2", false)
play3 = useBool("play3", false)
delta = useInt("delta", 0)
gameOverTime = useInt("gameOverTime", 5000)
finishTime = useInt("finishTime", 5000)
checkPoint = useInt("checkPoint", 255)

<...> Game logic <...>

setInt("message", message);
setInt("checkPoint", checkPoint)
setInt("finishTime", finishTime)
setInt("gameOverTime", gameOverTime)
setInt("timer", timer)
setBool("play3", play3)
setBool("play2", play2)
setBool("play1", play1)
setBool("play0", play0)
setInt("startTimer", startTimer)
setBool("showTimer", showTimer)
setInt("timer", timer)
setBool("finish", finish);

我在开始时调用了从 C++ 中的哈希映射中检索全局变量的特殊方法,并在脚本末尾再次设置它们。

有没有办法隐含地做到这一点?

不使用 Lua 作为主要游戏循环是一个糟糕的设计吗?

4

1 回答 1

3

好吧,虽然您的解决方案在技术上没有任何问题,但如果您最终使用大量全局变量(通常应该避免的),您可能会开始注意到一些性能问题。

话虽如此,仍有改进的余地。例如:

在脚本的开头,检查您的全局变量是否为nil. 如果是,那么你可以初始化它,如果不是,这可能不是你第一次运行脚本,所以不要修改它。但这意味着很多讨厌的if-else陈述,很容易忘记。我们可以做得更好!

我建议您阅读《Lua 编程》一书中的第 14 章:环境。这是介绍中的快速引用:

Lua 将其所有全局变量保存在一个常规表中,称为环境。...另一个(实际上是主要的)优点是我们可以像操作其他任何表一样操作该表。为了方便这种操作,Lua 将环境本身存储在一个全局变量 _G 中。(是的,_G._G 等于 _G。)

由于_G是一个表,它也有一个元表,因此您可以定义元方法来处理对全局变量的访问和创建__index您可以在第 14.2 节__newindex中找到这方面的示例。去阅读整章吧,它并不长(如果你不熟悉元方法和元表,也可以看看第 13 章——这是 Lua 在灵活性方面真正闪耀的地方)。

既然我们已经介绍了琐碎和普通的方法,让我们来看看光谱的过度杀伤力。作为一个例子,我将看看 Unity 的脚本编写方法。Unity javascript 通常定义变量、函数和类型。任何在方法或类型范围之外定义的变量都会在帧之间持久化,因为脚本本身并不是每帧都执行的。相反,他们让脚本定义函数并在适当的时间调用函数。因此,如果您希望每帧都执行某些操作 - 您可以将其放入Update函数中。每个脚本都可以定义自己的Update函数,因为它有自己的范围。因此,脚本引擎的每一帧都会遍历所有对象,检查脚本的作用域是否有Update方法并调用它。

回到 Lua - 这样的解决方案将涉及为每个对象/脚本/无论您的节点是什么创建单独的环境。然后,您的主循环将遍历所有节点并在其环境中运行一个函数,而不是每帧执行附加到您的节点的脚本。您还可以切换环境,因此您可以在执行之前将全局环境设置为节点的 env,然后在完成后切换回来。这允许您的脚本在他们认为合适的时候使用全局变量,让它们在帧之间保持不变,并排除名称冲突或全局命名空间污染的可能性。此外,您可以使用元方法将节点的环境嵌套在实际的全局环境中或使用辅助方法的 API 环境中(基本上,__indexparent)。

于 2012-11-22T10:24:16.877 回答