我一直在學習遊戲開發的一些lua。我聽說過其他語言的協程,但在lua中真的出現了。我真的不明白它們的用處是多麼的有用,我聽到很多人都在談論它是如何做一個多線程的東西的方法,但是它們不是按順序運行的嗎?那麼正常的函數也會有什麼好處呢?我只是沒有看到它們與功能的區別,只不過它們可以暫停而讓另一次運行。似乎用例場景對我來說不會那麼重要。協程有什麼好處?
任何人都在關注爲什麼有人會從中受益?
特別是從一個遊戲編程的角度洞察將是很好的^^
我一直在學習遊戲開發的一些lua。我聽說過其他語言的協程,但在lua中真的出現了。我真的不明白它們的用處是多麼的有用,我聽到很多人都在談論它是如何做一個多線程的東西的方法,但是它們不是按順序運行的嗎?那麼正常的函數也會有什麼好處呢?我只是沒有看到它們與功能的區別,只不過它們可以暫停而讓另一次運行。似乎用例場景對我來說不會那麼重要。協程有什麼好處?
任何人都在關注爲什麼有人會從中受益?
特別是從一個遊戲編程的角度洞察將是很好的^^
我們使用他們的一個項目我的工作。對我們來說主要的好處是,有時候使用異步代碼,有些地方很重要,因爲某些依賴關係,某些部分依次運行。如果使用協同程序,則可以強制一個進程等待另一個進程完成。他們不是唯一的方式來做到這一點,但他們可以比其他方法簡單得多。
我只是沒有得到多麼不同,他們從功能,但 他們可以暫停,讓另一個運行一秒。
這是一個非常重要的屬性。我曾在一個遊戲引擎上使用它們進行計時。例如,我們有一個每秒鐘運行10次的引擎,並且您可以WaitTicks(x)等待x個tick,並且在用戶層中,您可以運行WaitFrame(x)來等待x個幀。
即使專業的本地併發庫也使用相同的產生行爲。
好吧,從遊戲開發的角度思考。
假設你正在做一個過場動畫或者一個教程。無論哪種方式,你有什麼是一個有序的命令序列發送到一些實體。一個實體移動到一個位置,與一個男人談話,然後走到其他地方。等等。一些命令在其他人完成之後才能啓動。
現在回頭看看你的遊戲是如何工作的。每一幀都必須處理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邏輯有多簡單。它的確如它所說的那樣。很明顯,很明顯,因此很難弄錯。
協程的能力在於能夠部分地完成某項任務,等待條件成真,然後繼續下一個任務。
很多遊戲開發者的好例子。我會在應用程序擴展空間中給予另一個。考慮應用程序有一個引擎可以在Lua中運行用戶例程的情況,同時在C中執行核心功能。如果用戶需要等待引擎達到特定狀態(例如等待數據被接收),你要麼必須:
第三個選項對我來說是最容易實現的,避免了在多個平臺上處理多線程的需要。它還允許用戶的代碼不加修改地運行,看起來好像他們調用的函數花了很長時間。
在遊戲中的協同工作: 易於使用,在許多地方使用時很容易搞砸。
只要小心,不要在很多地方使用它。 不要讓您的整個AI代碼依賴於協程。
協調器在引入之前不存在的狀態時可以快速修復。
這正是java所做的。睡眠()和等待() 這兩種功能都是讓您無法調試遊戲的最佳方式。 如果我是你,我會完全避免使用像Coroutine那樣的Wait()函數的任何代碼。
OpenGL API是你應該注意的事情。它從不使用wait()函數,而是使用乾淨的狀態機,該狀態機確切知道對象所處的狀態。 如果你使用協程,那麼你最終會得到很多無狀態的代碼,它肯定會壓倒性地進行調試。
當你正在製作像文本編輯器..銀行應用程序..服務器..數據庫等(不是遊戲)的應用程序時,協程是很好的。 當你在任何時候發生任何事情的遊戲時都很糟糕,你需要有狀態。
所以,在我看來,協程是一種不好的編程方式,也是編寫小型無狀態代碼的藉口。
但這就是我。
他們的歷史可以追溯到上個世紀。多核cpus和從cpu緩存中取消的懲罰性延遲放到了他們的用處。線程是它。 –
@Hans Passant:這完全忽略了協程的點。協程並不是線程的替代品,您不會將它們用於您將使用線程的同一件事。關鍵是寫一個乾淨而舒適的(非併發!)代碼,其中可以暫停一個函數調用,以便在有更多信息時可以返回,而不會阻塞主循環。這樣做沒有任何開銷,這是lua做的。在那個用例中,操作系統線程將是一個糟糕的替代品。 –