【问题标题】:In Unity, how to remove a RenderTexture from memory when the scene is unloaded在 Unity 中,如何在场景卸载时从内存中删除 RenderTexture
【发布时间】:2018-10-30 23:29:39
【问题描述】:

我有一个统一的场景,我在其中使用着色器和渲染纹理进行一些计算。

为此,我有一个脚本来实例化渲染纹理和我需要的材质,然后将材质应用到现有渲染纹理并将结果写入实例化的渲染纹理中。

这基本上是我所拥有的:

public RenderTexture dstTex;
public RenderTexture srcTex1;
public RenderTexture srcTex2;
public Shader myComputeShader;
public Material myMaterial;

void Awake()
{

    //Create result render Texture
    dstTex = new RenderTexture(textureSizeX, textureSizeY, 16, RenderTextureFormat.ARGB32);
    dstTex.Create();

    //Create material
    myMaterial = new Material(myComputeShader);     
    myMaterial.SetTexture("_srcTex2", srcTex2);
}

void Update()
{
    //Apply material to srcTex1 and write result in dstTex
    Graphics.Blit(srcTex1, dstTex, myMaterial);
}    

现在这工作正常。 我的问题是,当我重新加载我的场景或加载另一个使用相同脚本的场景时,dstTex 没有重新初始化。

我的脚本实际上是用当前测量的高度图 (srcTex) 更新房间的高度图 (dstTex)。所以 srcTex 值会随着时间而变化,而 dstTex 会随着时间而被填充。

然后,当我重新加载我的场景时,我希望 dstTex 再次全黑,因为它再次被 dstTex = new RenderTexture(textureSizeX, textureSizeY, 16, RenderTextureFormat.ARGB32); 实例化。但事实并非如此,之前场景的值还在纹理中。

我尝试在脚本中添加以下行来解决此问题,但没有奏效:

void OnDestroy()
{   srcTex1.Release();
    srcTex2.Release();  
    dstTex.Release();

    srcTex1.DiscardContents();
    srcTex2.DiscardContents();
    dstTex.DiscardContents();
}

知道如何从内存中删除这些纹理吗?

【问题讨论】:

  • 您谈到了dstTex,但甚至没有在您的代码中的任何地方声明......
  • 是的对不起它实际上也是一个公共变量,我在我的帖子中添加了它。我不得不在这里写一个更简单的代码来解释我的问题,因为我的代码中有很多其他不相关的东西。

标签: c# unity3d memory textures render-to-texture


【解决方案1】:

我没有明确的答案,但这里有几个可能的原因,您的 RenderTexture 未按预期重置为全黑。

This GameDev SE post 暗示 RenderTextures 不一定被清除,如果你想重置纹理,你应该clear it explicitly

根据RenderTexture documentation,当您加载新关卡时,您的 RenderTexture 可能会丢失

请记住,渲染纹理内容在某些情况下可能会“丢失” 事件,例如加载新关卡、系统进入屏幕保护模式、 进出全屏等等。发生这种情况时,您现有的 渲染纹理将再次变为“尚未创建”,您可以检查 使用 IsCreated 函数。

所以这是我不确定的部分,但似乎在重新加载场景后,您的 RenderTexture 在重新创建时最终使用相同的硬件纹理。


至于您尝试的修复:

  1. RenderTexture.Release 的文档说它只是释放资源(并没有说它被明确清除):

RenderTexture.Release

该函数释放渲染器使用的硬件资源 质地。纹理本身不会被破坏,而是会被 使用时自动重新创建。

  1. RenderTexture.DiscardContents 的文档没有指定确切的行为,这是对 GPU 驱动程序的优化提示:

RenderTexture.DiscardContents

提示 GPU 驱动程序不会显示 RenderTexture 的内容 用过。

在某些平台上,如果您指明何时 不再需要 RenderTexture 的当前内容。这个 可以保存将其从一种内存复制到另一种内存时 纹理被重复使用。 Xbox 360、Xbox One 和许多移动 GPU 受益 从此。

此调用通常仅在给定的 RenderTexture 为 当前是一个活跃的渲染目标。在这个调用之后,内容 RenderTexture 未定义,因此用户不应尝试 在清除 RenderTexture 或之前访问其内容 绘制到它的每个像素。

【讨论】:

  • 我遇到了 RenderTexture 的内存泄漏,我通过调用 RenderTexture.Release 修复了它。即使超出范围,GC 似乎也无法正确释放其资源。
  • @rkachach 这正是 GC 所发生的。来自RenderTexture.Release() 的文档:“与其他“原生引擎对象”类型一样,重要的是要注意任何渲染纹理的生命周期,并在使用完它们时释放它们,因为它们不会像普通托管类型那样被垃圾收集。”
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多