2017-06-22 43 views
1

デフォルトのカメラと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

あなたは1フレームごとにたくさんのオブジェクトを作成して破壊していますが、ゲームにそれを必要とするものはありません。 – Lestat

+0

@Lestat自分のゲーム自体はフレームごとに多くのオブジェクトを作成しません....簡単なやり方...誰かがメモリが決して解放されない(と永遠に成長し続ける)理由が、このような簡単なコードで答えると感謝します...ありがとう。 –

+0

こんにちは、問題は 'gb.AddComponent ()'私の答えで述べたようです。その行をコメントして、そのステートメントを確認することができます。あなたは2つの例が私の答えでリンクされているオブジェクトのプールが必要です。 – Programmer

答えて

1

あなたのコード内の三つの問題があります

【選択は、問題はgb.AddComponent<SpriteRenderer>();です。 SpriteRendererを追加すると、シーンがリロードされるまでメモリが解放されていないようです。 これはコードの主な問題です。 Update関数からthis.objects = new List<GameObject>(); .Remove

。すでにStart機能でこれを行っています。不要なリストだけを作成します。

このコード行をthis.objects.Clear();に置き換えると、次の行にオブジェクトを追加する前にリストがクリアされるためです。

。あなた起因するパフォーマンス上の問題にUpdate決してコールResources.Load必要があります。これは、フレームごとにファイルを読み込むようなもので、ゲームのパフォーマンスに影響します。当然の


ObjectPoolingは行われますが、プレイヤーが時間のために遊ぶ になりますし、別のスプライトのトンがあるので、私はこの は依然として問題だと思うことができました。

いいえ、いいえ。オブジェクトプールはこれに対する解決策であり、各フレームに新しいSpriteRendererを追加することはありません。

オブジェクトプールのために簡単に使用できるArrayObjectPoolingクラスの説明とこれについてはthisを参照してください。

0

GameObjectはCOMオブジェクトですか?その場合は、参照ポインタをリストに追加してインクリメントしますが、gb変数を破棄して参照カウンタを解放しないでください。

+0

私はCOMオブジェクト(私はC#の初心者です)が何であるかについては分かりませんが、Unityのドキュメントを見れば、そうではないようです。ありがとう。 –

0

あなたがメモリリークを持っているし、あなたのガベージコレクタは何もしていません呼び出す理由は、どのようにあなたが

private List<GameObject> objects; 

を宣言しているのは、あなたのパブリッククラスのゲームインスタンス化するときには、グローバル変数としてこれを宣言した:MonoBehaviorを。

ガベージコレクションが呼び出されると、これは最終的に、クラスがもはや使用されなくなるまで処分されないオブジェクトの第2世代のプールにリストを置きます。

実際には2つのオプションがあります。オブジェクトのスコープをメソッド内に配置することで、通常のガベージコレクタによってメモリが解放されるようにすることができます。

TrimExcess()をリストに追加すると、リストの割り当て領域のメモリを、そのリスト内のオブジェクトが実際に保持するメモリ量に減らすことができます。ここで

は、C#のためのガベージコレクタとオブジェクトの世代についてのいくつかの有用なリンクです:

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

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

関連する問題