如何在Lua中结束循环协程?

我目前正在使用Roblox(使用Lua)制作一个游戏。这是由几个小游戏组成的。在每一轮开始时,游戏中的所有玩家都被放在一个表中并传送到一个区域。协同程序就在这里发挥作用。在进展中的回合中,我希望协同程序启动。每秒钟这个协同程序检查玩家的血量是否低于零,如果是,则将其从当前玩家表中删除。

如果我描述问题不正确,那么很抱歉,但是协同程序将不会产生任何效果。我以前没有使用过协同程序,所以我可能正在尝试错误的方法来产生效果。我知道你们大多数人不熟悉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
点赞
用户34799
用户34799

Lua是一种单线程语言。协同程序不会导致函数并行执行。

协同程序实际上只是一种可以暂停自身执行(使用 coroutine.yield)并且可以从外部恢复执行(使用 coroutine.resume)的函数。没有“coroutine.running”:在任何时候只有一条“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(05000)

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的事件处理游戏的逻辑。

  • 只有在玩家数量改变时才检查游戏是否应该开始。
  • 只有在生命值改变时(HealthChanged事件)才寻找胜者。
  • 在某种计时器或时间间隔上运行计时器(不要忘记您可能希望在有人获胜时提前结束游戏)。

与繁忙循环相比,事件具有_[许多许多]_优点;最显著的一个优点将是您的检查发生的时间是_它们正在检查的_事情发生的时间,而不是之后。

2014-02-18 20:11:32
用户1442917
用户1442917

我建议你跟随 Stuart 的建议使用事件; 这主要是为了提供关于协同程序的额外信息,以帮助你正确地使用它们。

将协同程序视为可以返回值的函数,但有一个特殊之处:当“普通”函数执行 return 时,它完成了,但当你从协同程序中 yield 时,它保存了自己的状态,使得 resume 可以从你 yield 的点继续执行,就好像什么也没有发生一样。请注意,你只能从协同程序中 yield,并且只能到该协同程序的 resume 执行的点(这与调用函数并从函数返回没有任何区别;控制权返回到你调用函数的点)。

此外,resumeyield 调用允许你向协同程序传递值并从协同程序返回(中间)值。查看这个 SO 回答 来查看如何使用这一点的示例。

仍然可以从协同程序中 return,这与从函数中返回没有任何区别,它将完成其执行。如果在那时检查协同程序的状态(coroutine.status),它应该是“已死”。

所以,回答你的问题如何结束一个循环协同程序:你可以从它中 return,你可以从它中 yield()(然后再也不 resume 它),或者你可以调用 error(),之后你可以捕获它,并在 resume 调用的结果中检查它。话虽如此,我同意 Stuart 的观点,这可能不是解决你的问题的正确方法。

2014-02-18 21:36:13