allenchou.net
遊戲程式:延遲蒐集運算結果 | Ming-Lun "Allen" Chou | 周明倫
[latexpage] Here is the original English post.本文之英文原文在此 簡介 我先前就讀於DigiPen,每逢"公司日"邀請業界人士來學校分享專業經驗,在問與答時間總是會出現一個常駐問題:請告訴我們你希望當初在學校就已學會的事(主題可涵蓋技術能力、社交能力、製作能力等)。我常常想像,若我以校友身分參加"公司日"回母校分享經驗,我會如何回答這個問題。經過了很長一段時間,我心中一直沒有個明確的答案。直到現在,如果我回母校參加"公司日"分享經驗,我大概會針對CS的同學給予這個答覆──我希望我在學校的時候,就能學到兩個遊戲程式的優化技巧:延遲蒐集運算結果(delayed result gathering)和時間切割(time slicing)。 這是我加入頑皮狗(Naughty Dog)之後最先學到的兩個技巧,而且它們在我的職業生涯中非常實用。時至今日,我仍然在不少遊戲系統中使用這兩個優化技巧。它們是相當泛用的解決方案,能廣泛且有效的地套用到各種系統上。 在這個教學中,我會先介紹第一個技巧:延遲蒐集運算結果。我會於下一個教學中再介紹時間切割。 範例:曝光地圖與曝光迴避 首先,來介紹一下作為貫串這兩個教學作為示範基底的範例。在這兩個教學的過程中,我將會不斷地修改這個範例,展示如何將這些優化技巧套用到既有系統上。 這個範例是曝光地圖(exposure map)與曝光迴避(exposure avoidance)。有個網格(grid)資料結構,其每一個格子(cell)存有是否曝光於一個哨兵(sentinel)的資料。另外有一個角色會嘗試避免曝光於哨兵的視野中。若哨兵移動後導致角色所在的格子曝光,角色則會逃離至附近的未曝光格子。這位角色是個害羞的球球。 以下是這個機制(mechanic)的更新迴圈(update loop),共有三個步驟: 根據哨兵的位置更新曝光地圖,使用射線投射(raycast)偵測從哨兵眼睛到每一個格子的直線途徑是否淨空。若直線途徑淨空,表示這個格子曝光於哨兵的視野中。計算角色到每一個格子的路徑長度。若角色所在的格子已曝光,更新目的地為附近的未曝光格子,並使角色尋徑至該格子。 此更新迴圈的程式碼看起來如下: void Update() { UpdateExposureMap(); UpdatePathLengths(); UpdateDestination(); } 大學時期的我實作UpdateExposureMap,應該會像這樣: void UpdateExposureMap() { for (int iCell = 0; iCell < NumCells; ++iCell) { Vector3 cellCenter = Grid[iCell]; Vector3 vec = cellCenter - EyePos; Vector3