【问题标题】:Memory leak when Camera.targetTexture = new RenderTexture(...)Camera.targetTexture = new RenderTexture(...) 时的内存泄漏
【发布时间】:2018-10-31 10:01:49
【问题描述】:

我已经编写了一个 EditorWindow,它将摄像机的视图呈现到一个附加的编辑器窗口中。为了在调整窗口大小时立即适应,在tick时间重新分配相机的目标纹理(实际上只在必要时进行)以演示问题:

public class PlayerViewWindow : EditorWindow
{
    private Camera PlayerViewCamera; // References a camera in the scene

    public void OnGUI()
    {
        PlayerViewCamera.targetTexture = new RenderTexture((int)position.width, (int)position.height, 24, RenderTextureFormat.ARGB32);
        PlayerViewCamera.Render();
        GUI.DrawTexture(new Rect(0, 0, position.width, position.height), PlayerViewCamera.targetTexture);       
    }
}

当我激活此窗口时,重新分配相机目标纹理会导致内存泄漏。那么:为什么旧的目标纹理没有被垃圾收集? 有没有办法显式销毁旧的目标纹理?

谢谢

【问题讨论】:

    标签: c# unity3d rendering


    【解决方案1】:

    来自RenderTexture Documentation

    与其他“原生引擎对象”类型一样,重要的是要注意任何渲染纹理的生命周期,并在使用 Release 函数完成使用它们时释放它们,因为它们不会像正常托管的那样被垃圾收集类型。

    所以在附加新的之前,只需在旧的RenderTexture 上调用Release()

    public class PlayerViewWindow : EditorWindow
    {
        private Camera PlayerViewCamera; // References a camera in the scene
    
        public void OnGUI()
        {
            if(PlayerViewCamera.targetTexture != null)
            {
                PlayerViewCamera.targetTexture.Release();
            }
    
            PlayerViewCamera.targetTexture = new RenderTexture((int)position.width, (int)position.height, 24, RenderTextureFormat.ARGB32);
            PlayerViewCamera.Render();
            GUI.DrawTexture(new Rect(0, 0, position.width, position.height), PlayerViewCamera.targetTexture);       
        }
    }
    

    【讨论】:

      【解决方案2】:

      您必须像derHugo 在他的回答中所说的那样使用它后释放RenderTexture。不幸的是,每次调用OnGUI 时创建和销毁RenderTexture 的成本很高,而且OnGUI 的调用频率甚至比Update 函数更频繁。

      最好使用RenderTexture.GetTemporary 获得一个临时渲染,然后在使用完毕后使用RenderTexture.ReleaseTemporary 释放它。 请注意,过去在某些平台上 RenderTexture.ReleaseTemporary 函数存在错误。我认为它现在已修复,但如果您遇到问题,请坚持使用 other 解决方案。

      public class PlayerViewWindow : EditorWindow
      {
          private Camera PlayerViewCamera; // References a camera in the scene
      
          public void OnGUI()
          {
              Vector2 size = new Vector2(position.width, position.width);
              //Get temporary RenderTexture
              RenderTexture tempRT = RenderTexture.GetTemporary((int)size.x, (int)size.y, 24, RenderTextureFormat.ARGB32);
              PlayerViewCamera.targetTexture = tempRT;
              PlayerViewCamera.Render();
              GUI.DrawTexture(new Rect(0, 0, size.x, size.x), PlayerViewCamera.targetTexture);
              //Release temporary RenderTexture
              RenderTexture.ReleaseTemporary(tempRT);
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2013-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-05-15
        • 2013-05-25
        • 2021-05-08
        相关资源
        最近更新 更多