總結使用Unity 3D優化遊戲運行性能的經驗

轉自:http://gamerboom.com/archives/76214程序員

做者:Amir Fasshihi編程

流暢的遊戲玩法來自流暢的幀率,而咱們即將推出的動做平臺遊戲《Shadow Blade》已經將在標準iPhone和iPad設備上實現每秒60幀視爲一個重要目標。緩存

如下是咱們在緊湊的優化過程當中提高遊戲運行性能,並實現目標幀率時須要考慮的事項。ssh

當基本遊戲功能到位時,就要確保遊戲運行表現可以達標。咱們衡量遊戲運行表現的一個基本工具是Unity內置分析器以及Xcode分析工具。使用Unity分析器來分析設備上的運行代碼真是一項寶貴的功能。ide

咱們總結了這種爲將目標設備的幀率控制在60fps而進行衡量、調整、再衡量過程的中相關經驗。函數

  1、遇到麻煩時要調用「垃圾回收器」(Garbage Collector,無用單元收集程序,如下簡稱GC)工具

因爲具備C/C++遊戲編程背景,咱們並不習慣無用單元收集程序的特定行爲。確保自動清理你不用的內存,這種作法在剛開始時很好,但很快你就公發現本身的分析器常常顯示CPU負荷過大,緣由是垃圾回收器正在收集垃圾內存。這對移動設備來講尤爲是個大問題。要跟進內存分配,並儘可能避免它們成爲優先數,如下是咱們應該採起的主要操做:性能

1.移除代碼中的任何字符串鏈接,由於這會給GC留下大量垃圾。優化

2.用簡單的「for」循環代替「foreach」循環。因爲某些緣由,每一個「foreach」循環的每次迭代會生成24字節的垃圾內存。一個簡單的循環迭代10次就能夠留下240字節的垃圾內存。動畫

