咱們在遊戲設計和開發中,尤爲是引擎開發中,邏輯循環是一個重要組成部分,循環決定了遊戲的基礎邏輯和運行方式,在不一樣的開發環境和語言下,對於循環的釋義甚至相差甚遠,那麼我想和你們分享的是在Silverlight遊戲開發中,循環的設計方式和作法。算法
如下內容來自以往的遊戲開發經驗,可能在其餘語言中的相關文章更加詳細,謹在這裏討論有關在Silverlight遊戲開發中的應用。設計模式
在傳統的開發觀念中,不管任何開發環境,它都逃不出While,代碼通常是這樣:數組
while (true) { if (GameExit() == true) break; else GameLoop(); }
這個代碼方式只是一個模型,能夠將其理解成爲一個不停在檢查狀態的狀態機。安全
那麼在Silverlight遊戲開發中,咱們是否也能夠這樣應用呢?道理上差很少,目前來講大部分的作法只是實現了一個根(Root)部,這方面深藍色右手以及不少其餘朋友都有了各類各樣的解決方案,有興趣的朋友能夠找他們的文章,不管是用線程(Thread)、故事板(Storyboard)、Rendering、DispatcherTimer,都是一個好的循環體的開始。網絡
對於遊戲而言,尤爲是網絡遊戲,咱們將面臨着大量的交互,這些交互可能來自用戶,也可能來自自身的遊戲邏輯,就如最現實的問題是,當一個遊戲的同屏幕呈現100個以上的角色的時候,遊戲是否所以而「卡」住,在早期的時候,我陷入了一個誤區,呈現足夠多的角色就是最大的性能體現(3.0呈現600個角色不卡),如今看來倒是否則,由於單純的角色呈現,有幾百個不算什麼,在一個總體遊戲的執行時候,它是否還能保持足夠的流暢纔是最重要的,由於戰鬥邏輯、界面邏輯、場景管理器無時不刻在佔用着系統資源,而且此時的角色也絕非幾張圖片那麼簡單,他們身上的裝備、部件、特效都將成爲遊戲開發者的負擔。數據結構
在此種狀況下,優化循環過程至關重要,做爲團隊經驗積累,今次拿出來你們一塊兒研討,有什麼好的想法和建議歡迎一塊兒交流一下:)下面的五種循環設計模式名字本身亂起的很差,還請見諒。oop
自身式循環比較容易理解,好比一個精靈控件,本身內部實現一個循環,來不停的檢測和執行邏輯,開發者都不須要去單獨作什麼,只須要new出來它們本身就會執行邏輯了,這種方式很是便捷和方便,開發起來也相對容易,互相之間沒有任何關係,此時須要藉助單例之類的設計模式來解決互相的結合問題。圖示以下:性能
很顯然,咱們自身邏輯有一個最大的問題是獨自的性能佔用,若是一個場景(不是同屏)有幾百個這樣的循環時,那麼遊戲各個線程就會吃掉大量的CPU,尤爲是用Thread、Storyboard、DispatcherTimer的時候。優化
自身邏輯存在各自的循環消耗問題,那麼有沒有辦法將各自的循環邏輯統一到一個循環中呢,若是學過數據結構,咱們能夠透過鏈表的形式來作,基本的原理是將各個循環體放入到一個大循環中,而後從第一個開始執行循環邏輯,只執行一次,而後下一個,到底之後回來繼續執行,模型以下:動畫
這是一種常見的處理方法,可以大大下降系統消耗,並且C#提供了迭代器等好用的遍歷,使得咱們結合面向對象的思路更方便。示意代碼以下:
public class obj { public virtual void OnLogic(); } List<obj> ObjList = new List<obj>(); public void OnLoop() { foreach (var item in ObjList) { item.OnLogic(); } }
鏈條式循環最大的優勢是將全部的獨立循環所有集中到一個大循環邏輯中,須要注意的有一個問題,那就是動態處理,由於遊戲當中的物體生成和銷燬是很是頻繁的,正在循環的時候發生了集合改變,那麼就危險了,咱們的作法有兩種,分別是數組轉換和回收判斷,數組轉換很是容易,將集合拷貝到一個數組中,而後循環數組的各個元素;回收判斷是經過標識將物體,在合適的時機摘出到一個回收列表中,而後在安全的時機清理。
鏈條式循環的優勢能夠創造一個遊戲的RootHead,將全部的元素加入到這個RootHead當中,建立一個主循環而後遍歷便可,固然了,你須要經過基類的方式來達到目的。
這是一種好的方式嗎?在某種狀況是的,它能解決性能損耗,固然了,要是內部實現的邏輯過於複雜,有的時候可能還得藉助一下另外線程。在遊戲產品中,有一個更加直接的需求,那就是級別層次問題,也就是說,有的循環體是系統級別,而有的可能只是一張圖片,那麼遊戲的循環到底有多大才能包容一切,好比場景管理中的那麼多場景物體,若是有邏輯循環就直接加入到這個大循環中嗎?在遊戲運行時,有一些循環在特定的時候是不須要使用的,或者不須要執行的,也爲後續開發形成了障礙,因此,在咱們的MMOROG引擎中,最多應用是下面的這種循環模式。
子樹循環顧名思義,使用樹狀結構來處理循環邏輯,咱們實際應用中還有能夠分爲:活動子樹式循環和固定子樹循環,爲了方便講解,主要講固定子樹循環的模式。
咱們知道在一個遊戲中,有不少的系統,好比場景系統、戰鬥系統、隊伍系統、公會系統、聊天系統……N多系統,它們本身內部是否有一個循環呢?若是從直觀角度上,上述系統可能不須要循環,可是事實否則,好比隊伍系統,可能爲了完成組隊、移動等行爲,專門有一個循環來處理判斷邏輯,雖然這個邏輯很簡單,再好比公會系統是否有每10秒鐘刷新一下公會列表的需求……
如上圖所示,咱們利用子對象的方式創造一顆樹,而後逐一進行遍歷,在執行過程可使用迭代,也可使用遞歸,無論那種方式,對於子樹而言沒有太大的區別,可是對於性能而言,咱們能夠作一些有趣的優化,當一個系統關閉的時候,它在樹中就不執行了——具體用什麼方法,看狀況而定,不管是拆枝仍是邏輯斷定都行。咱們獲得的效果是,關閉的子樹下面的元素也不會執行循環,多麼簡單,比鏈條式的容易多了,一斷全都斷。
子樹式循環在系統級別很是經常使用,對於那些比較頻繁的更換的邏輯比較實用,好比特效動畫、地圖系統等等,具體的算法和操做在《數據結構》中有明確的答案,能夠在其中找到想要的東西:)。
區間式循環嚴格意義上是循環中的一個斷定方式,而不是實現模式,原理是將遊戲系統各個部分拆分開,掛入不一樣的循環結構中,若是說鏈條式和子樹式是一種Object集中,區間式能夠說是一種Objects集合打散,釋義圖以下:
區間式在大系統級別,能夠分拆最消耗性能的部分,到另一個線程(或循環結構)中完成循環,好比說戰鬥系統、地圖處理、場景管理器,而場景管理器下也能夠帶入一個區間式循環,將場景分割,而後對一個區域範圍的物體進行處理(若是想一想上面的圖是否能夠作成一個二維數組呢?),對於超出區域範圍內的循環邏輯徹底視而不見就好了,不然的話,要處理一片大場景中的N多個角色,不管是在自身、鏈條、子樹都會一筆不小的開銷。
區間式最大的優勢是增強了範圍斷定,若是寫的好,還能夠多重結合,使用二維(三維也行)數組完成各個須要循環邏輯的分配,將不須要的拆分出去,這裏的算法可能稍微有點意思,相似哈希和List的結合,要注意的是當一個物體(OBJ)從區間1到區間2的時候,會發生什麼事情:)
其實組合式循環是一個很是偷懶的部分,由於組合的是前四種而已,在遊戲開發中,並非上述的那種方式最好,而是因地制宜,什麼樣的模式知足什麼樣的需求,不能只是單純爲了達到高效而高效,更加要注意將來開發的順利程度,避免返工。
如上圖所示,咱們能夠很清楚的分析不一樣循環方式在不一樣的環境下的應用:
自身式循環比較適合界面,由於比較固定,並且複雜邏輯很少,固然了這只是在Silverlight的UI當中比較適用,其實主邏輯就是一個很大的自身循環,Root的循環方式就是一個自身式循環。
鏈條式循環比較使用與第二級的遊戲系統,將系統所有串起來,以達到快速遍歷目的,可是在系統的下一級,就是子樹式循環,系統元素所有在一個系統下,下面的子樹中也可能會出現鏈條式,很顯然是一種最頻繁的組合方式。
區間式循環主要是應用在場景系統,可能須要一個鏈條循環或者子樹循環帶動,具體狀況須要看遊戲的設計模式,若是單個場景(好比地圖)是使用單例的方式,那麼使用鏈條式循環帶動循環邏輯比較合適,若是單個場景是經過new出來的,那麼使用子樹方式來切換銜接更加容易明瞭。
以上是咱們在作MMORPG時候的一些小小經驗總結,上述中咱們用的最可能是組合式循環(廢話,組合式全包了),可是對於一些小型的遊戲,建議仍是不要設計這麼複雜,對於大型的網絡遊戲而言,程序設計這部分的重要性非比尋常,最後,看過不少這樣或那樣的說法,網頁遊戲對於性能是不行的,我想大部分的性能問題並非技術自己,而是開發者沒有將一個遊戲本質思考清楚,何時咱們用什麼方法能夠達到什麼目的,能爲各位開發者多能從中找到一點靈感,那爲我本身的想法也有了一個交代,也歡迎小夥伴們在評論下方留言,共同討論。