2017-06-22 117 views
1

只有一個默認相機和一個GameObject。這段代碼爲什麼會造成內存泄漏?

爲什麼銷燬的遊戲對象仍然在內存中?我試圖手動調用GC,Resources.UnloadUnusedAssets和其他一些黑客沒有成功。 我的遊戲需要隨時創建GameObjects ... ObjectPooling當然可以完成,但由於玩家將玩數小時,並且有大量不同的精靈,我認爲這仍然是一個問題。

public class Game : MonoBehaviour 
{ 

    private List<GameObject> objects; 

    // Use this for initialization 
    void Start() 
    { 
     this.objects = new List<GameObject>(); 
    } 

    // Update is called once per frame 
    void Update() 
    { 
     foreach (var item in this.objects) 
     { 
      Destroy(item); 
     } 
     this.objects = new List<GameObject>(); 
     for (var i = 0; i <= 1000; i++) 
     { 
      GameObject gb = new GameObject(); 
      gb.name = i.ToString(); 
      SpriteRenderer renderer = gb.AddComponent<SpriteRenderer>(); 
      renderer.sprite = Resources.Load("Sprites/grass", typeof(Sprite)) as Sprite; 
      gb.transform.position = new Vector3(i, transform.position.y, transform.position.z); 
      this.objects.Add(gb); 
     } 
    } 
} 
+0

你創建和每一幀摧毀了太多的對象,沒有遊戲將永遠需要一個 – Lestat

+0

@Lestat我的遊戲本身不產生許多對象每一幀....此代碼是精心策劃,以重現問題一個簡單的方式...我會很感激,如果有人回答爲什麼內存永遠不會釋放(並保持永遠增長)在這樣一個簡單的代碼...謝謝。 –

+0

您好,問題是'gb.AddComponent ()'如在我的答案提及。您可以評論該代碼行以驗證該聲明。你需要在我的答案中鏈接兩個對象池。 – Programmer

回答

1

有三個問題在你的代碼:

.The問題是gb.AddComponent<SpriteRenderer>();。添加SpriteRenderer似乎沒有釋放內存,直到場景重新加載。 這是您的代碼中的主要問題。

卸下襬臂的this.objects = new List<GameObject>();Update功能。您已在Start函數中完成此操作。您只會創建更多不需要的列表。

該行代碼應該替換爲this.objects.Clear();,因爲在下一行添加更多對象之前,它將清除列表。

。您應該從未呼叫在UpdateResources.Load由於性能問題。這就像每個框架加載一個文件,這會影響遊戲的性能。當然


ObjectPooling可以做,但由於玩家將 玩幾個小時,有噸不同的精靈,我認爲這 仍然是一個問題。

沒有,沒有。對象池是解決這個,讓你不會再增加新的SpriteRenderer每一幀。

閱讀this的解釋和這個ArrayObjectPooling類可以很容易地用於對象池。

0

是您的遊戲對象的COM對象?如果是這樣,則通過將參考指針添加到列表中來增加參考指針,但不要通過處理gb變量來釋放參考計數器。

+0

我不知道什麼是一個COM對象(我是C#初學者),但通過查看統一文檔似乎並非如此。謝謝。 –

0

你有內存泄漏和原因呼喚你的垃圾收集器沒有做任何事情,因爲你是如何聲明

private List<GameObject> objects; 

的你宣佈這是現化公共類遊戲,當一個全局變量:MonoBehavior。

由於垃圾收集被調用,這將最終將List放入第2代的對象池中,直到該類不再使用時纔會被丟棄。

我看到兩個選項,你可以通過將它放在一個允許內存被普通垃圾回收器釋放的方法中來使對象的範圍更小,因爲它將成爲此時的第1代或第0代對象。

,或者您可以撥打TrimExcess()你的名單,這將降低列表的任何分配空間的內存下降到通過在列表中的對象持有的內存實際數量。

以下是關於垃圾收集一些有用的鏈接和對象世代C#:

https://docs.microsoft.com/en-us/dotnet/standard/garbage-collection/fundamentals

http://www.dotnettricks.com/learn/netframework/net-garbage-collection-in-depth