[心得] 容易被遺忘的遊戲設計模組(3)

看板GameDesign (遊戲設計)作者 (溺於黑暗)時間16年前 (2010/02/05 18:20), 編輯推噓9(902)
留言11則, 11人參與, 最新討論串1/1
作者:NDark 時間﹔201001 http://wp.me/pBAPd-a4 "容易被遺忘的遊戲設計模組"之三:Resource/Stage Paragraphing http://blog.zhieng.com/wp-content/uploads/2009/10/warcfrat_loading.jpg
我想大家都看過進遊戲之前,或是從遊戲大廳進入戰鬥時的讀取狀態跟讀取條。 不知道有沒有人想過,為什麼不在程式開始的時候就把所有東西讀進來。 這樣遊戲過程不就不用等待了嗎? 也許這個問題太笨了。 OK, 以關卡制為例,我們不用在第一關開始的時候就把第二關的場景讀進來。 (這樣做造成了第一關開始要讀入的資料變少了。只是把資料讀取延後到第二關。) 以MMORPG為例,還沒有跨到下一區的時候也沒必要讀入那一區的場景。 因為那對於主記憶體都是一個浪費, 不如把資源省下來給目前正在使用的場景讓他有更多的多樣性。 一定有人想過MMORPG在快接近第二區的時候就開始偷偷預先讀資料的設計。 避免遊戲中的停頓是非常重要的設計, 有時候差那個幾秒,對使用者來說就會累積不耐煩。 因此有些人在讀取資料的時候用動畫,用讀取條來"安慰"使用者。 或是先讀入小部分的資料,用預先設計好的即時動畫,或飛覽來讓使用者再多等一下。 這邊不是要討論如何製造這些安慰劑。 而是用幾個事實說明分段的重要性。 .如果把資料全部在一開始讀入,那麼程式開始可能要讀10分鐘。這恐怕是個災難。  但是如果分成3分3分4分讀入,使用者也許就能接受。 .只讓主記憶體塞滿目前要用的資料為目標,那麼這空間就很可觀,  可以讓你的場景豐富起來。意思是同一時間能呈現的多變性夠多。 .資源是有限的,讓盡量多的使用者的電腦都能玩是一件重要的事情。  無論使用者的主記憶體與顯示卡有多low。 確認了分段的重要性 那麼,確實來說要怎麼分段? 大部分的遊戲都包含這樣的結構 主選單模式:還沒進入遊戲,大部分是讓你選擇要繼續上次的進度還是新遊戲。       資源與遊戲模式是幾乎豪無相關。 遊戲模式:主要的場景,大部分的遊戲時間在的模式。 戰場模式:或是次遊戲模式,從主遊戲切換至的遊戲模式,      場景與主遊戲不相關,但是資料是相關的。 註:有時會只分兩段,也就是主選單-遊戲 因此我們的遊戲應該怎麼執行? 1)-讀取主選單的資源-主選單模式-釋放主選單的資源-進入2 2)-讀取遊戲模式的資源-遊戲模式-釋放遊戲模式的資源-進入1/3 3)-讀取戰場模式的資源-戰場模式-釋放戰場模式的資源-回到2 延伸思考 如果考量到"安慰劑"的話上面的狀況會變成怎樣?   意思是在真的開始大量讀取資源之前一定有一些事情要作吧。 註:這邊我定義的資源與資料有點不太一樣。應該不用我多作說明了吧。 到此所討論的東西我把他稱之為Resource Paragraphing, 主要是為了資源分配最大化(後述)為考量的。 我在沙漠商旅C的時候用的stage稍微細一點,分別是: system initalization:程式開始,將遊戲系統初始化中,把主選單的資源讀進來。 system pre-main menu:遊戲系統已經讀入了基本的元件,或是已經初始化完畢。 在主選單前會有一些必要的東西。 請思考一下這段使用者看到什麼。 main menu:主選單,舉凡列出讀檔清單與新遊戲挑選角色。 load level:讀取關卡資源,開始進入遊戲模式了。 game starting:遊戲開始中。 game playing:遊戲進行中,請思考一下跟starting有什麼不一樣。 load battle:讀取戰場資源,進入戰場模式 game battling:遊戲戰鬥中。 back to play:自戰場回到遊戲模式。這是第二種進入遊戲模式的方法。 back to main:自遊戲模式回到主選單。大量的資源被釋放了, 這是第二種進入主選單模式的方法。 pausing:暫停狀態。 exiting:從主選單或是從任何狀態離開程式的時候,連遊戲系統的物件都被釋放了。 延伸思考   暫停狀態是什麼暫停了?什麼沒暫停?   如果主選單太久沒動作會自動播放動畫,那麼要怎麼修改?   戰鬥之後的結算畫面應該是哪個stage?或是額外的stage? 註:沙漠商旅C的結構是 平台程式承載遊戲系統物件 遊戲系統物件再承載遊戲資料如圖: http://ndark.files.wordpress.com/2010/01/caravaneerclone-system-graph.jpg
但平台程式負責將遊戲資料繪出 且平台程式負責互動處理。恩...大概很像是MVC的架構。 (沒聽過這個的後述) 註:這些分段如果大部分的遊戲都存在這樣的設計,   是否我們可以在每個遊戲設計專案開始之初建立一個架構?   這也是我寫這幾篇文章的起始動機。 曾經有位非遊戲界的軟體工程師問我,multi-thread在遊戲程式設計中有沒有用。 我回答他:"有用,但不是最重要的。因為遊戲設計開始之初,都是單執行緒的。" 當然隨著時代進步,開始有多工軟硬體環境(如Sony PS3就是多工硬體), 但是那都是加強運算的能力,而非加強遊戲程式設計的本質。 我們接下來都先假設我們只有單執行緒。 再進一步討論之前, 我要先介紹codeproject.com的一篇文章。 SK Genius 的 "Game Programming - One" http://www.codeproject.com/KB/game/skgameone.aspx 他介紹了一個十分簡單卻重要的遊戲流程。 請翻到"It's All About Timing"下方的程式碼。 我們可以看到,在一個單執行緒的流程中,遊戲是一直反覆著在作相同的幾個步驟。 GetInput() PerformLogic() DrawGraphics() 這三步驟基本上涵蓋了遊戲程式設計的主要工作:控制,資料/流程,繪圖    也就是Control,Model,View。 (與一般視窗軟體不同的是,  遊戲進行中即使不輸入,流程本身也是一直在進行控制=改變的。) 當然複雜一點的遊戲流程會作比較多的步驟。以沙漠商旅C為例,依序為 1.FPS計算, 2.網路處理(未完成預留), 3.3D動畫(未完成預留), 4.更新位置, 5.2D動畫(未完成預留), 6.輸入事件, 7.碰撞偵測, 8.環境變化(讀檔,遊戲事件處理,更新3D視野,更新2D選單), 9.人工智能, 10.繪圖前處理(未完成預留), 11.繪圖(設定3D視野,畫3D物件,設定平面視野,畫2D選單) 註:這些流程的順序當然並非一定得這樣排,而且一定可以找到更好的排法。 很希望未來有機會可以跟各位討論這個問題。 因此,我們有主要流程,每個畫格都作一樣的事情-執行了1,2,3...的步驟流程。 再加上還有一開始討論的stage,就是不同的階段下我們的流程應該作不同的事情。 那麼這兩個該怎麼組合在一起? 最Naive的做法當然就是把各個階段當作不同的遊戲,甚至是不同的程式。 畢竟它們的流程是真的不一樣。因此這樣的主流程會像這樣: -以Stage(階段)為經,以Process(流程)為緯 MainLoop { switch( StageNow ) { case system initalization : GameLoopSysInit() ; case game playing : GameLoopGamePlaying() ; ... } } 但是, 我們會發現其實每個階段中都會有相同的工作要作, 這一種方式簡直就是把同樣的事情重複作好幾次。完全不符合程式設計偷懶的本質。 因此接下來我們就要跟各位討論本篇主題的第二個部分Stage Paragraphing。 -以Process(流程)為經,以Stage(階段)為緯 我們的流程變成這樣 MainLoop { InputHandling() ; ... EnvironmentChanging() ; ... DisplayMain() } MainLoop裡面的各子函式就都可以變成這種形式 (*)SubFunc() { switch( stage ) { case game playing : ... break ; case game battling : ... break ; } } 這樣作的好處是有時候 相同的流程可以用在不同的階段。 譬如說 主選單模式的stage,遊戲模式的stage,與戰場模式的stage都有畫選單的流程 而且這些流程基本上是做相同的事情-畫出目前需要的選單。 因此在畫選單函式就可以合併成這樣。 RenderMenu { switch( stage ) { case main menu : case game playing : case game battling : DrawAllValidMenu() ; break ; } } 壞處是,結構改變的時候, a) 當原本合併的兩個stage要分開,或是 b) 原先沒有必要進行因此忽略的stage突然需要,卻忘記修正這個分段結構。 就會造成除錯的風險。(A) 簡單來講,如果開發團隊沒辦法完全掌控好這結構就容易造成維護上的困擾。 分段結構造成的影響是 a) 極大化同樣的程式-若是相近的流程運作,卻因為小處的不同而刻了兩段類似的程式 ,反而會造成未來維護上的更大危機。 b) 強迫遊戲開發者去開發通用(robust)的元件,來符合這個分段結構。 註:這邊的"更大"指得是相較於上述(A) "忘記修正這個分段結構" 講了這麼多,最後作總結。 雖然有點抽象,但請試著想像一下 一個好的分段就像一個"壓縮率"的比例,同時壓縮資源/程式碼/風險 這個分段的做法保持了一個原則: "將相同的事情變成同一件事,將不同的事情盡量分開"。 (剛好符合程式設計模式的大概念。) 假設優秀的分段可以讓效能發揮到0.3的壓縮率。   而沒有分段時壓縮率為1.0。 當硬體進步時100分的硬體等於塞進了100個未壓縮的物體 有分段的結構就是塞進了100/0.3=333個物體。 當硬體效能1000的時候,比值就是 1000比3333 高壓縮率的設計方式可以讓在同等硬體平台同樣的人力工時運作"開發"這件事情的時候, 獲得超越對手的(虛擬)硬體/遊戲內容。 這聽起來既模糊又顯而易見。 事實上就是一個永無止盡的軍備競賽-遊戲開發工廠的輸入與輸出。 輸入的是code或是PG的工時,輸出的是遊戲效能。 質的改變最終造成量的改變。 -- "May the Balance be with U"(願平衡與你同在) 視窗介面遊戲設計教學( http://0rz.tw/V28It ),討論,分享。歡迎來信。 視窗程式設計(Windows CLR Form)遊戲架構設計(Game Application Framework) 遊戲工具設計(Game App. Tool Design ) 電腦圖學架構及研究(Computer Graphics)論文代讀(含投影片製作) -- ※ 發信站: 批踢踢實業坊(ptt.cc) ◆ From: 140.96.77.176 ※ 編輯: NDark 來自: 140.96.77.176 (02/05 18:20) ※ 編輯: NDark 來自: 140.96.77.176 (02/05 18:20)

02/05 18:34, , 1F
頭推!! 受益良多
02/05 18:34, 1F

02/05 18:56, , 2F
這篇超重要 大推
02/05 18:56, 2F

02/05 19:08, , 3F
推!
02/05 19:08, 3F

02/05 20:23, , 4F
推~ 超棒的~
02/05 20:23, 4F

02/05 21:01, , 5F
推!
02/05 21:01, 5F

02/05 21:02, , 6F
謝謝~~~~ 獲益良多阿
02/05 21:02, 6F

02/05 21:11, , 7F
推!幾個月前把遊戲放在360上時也卡這問題卡許久Q_Q
02/05 21:11, 7F

02/05 22:20, , 8F
一點想法 我覺得分段有一部分是為了較有彈性的資料驅動方式
02/05 22:20, 8F

02/06 12:34, , 9F
感謝分享一系列的文章, 我可以拜一下嗎? ><
02/06 12:34, 9F

02/08 02:27, , 10F
thanks for your share.
02/08 02:27, 10F

03/11 19:47, , 11F
03/11 19:47, 11F
文章代碼(AID): #1BQ_3far (GameDesign)
文章代碼(AID): #1BQ_3far (GameDesign)