Unity3D 移動開發代碼優化

1. 儘可能避免每幀處理html

比方:數組

function Update() { DoSomeThing(); }緩存

可改成每5幀處理一次:函數

function Update() { if(Time.frameCount % 5 == 0) { DoSomeThing(); } }佈局

2. 定時反覆處理用 InvokeRepeating 函數實現性能

比方。啓動0.5秒後每隔1秒運行一次 DoSomeThing 函數:優化

 

function Start() { InvokeRepeating("DoSomeThing", 0.5, 1.0); }3d

 

3. 優化 Update, FixedUpdate, LateUpdate 等每幀處理的函數orm

函數裏面的變量儘可能在頭部聲明。htm

比方:

function Update() { var pos: Vector3 = transform.position; }

可改成

private var pos: Vector3; function Update(){ pos = transform.position; }

 

4. 主動回收垃圾

給某個 GameObject 綁上下面的代碼:

function Update() { if(Time.frameCount % 50 == 0) { System.GC.Collect(); } }

 

5. 執行時儘可能下降 Tris 和 Draw Calls

預覽的時候,可點開 Stats,查看圖形渲染的開銷狀況。

特別注意 Tris 和 Draw Calls 這兩個參數。

通常來講,要作到:

Tris 保持在 7.5k 下面

Draw Calls 保持在 20 下面

 

6. 壓縮 Mesh

導入 3D 模型以後,在不影響顯示效果的前提下,最好打開 Mesh Compression。

Off, Low, Medium, High 這幾個選項,可酌情選取。

 

7. 避免大量使用 Unity 自帶的 Sphere 等內建 Mesh

Unity 內建的 Mesh,多邊形的數量比較大,假設物體不要求特別圓滑。可導入其它的簡單3D模型取代。

 

8. 優化數學計算

比方。假設可以避免使用浮點型(float),儘可能使用整形(int),儘可能少用複雜的數學函數比方 Sin 和 Cos 等等

 

下降固定增量時間

將固定增量時間值設定在0.04-0.067區間(即,每秒15-25幀)。您可以經過Edit->Project Settings->Time來改變這個值。這樣作減小了FixedUpdate函數被調用的頻率以及物理引擎運行碰撞檢測與剛體更新的頻率。假設您使用了較低的固定增量時間,並且在主角身上使用了剛體部件。那麼您可以啓用插值辦法來平滑剛體組件。

下降GetComponent的調用

使用 GetComponent或內置組件訪問器會產生明顯的開銷。您可以經過一次獲取組件的引用來避免開銷,並將該引用分配給一個變量(有時稱爲"緩存"的引用)。

好比。假設您使用例如如下的代碼:

function Update () {

transform.Translate(0, 1, 0);

 

}

經過如下的更改您將得到更好的性能:

 

var myTransform : Transform;

function Awake () {

myTransform = transform;

}

function Update () {

myTransform.Translate(0, 1, 0);

}

 

避免分配內存

您應該避免分配新對象。除非你真的需要。因爲他們再也不在使用時,會添加垃圾回收系統的開銷。

您可以經常反覆使用數組和其它對象,而不是分配新的數組或對象。

這樣作優勢則是儘可能下降垃圾的回收工做。同一時候,在某些可能的狀況下,您也可以使用結構(struct)來取代類(class)。這是因爲,結構變量主要存放在棧區而非堆區。

因爲棧的分配較快,並且不調用垃圾回收操做,因此當結構變量比較小時可以提高程序的執行性能。

但是當結構體較大時。儘管它仍可避免分配/回收的開銷。而它因爲"傳值"操做也會致使單獨的開銷,實際上它可能比等效對象類的效率還要低。

 

最小化GUI

使用GUILayout 函數可以很是方便地將GUI元素進行本身主動佈局。然而,這樣的本身主動化天然也附帶着必定的處理開銷。您可以經過手動的GUI功能佈局來避免這樣的開銷。

此外,您也可以設置一個腳本的useGUILayout變量爲 false來全然禁用GUI佈局:

function Awake () {

useGUILayout = false;

}

 

使用iOS腳本調用優化功能

UnityEngine 命名空間中的函數的大多數是在 C/c + +中實現的。從Mono的腳本調用 C/C++函數也存在着必定的性能開銷。您可以使用iOS腳本調用優化功能(菜單:Edit->Project Settings->Player)讓每幀節省1-4毫秒。此設置的選項有:

Slow and Safe – Mono內部默認的處理異常的調用

 

Fast and Exceptions Unsupported –一個高速運行的Mono內部調用。只是。它並不支持異常,所以應慎重使用。它對於不需要顯式地處理異常(也不需要對異常進行處理)的應用程序來講,是一個理想的候選項。

 

優化垃圾回收

 

如上文所述,您應該儘可能避免分配操做。

但是,考慮到它們是不能全然杜絕的,因此咱們提供兩種方法來讓您儘可能下降它們在遊戲執行時的使用:

假設堆比較小。則進行高速而頻繁的垃圾回收

這一策略比較適合執行時間較長的遊戲,當中幀率是否平滑過渡是基本的考慮因素。像這種遊戲通常會頻繁地分配小塊內存,但這些小塊內存僅僅是臨時地被使用。

假設在iOS系統上使用該策略,那麼一個典型的堆大小是大約 200 KB。這樣在iPhone 3G設備上。垃圾回收操做將耗時大約 5毫秒。假設堆大小添加到1 MB時,該回收操做將耗時大約 7ms。所以。在普通幀的間隔期進行垃圾回收有時候是一個不錯的選擇。一般,這種作法會讓回收操做執行的更加頻繁(有些回收操做並不是嚴格必須進行的),但它們可以高速處理並且對遊戲的影響很是小:

if (Time.frameCount % 30 == 0)

{

System.GC.Collect();

}

 

但是。您應該當心地使用這樣的技術,並且經過檢查Profiler來確保這樣的操做確實可以減小您遊戲的垃圾回收時間

假設堆比較大,則進行緩慢且不頻繁的垃圾回收

這一策略適合於那些內存分配 (和回收)相對不頻繁,並且可以在遊戲停頓期間進行處理的遊戲。假設堆足夠大,但尚未大到被系統關掉的話。這樣的方法是比較適用的。但是,Mono執行時會盡量地避免堆的本身主動擴大。所以,您需要經過在啓動過程當中預分配一些空間來手動擴展堆(ie,你實例化一個純粹影響內存管理器分配的"無用"對象):

 

function Start() {

 

var tmp = new System.Object[1024];

 

// make allocations in smaller blocks to avoid them to be treated in a special way, which is designed for large blocks

 

for (var i : int = 0; i < 1024; i++)

 

tmp[i] = new byte[1024];

 

// release reference

 

tmp = null;

 

}

 

遊戲中的暫停是用來對堆內存進行回收。而一個足夠大的堆應該不會在遊戲的暫停與暫停之間被全然佔滿。因此。當這樣的遊戲暫停發生時。您可以顯式請求一次垃圾回收:

 

System.GC.Collect();

 

另外,您應該慎重地使用這一策略並時刻關注Profiler的統計結果,而不是假定它已經達到了您想要的效果。

原文連接:http://blog.sina.com.cn/s/blog_6ad33d35010136fl.html

相關文章
相關標籤/搜索