我一直在为游戏开发学习一些lua。我听说过其他语言的协同程序,但是真的在lua中找到了它们。我只是不明白它们有多有用,我听到很多人都在谈论如何做一个多线程的东西,但是它们不是按顺序运行的吗?那么顺序运行的普通函数会带来什么好处呢?我只是没有得到它们与函数有多么不同,只是它们可以暂停并让另一个运行一秒钟。似乎用例场景对我来说不会那么大。
任何人都想清楚为什么有人会从中受益?
特别是从游戏编程角度来看,洞察力会很好^^
答案 0 :(得分:17)
好的,请考虑游戏开发。
假设你正在做一个过场动画或者教程。无论哪种方式,您拥有的是发送到某些实体的有序命令序列。一个实体移动到一个位置,与一个人交谈,然后走到其他地方。等等。有些命令在其他命令完成之前无法启动。
现在回顾一下你的游戏是如何运作的。每一帧,它必须处理AI,碰撞测试,动画,渲染和声音,以及其他可能的事情。你只能思考每一帧。那么你如何把这种代码放在哪里,你必须等待一些动作才能完成下一个呢?
如果你用C ++构建了一个系统,你所拥有的就是在AI之前运行的东西。它将有一系列要处理的命令。其中一些命令是即时的,例如“告诉实体X去这里”或“在这里产生实体Y”。其他人则必须等待,例如“告诉实体Z去这里并且不再处理命令,直到它已经到了这里。”必须在每一帧调用命令处理器,并且必须理解复杂的条件,例如“实体在位置”等等。
在Lua中,它看起来像这样:
local entityX = game:GetEntity("entityX");
entityX:GoToLocation(locX);
local entityY = game:SpawnEntity("entityY", locY);
local entityZ = game:GetEntity("entityZ");
entityZ:GoToLocation(locZ);
do
coroutine.yield();
until (entityZ:isAtLocation(locZ));
return;
在C ++大小上,您将每帧恢复一次此脚本,直到完成为止。一旦它返回,你知道过场动画已经结束,所以你可以将控制权交还给用户。
看看Lua逻辑是多么简单。它完全符合它的说法。它很明显,很明显,因此很难出错。
协同程序的功能是能够部分完成某项任务,等待条件变为真,然后继续执行下一个任务。答案 1 :(得分:0)
我们在我正在进行的项目中使用它们。对我们来说,主要的好处是,有时使用异步代码,有些重点是某些部分由于某些依赖性而按顺序运行。如果使用协同程序,则可以强制一个进程等待另一个进程完成。它们不是唯一的方法,但它们可以比其他方法简单得多。
答案 2 :(得分:0)
我只是没有得到它们与函数的区别 他们可以停下来让另一个人跑一秒钟。
这是一个非常重要的财产。我参与了一个使用它们进行计时的游戏引擎。例如,我们有一个每秒运行10个滴答的引擎,你可以WaitTicks(x)等待x个滴答,在用户层,你可以运行WaitFrames(x)来等待x帧。
即使是专业的本机并发库也会使用相同类型的让步行为。
答案 3 :(得分:0)
游戏开发者有很多很好的例子。我将在应用程序扩展空间中给出另一个。考虑一下这样的场景:应用程序有一个引擎可以在Lua中运行用户例程,同时在C中执行核心功能。如果用户需要等待引擎进入特定状态(例如,等待接收数据),你要么:
第三个选项对我来说最容易实现,避免了在多个平台上处理多线程的需要。它还允许用户的代码未经修改地运行,就像他们调用的函数需要很长时间一样。
答案 4 :(得分:0)
游戏中的协同程序: 易于使用,在许多地方使用时易于拧紧。
请小心,不要在很多地方使用它。 不要让整个AI代码依赖于Coroutines。
当引入以前不存在的状态时,协同程序可以快速修复。
这正是java所做的。睡眠()和等待() 这两种功能都是使游戏无法调试的最佳方式。 如果我是你,我会完全避免任何必须使用像Coroutine那样的Wait()函数的代码。
OpenGL API是您应该注意的事项。它从不使用wait()函数,而是使用一个干净的状态机,它可以准确地知道对象的状态。 如果您使用协同程序,那么最终会出现如此多的无状态代码,因此调试它们肯定会无法容忍。
当你创建像Text Editor ..bank application .. server ..database等(不是游戏)这样的应用程序时,协同程序是很好的。 当你制作一个任何时候都可能发生任何事情的游戏时,你需要拥有状态。
因此,在我看来协同程序是一种糟糕的编程方式,也是编写小型无状态代码的借口。
但那只是我。