UnityWebRequest在使用它重复加载图像时填满内存

UnityWebRequest filling up Memory when using it to load images repeatedly

我正在使用 UnityWebRequest 加载图像。

这是代码。

            UnityWebRequest uwr;
            StartCoroutine(LoadImageCorroutine());
            IEnumerator LoadImageCorroutine()
            {
                using (uwr = UnityWebRequestTexture.GetTexture(@"file:///C://UnityTests/Filerepository/Items/3faju5ozafrz.png"))
                {
                    yield return uwr.SendWebRequest();
                    rawImage.texture = DownloadHandlerTexture.GetContent(uwr);

                    //Debug.Log(i.ToString());
                }
                uwr.Dispose();
                StopCoroutine(LoadImageCorroutine());
            }

我 运行 进行了一些性能测试,发现每次我调用协程时内存使用量都会上升,之后就不会下降。

考虑到 CPU 负载随时间下降,协程似乎正确停止或至少处于空闲状态。

如何摆脱 UnityWebRequest 加载到我的内存中的任何内容?

我自己已经 运行 遇到过这个问题。您可以使用 profiler (CTRL + 7) and do a memory snapshot

查看会发生什么
  • 点击内存模块
  • 在底部从"Simple"切换到"Detailed"
  • 点击采样
  • 结帐"Assets"→ "Texture2D"

在运行你的例程之前和之后。

剧透:您会看到,在下载例程的每个 运行 之后,内存中都会多出一个从未被破坏的纹理资源。

问题是通过 UnityWebRequestTexture.GetTexture 下载的任何 Texture 未被 GC 收集 即使它不再被引用!因此协程的每个 运行 都会向您的内存中添加一个纹理实例。


为了解决这个一旦你知道你真的想要破坏你必须这样做的纹理"manually":

IEnumerator LoadImageCorroutine()
{
    using (var uwr = UnityWebRequestTexture.GetTexture(@"file:///C://UnityTests/Filerepository/Items/3faju5ozafrz.png"))
    {
        yield return uwr.SendWebRequest();

        // I would always check for errors first
        if(uwr.isHttpError || uwr.isNetworkError)
        {
            Debug.LogError($"Could not load texture do to {uwr.responseCode} - \"{uwr.error}\"", this);
            yield break;
        }

        <b>// Destroy the current texture instance
        if(rawImage.texture) 
        {
            Destroy(rawImage.texture);
        }
     </b>
        rawImage.texture = DownloadHandlerTexture.GetContent(uwr);

        //Debug.Log(i.ToString());
    } 

    // since you are using "using" there is no need to call Dispose() manually

    // This is anyway the end of your coroutine .. you do not want to call
    // StopCoroutine(LoadImageCorroutine()) here
}