Lua保留了全球价值观

时间:2012-11-21 09:12:48

标签: c++ lua

我使用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作为主要游戏循环是不是一个糟糕的设计?

1 个答案:

答案 0 :(得分:3)

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

据说,还有改进的余地。例如:

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

我建议您阅读Lua中的Programming in book中的Chapter 14: The Environment。以下是介绍中的快速报价:

  

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

由于_G是一个表,它也有一个元表,因此您可以定义__index__newindex元方法来处理全局变量的访问和创建。您可以在section 14.2中找到相关示例。阅读整章,不是那么久(如果你不熟悉元方法和元数据,也可以浏览chapter 13 - 这就是Lua在灵活性方面真正闪耀的地方)。

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

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