2014-02-18 79 views
5

我目前正在使用Roblox(使用Lua)進行遊戲。它基本上由幾個迷你遊戲組成。在每輪比賽開始時,比賽中的所有球員被放在一張桌子上並傳送到一個區域。這就是協程進入的地方。由於這輪比賽正在進行中,我想要一個協同程序開始。協程每檢查一次玩家的健康是否低於零,並將它們從currentPlayer表中刪除(如果是)。如何在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 
+0

感謝您修復代碼,我的錯誤是無法正確發佈。 – user3314993

回答

4

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事件)時纔會查找獲勝者。
  • 在某種計時器或時間間隔上運行計時器(不要忘記,一旦有人獲勝,您可能會希望儘早結束遊戲)。

活動有很多很多優勢在繁忙的循環;最明顯的將是你的支票發生他們正在檢查的事情發生,而不是以後。

+0

有關協程的更多信息,請參閱http://www.lua.org/pil/9.1.html –

3

我建議你按照Stuart的建議來使用事件;這主要是爲了提供關於哪些協同程序能夠幫助您正確使用它們的附加信息。協程的

想象成可能返回值,但與一捻功能:當一個「正常」的功能,當它執行return完成,當你yield從協程,它保存其狀態,從而使resume可以再從繼續就像你沒有發生任何事情一樣。請注意,只有yield一個協程,並且只到該協程的resume完成的點(這與調用函數並從中返回並沒有什麼不同;控制返回到您稱爲該函數的位置)。

除此之外,resumeyield調用允許您將值傳遞給協程並從協程返回(中間)值。有關如何使用該示例的示例,請參見此SO answer

從協程中仍然可以得到return,它與從完成其執行的函數返回沒有區別。如果你當時檢查協程的狀態(coroutine.status),它應該是「死的」。

因此,要回答你的問題,你如何結束一個循環的協同程序:您可以return從中,你可以yield()從它(永不再resume的話),或者也可以稱之爲error(),然後你就可以捕獲並檢查在撥打resume的結果。話雖如此,我同意斯圖亞特認爲這可能是解決問題的錯誤方法。