Unity堆記憶體優化

2022-11-24 22:16:14 字數 2203 閱讀 1508

unity中減少堆記憶體分配以減少垃圾**處理:

只有區域性變數且為值類值的變數是從stack棧中分配記憶體,其它所有情況都是從heap堆中分配內在。

* 快取獲取到的資料。

* 頻繁被呼叫的函式中儘量少的分配空間。如update函式,快取變數或者增加時間判斷每延遲多少時間後再執行一次而沒必要每幀執行。

* 複用集合類變數,如list資料,當有新資料時clear()後重新新增而不是new list()。

* 使用快取池object pooling,網上相關教程挺多的。

* string: 

- string是引用型別,減少沒必要的新string儘量快取;

- text元件文字若經常變化,可以考慮將不變的文字和變化的文字拆為多個text元件;

- string的+操作每次都會產生垃圾,請用stringbuilder代替之,尤其注意在update()中使用string;

- 不需要呼叫測試之後應該移除所有的debug.log(),每次呼叫至少產生並丟棄一個string,即便是空呼叫不輸出任何東西也一樣;

- 不要用 string.compare或string.compareto返回0來比較相等,而是用作排序sort。(非記憶體優化建議)

* unity函式呼叫:

- 有些函式或屬性每次呼叫都會產生新的陣列並返回,儘量快取結果,如mesh.normals

for (int i = 0; i < mymesh.normals.length; i++)

改為

vector3 meshnormals =mymesh.normals;

for (int i = 0; i < meshnormals.length; i++)

- gameobject.name和gameobject.tag同樣每次呼叫都會產生新的string,當檢查是否相等時請使用gameobject.comparetag()代替,它不會產生垃圾;

- 其它一些函式同樣有類似的替代呼叫,如 input.gettouch() 和 input.touchcount 代替 input.touches, 或者 physics.spherecastnonalloc() 代替physics.spherecastall();

* 儘量避免裝箱拆箱,如string.format()傳入值型別資料時必然存在將值型別裝箱為object型別的轉換。

* 協程coroutines:

- yield return null代替yield return 0;

- 減少相同的new操作:

while (!iscomplete)

改為

waitforseconds delay = newwaitforseconds(1f);

while (!iscomplete)

- 如果由於協程產生了很多垃圾,則可以用其它方式代替協程實現相同功能。如果主要是對時間的控制則可以將邏輯寫到update函式中;如果是控制一系列事情的先後執行順序則可以使用事件機制(觀察者模式)來實現各模組的溝通。

* 除陣列外的foreach的呼叫會產生額外的gc,儘量少用,5.5版本後該問題被解決。

*函式引用,無論是匿名還是具名函式,都會有堆記憶體分配,尤其是閉包closure會增加更多的記憶體佔用,少量使用函式引用(一般是各種delegate了)。

*linq和正規表示式都會由於存在裝箱而產生垃圾,對效能要求比較高時應避免使用它們。

* struct結構是值型別,但當結構中包含引用型別時,垃圾**器也不得不對整個結構進行檢查,當有大的結構陣列存在時就會加大垃圾**的負擔:

public structitemdata

private itemdata itemdata;

由於string是引用型別導致垃圾**器對整個結構陣列都需要檢查,拆分出來就可以避免該問題:

private string itemnames;

private int itemcosts;

private vector3 itempositions;

* 類被引用的數量越多,垃圾**需要檢查的工作則越大,儘量減少沒必要的類引用。

* 在遊戲暫停、場景切換等時機,可以主動進行垃圾**,從而及時去除遊戲中已經不必要的記憶體佔用:

voidupdate()  }

參考: