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 normal = myMesh.normals[i]; }
改為
Vector3[] meshNormals = myMesh.normals;
for (int i = 0; i < meshNormals.Length; i++) { Vector3 normal = meshNormals[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)
{
yield return new WaitForSeconds(1f); }
改為
WaitForSeconds delay = new WaitForSeconds(1f);
while (!isComplete) { yield return delay; }
- 如果由於協程產生了很多垃圾,則可以用其它方式代替協程實現相同功能。如果主要是對時間的控制則可以將邏輯寫到Update函數中;如果是控制一系列事情的先后執行順序則可以使用事件機制(觀察者模式)來實現各模塊的溝通。
* 除數組外的foreach的調用會產生額外的GC,盡量少用,5.5版本后該問題被解決。
*函數引用,無論是匿名還是具名函數,都會有堆內存分配,尤其是閉包closure會增加更多的內存占用,少量使用函數引用(一般是各種delegate了)。
*LINQ和正則表達式都會由於存在裝箱而產生垃圾,對性能要求比較高時應避免使用它們。
* struct結構是值類型,但當結構中包含引用類型時,垃圾回收器也不得不對整個結構進行檢查,當有大的結構數組存在時就會加大垃圾回收的負擔:
public struct ItemData
{
public string name; public int cost; public Vector3 position; } private ItemData[] itemData;
由於string是引用類型導致垃圾回收器對整個結構數組都需要檢查,拆分出來就可以避免該問題:
private string[] itemNames;
private int[] itemCosts; private Vector3[] itemPositions;
* 類被引用的數量越多,垃圾回收需要檢查的工作則越大,盡量減少沒必要的類引用。
* 在游戲暫停、場景切換等時機,可以主動進行垃圾回收,從而及時去除游戲中已經不必要的內存占用:
void Update()
{
if(Time.frameCount % 50 == 0) { System.GC.Collection(); } }
參考:https://unity3d.com/cn/learn/tutorials/topics/performance-optimization/optimizing-garbage-collection-unity-games?playlist=44069