如何在 Lua 中结束循环协程?
Posted
技术标签:
【中文标题】如何在 Lua 中结束循环协程?【英文标题】:How to end a looping coroutine in Lua? 【发布时间】:2014-03-18 18:51:21 【问题描述】:我目前正在使用 Roblox(使用 Lua)开发一款游戏。它基本上是由几个小游戏组成的。在每一轮开始时,游戏中的所有玩家都被放在一张桌子上并传送到一个区域。这就是协程发挥作用的地方。随着回合的进行,我想要一个协程开始。协程每秒检查玩家的生命值是否低于零,如果是,则将其从 currentPlayer 表中删除。
对不起,如果我没有正确描述问题,但协程不会产生。我以前没有使用过协程,所以我可能试图以错误的方式产生它。我知道你们大多数人不会熟悉 Roblox,但 Lua 语法是一样的。
谁能给我一个如何结束循环协程的例子?
currentPlayers =
roundTime = 60
local lookForWinners = coroutine.create(function()
while coroutine.running do
wait(1)
for i, v in pairs(currentPlayers) do
if v.Character.Humanoid.Health <= 0 then
table.remove(currentPlayers, v)
end
end
end
end)
while wait() do
repeat display("Two or more players need to be in the game.", 1) until #_G.plrs > 1 --Ignore, just checks if two+ players are in game.
display("Picking a map...", 3) pickMap()
teleport(0, 500, 0)
coroutine.resume(lookForWinners)
wait(roundTime)
print("Round over")
coroutine.yield(lookForWinners)
end
【问题讨论】:
感谢您修复代码,我没有正确发布它。 【参考方案1】:Lua 是一种单线程语言。协程不会导致函数并行执行。
协程实际上只是一种创建可以暂停其自身执行的函数(使用coroutine.yield
)的方法,该函数可以从外部恢复(使用coroutine.resume
)。 There is no "coroutine.running":在任何给定时间只有一行“正在运行”。
如果 Roblox 旨在让您使用 wait()
跳出 Lua 线程,您可以将其编写为一系列循环,检查它们的条件,然后调用 wait()
:
local currentPlayers=
local roundTime = 60
while #_G.plrs > 1 do
display("Two or more players need to be in the game.", 1)
wait()
end
display("Picking a map...", 3) pickMap()
teleport(0, 500, 0)
for i=0, roundTime do
for i, v in pairs(currentPlayers) do
if v.Character.Humanoid.Health <= 0 then
table.remove(currentPlayers, v)
end
end
wait(1)
end
print("Round over")
但是,这是错误的代码。 (每当您编写代码时,让其中带有“等待”函数的循环用于指示某些操作不正确。)您应该使用 Roblox 的 Events 来处理您的游戏逻辑。
检查游戏是否应该仅在玩家数量发生变化时才开始。 仅当人形机器人的健康状况发生变化(HealthChanged 事件)时“寻找赢家”。 以某种计时器或间隔运行计时器(不要忘记,一旦有人获胜,您可能希望提前结束游戏)。与繁忙的循环相比,事件有很多很多优点;最明显的是您的检查发生在他们正在检查的事情发生时,而不是稍后。
【讨论】:
【参考方案2】:我建议你按照 Stuart 的建议来使用事件;这主要是为了提供有关协程的附加信息,以帮助您正确使用它们。
将协程视为可以返回值的函数,但有一点不同:虽然“正常”函数在执行 return
时完成,但当您从协程中 yield
时,它会保存其状态,以便 @987654324 @ 然后可以从您屈服的点继续,就好像什么都没发生一样。请注意,您仅yield
来自 一个协程,并且仅到达该协程的resume
完成的点(这与调用函数并从它返回没有什么不同;控制返回到调用函数的位置)。
除此之外,resume
和 yield
调用允许您将值传递给协程并从协程返回(中间)值。请参阅SO answer 了解如何使用它的示例。
仍然可以从协程中return
,这与从完成执行的函数返回没有什么不同。如果查看当时协程的状态(coroutine.status
),应该是“死”了。
所以,要回答你的问题,如何结束循环协程:你可以从它return
,你可以从它yield()
(永远不要再resume
它),或者你可以调用error()
,然后您可以在resume
调用的结果中捕获并检查它。话虽如此,我同意 Stuart 的观点,即这可能是解决您问题的错误方法。
【讨论】:
以上是关于如何在 Lua 中结束循环协程?的主要内容,如果未能解决你的问题,请参考以下文章