Programming

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


作者:NDark

時間﹔201001

“容易被遺忘的遊戲設計模組"之三:Resource/Stage Paragraphing

warcraft loading

warcraft loading

我想大家都看過進遊戲之前,或是從遊戲大廳進入戰鬥時的讀取狀態跟讀取條。

不知道有沒有人想過,
為什麼不在程式開始的時候就把所有東西讀進來。
這樣遊戲過程不就不用等待了嗎?

也許這個問題太笨了。

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的結構是 平台程式承載遊戲系統物件 遊戲系統物件再承載遊戲資料如圖:

CaravaneerCLONE System Graph
CaravaneerCLONE System Graph

但平台程式負責將遊戲資料繪出
且平台程式負責互動處理。恩…大概很像是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(流程)為緯

MainLoop1
MainLoop1

但是,
我們會發現其實每個階段中都會有相同的工作要作,
這一種方式簡直就是把同樣的事情重複作好幾次。完全不符合程式設計偷懶的本質。

因此接下來我們就要跟各位討論本篇主題的第二個部分Stage Paragraphing。

-以Process(流程)為經,以Stage(階段)為緯

我們的流程變成這樣

MainLoop2
MainLoop2

MainLoop裡面的各子函式就都可以變成這種形式

SubFunc
SubFunc

這樣作的好處是有時候 相同的流程可以用在不同的階段。

譬如說
主選單模式的stage,遊戲模式的stage,與戰場模式的stage都有畫選單的流程
而且這些流程基本上是做相同的事情-畫出目前需要的選單。

因此在畫選單函式就可以合併成這樣。

RenderMenu
RenderMenu

壞處是,結構改變的時候,

a) 當原本合併的兩個stage要分開,或是
b) 原先沒有必要進行因此忽略的stage突然需要,卻忘記修正這個分段結構。
就會造成除錯的風險。(A)
簡單來講,如果開發團隊沒辦法完全掌控好這結構就容易造成維護上的困擾。

分段結構造成的影響

a) 極大化同樣的程式-若是相近的流程運作,卻因為小處的不同而刻了兩段類似的程式
,反而會造成未來維護上的更大危機。
b) 強迫遊戲開發者去開發通用(robust)的元件,來符合這個分段結構。

:這邊的"更大"指得是相較於上述(A)"忘記修正這個分段結構"

講了這麼多,最後作總結

雖然有點抽象,但請試著想像一下
一個好的分段就像一個 “壓縮率"的比例,同時壓縮資源/程式碼/風險
這個分段的做法保持了一個原則:
“將相同的事情變成同一件事,將不同的事情盡量分開"。
(剛好符合程式設計模式的大概念。)

假設優秀的分段可以讓效能發揮到0.3的壓縮率。
而沒有分段時壓縮率為1.0。

當硬體進步時100分的硬體等於塞進了100個未壓縮的物體
有分段的結構就是塞進了100/0.3=333個物體。

當硬體效能1000的時候,比值就是 1000比3333
高壓縮率的設計方式可以讓在同等硬體平台同樣的人力工時運作"開發"這件事情的時候,
獲得超越對手的(虛擬)硬體/遊戲內容。

這聽起來既模糊又顯而易見。
事實上就是一個永無止盡的軍備競賽-遊戲開發工廠的輸入與輸出
輸入的是code或是PG的工時,輸出的是遊戲效能。
質的改變最終造成量的改變。

廣告

發表迴響

在下方填入你的資料或按右方圖示以社群網站登入:

WordPress.com Logo

您的留言將使用 WordPress.com 帳號。 登出 / 變更 )

Twitter picture

您的留言將使用 Twitter 帳號。 登出 / 變更 )

Facebook照片

您的留言將使用 Facebook 帳號。 登出 / 變更 )

Google+ photo

您的留言將使用 Google+ 帳號。 登出 / 變更 )

連結到 %s