2017-06-22 97 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