3.更改咱們檢查遊戲對象標籤的方法。用「if (go.CompareTag (「Enemy」)」來代替「if (go.tag == 「Enemy」)」 。在一個內部循環調用對象分配的標籤屬性以及拷貝額外內存,這是一個很是糟糕的作法。

4.對象庫很棒,咱們爲全部動態遊戲對象製做和使用庫,這樣在遊戲運行時間內不會動態分配任何東西,不須要的時候全部東西反向循環到庫中。

5.不使用LINQ命令,由於它們通常會分配中間緩器,而這很容易生成垃圾內存。

  2、謹慎處理高級腳本和本地引擎C++代碼之間的通訊開銷。

全部使用Unity3D編寫的遊戲玩法代碼都是腳本代碼,在咱們的項目中是使用Mono執行時間處理的C#代碼。任何與引擎數據的通訊需求都要有一個進入高級腳本語言的本地引擎代碼的調用。這固然會產生它本身的開銷,而儘可能減小遊戲代碼中的這些調用則要排在第二位。

1.在這一情景中四處移動對象要求來自腳本代碼的調用進入引擎代碼,這樣咱們就會在遊戲玩法代碼的一個幀中緩存某一對象的轉換需求,並一次僅向引擎發送一個請求,以便減小調用開銷。這種模式也適用於其餘類似的地方,而不只侷限於移動和旋轉對象。

2.將引用本地緩存到元件中會減小每次在一個遊戲對象中使用 「GetComponent」 獲取一個元件引用的需求,這是調用本地引擎代碼的另外一個例子。

  3、物理效果

1.將物理模擬時間步設置到最小化狀態。在咱們的項目中就不能夠將讓它低於16毫秒。

2.減小角色控制器移動命令的調用。移動角色控制器會同步發生,每次調用都會耗損極大的性能。咱們的作法是緩存每幀的移動請求,而且僅運用一次。

3.修改代碼以避免依賴「ControllerColliderHit」 回調函數。這證實這些回調函數處理得並不十分迅速。

4.面對性能更弱的設備,要用skinned mesh代替physics cloth。cloth參數在運行表現中發揮重要做用,若是你肯花些時間找到美學與運行表現之間的平衡點,就能夠得到理想的結果。

5.在物理模擬過程當中不要使用ragdolls,只有在必要時才讓它生效。

6.要謹慎評估觸發器的「onInside」回調函數,在咱們的項目中,咱們儘可能在不依賴它們的狀況下模擬邏輯。

7.使用層次而不是標籤。咱們能夠輕鬆爲對象分配層次和標籤,並查詢特定對象,可是涉及碰撞邏輯時,層次至少在運行表現上會更有明顯優點。更快的物理計算和更少的無用分配內存是使用層次的基本緣由。

8.千萬不要使用Mesh對撞機。

9.最小化碰撞檢測請求(例如ray casts和sphere checks),儘可能從每次檢查中得到更多信息。

  4、讓AI代碼更迅速

咱們使用AI敵人來阻攔忍者英雄,並同其過招。如下是與AI性能問題有關的一些建議:

1.AI邏輯(例如能見度檢查等)會生成大量物理查詢。可讓AI更新循環設置低於圖像更新循環,以減小CPU負荷。

  5、最佳性能表現根本就不是來自代碼!

沒有發生什麼狀況的時候,就說明性能良好。這是咱們關閉一切沒必要要之物的基本原則。咱們的項目是一個側邊橫向卷軸動做遊戲,因此若是不具備可視性時,就能夠關閉許多動態關卡物體。

1.使用細節層次的定製關卡將遠處的敵人AI關閉。

2.移動平臺和障礙,當它們遠去時其物理碰撞機也會關閉。

3.Unity內置的「動畫挑選」系統能夠用來關閉未被渲染對象的動畫。

4.全部關卡內的粒子系統也可使用一樣的禁用機制。

  6、回調函數!那麼空白的回調函數呢?

要儘可能減小Unity回調函數。即便敵人回調函數存在性能損失。沒有必要將空白的回調函數留在代碼庫中(有時候介於大量代碼重寫和重構之間)。

  7、讓美術人員來救場

在程序員抓耳撓腮,絞盡腦汁去想該如何讓每秒運行更多幀時,美術人員總能神奇地派上大用場。

1.共享遊戲對象材料,令其在Unity中處於靜止狀態,可讓它們綁定在一塊兒,由此產生的簡化繪圖調用是呈現良好移動運行性能的重要元素。

2.紋理地圖集對UI元素來講尤爲有用。

3.方形紋理以及二者功率的合理壓縮是必不可少的步驟。

4.咱們的美術人員移除了全部遠處背景的網格,並將其轉化爲簡單的2D位面。

5.光照圖很是有價值。

6.咱們的美術人員在一些關口移除了額外頂點。

7.使用合理的紋理mip標準是一個好主意(遊戲邦注:要讓不一樣分辨率的設備呈現良好的幀率時尤爲如此)。

8.結合網格是美術人員能夠發揮做用的另外一個操做。

9.咱們的動畫師盡力讓不一樣角色共享動畫。

10.要找到美學/性能之間的平衡,就免不了許多粒子效果的迭代。減小發射器數量並儘可能減小透明度需求也是一大挑戰。

  8、要減小內存使用

使用大內存固然會對性能產生負面影響,但在咱們的項目中,咱們的iPod因爲超過內存上限而遭遇了屢次崩潰事件。咱們的遊戲中最耗內存的是紋理。

1.不一樣設備要使用不一樣的紋理大小,尤爲是UI和大型背景中的紋理。《Shadow Blade》使用的是通用型模板,但若是在啓動時檢測到設備大小和分辨率,就會載入不一樣資產。

2.咱們要確保未使用的資產不會載入內存。咱們必須遲一點在項目中找到僅被一個預製件實例引用,而且從未徹底載入內存中實例化的資產。

3.去除網格中的額外多邊形也能實現這一點。

4.咱們應該重建一些資產的生週期管理。例如,調整主菜單資產的加載/卸載時間,或者關卡資產、遊戲音樂的有效期限。

5.每一個關卡都要有根據其動態對象需求而量身定製的特定對象庫,並根據最小內存需求來優化。對象庫能夠靈活一點,在開發過程當中包含大量對象,但知道遊戲對象需求後就要具體一點。

6.保持聲音文件在內存的壓縮狀態也是必要之舉。

增強遊戲運行性能是一個漫長而具備挑戰性的過程,遊戲開發社區所分享的大量知識,以及Unity提供的出色分析工具爲《Shadow Blade》實現目標運行性能提供了極大幫助

相關文章
相關標籤/搜索