异步加载+内存分析

异步加载

Resources和AB包的同步加载与异步加载对比代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class AsyncLoad : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        //Resources的同步异步加载代码
        //同步加载代码
        //GameObject.Find("/Canvas/Image").GetComponent<Image>().sprite = Resources.Load<Sprite>("EXP");
        //通过开启协同,执行最后一个异步Resources加载资源
        //StartCoroutine(LoadImage());
        

        //AB包的同步异步加载代码
        //AssetBundle ab = AssetBundle.LoadFromFile(Config.ABPath + "/test2");
        //GameObject.Find("/Canvas/Image").GetComponent<Image>().sprite=ab.LoadAsset<Sprite>("EXP");
        StartCoroutine(LoadAB());
        
    }

    IEnumerator LoadImage()
    {
        //开启一个异步加载
        ResourceRequest rr = Resources.LoadAsync<Sprite>("EXP");
        //协同会在加载资源成功后,继续执行(底层封装了线程加载资源)
        yield return rr;
        //将加载成功的资源,显示出来
        GameObject.Find("/Canvas/Image").GetComponent<Image>().sprite = rr.asset as Sprite;
    }
    IEnumerator LoadAB()
    {
        AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(Config.ABPath + "/test2");
        yield return abcr;
        GameObject.Find("/Canvas/Image").GetComponent<Image>().sprite = abcr.assetBundle.LoadAsset<Sprite>("EXP");
    }
}

        想要区分是否成功执行异步加载,可以在运行游戏前开启暂停键,之后运行,若跨帧实现图片加载功能(第一帧图片为白图,下一帧图片加载出指定图片),则证明成功实现了异步加载功能。

内存分析

以Unity2021版的Profiler视窗为例(建议同学们也打开自己的视窗自行观察):

我们选择Profiler视窗中的Memory,并运行游戏观察其实时操作的内存占用情况。

(个人理解)

 通过Memory Profiler图观察,在以AB包为例观察其各功能在运行时内存的占用情况可知(本次测试观察Graphics&Graphics Driver),当仅加载AB包时,其内存会短暂出现短幅上升又下降的情况(该AB包为默认压缩状态,此过程可说明AB包在解压),最终下降到趋于运行无操作时内存占用量,说明加载AB包在运行时并不实际占用内存;而当加载图片时,内存占用量增加,此情况说明当AB包加载资源并显示到游戏界面时,才实际占用内存;当我们卸载AB包不销毁图片时,该张图片占用的内存不会被释放,而当我们重新加载AB包资源并加载其他图片覆盖未被销毁的图片,其图片会作为游离资源存放在内存中。

原因:Unity的回收机制为"懒回收"机制,它默认不会回收此类游离资源,若实际开发项目需要考虑内存情况,建议自行编写回收机制(但不建议过于频繁回收)决定何时回收此类游离资源,释放内存。

编写以上测试的代码:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Memory : MonoBehaviour
{
    AssetBundle ab;
    public Image image;
    public void LoadFile()
    {
        ab = AssetBundle.LoadFromFile(Config.ABPath + "/bigtest");
    }
    public void LoadImage()
    {
        image.sprite = ab.LoadAsset<Sprite>("PanelTest");
    }
    public void UnLoadFile()
    {
        //参数代表,是否将场景中通过AB包加载出来的资源,同AB包一起销毁
        ab.Unload(false);
    }
    public void Recycling()
    {
        //将所有没有再使用的资源进行回收
        Resources.UnloadUnusedAssets();
    }
}

场景视图及层级面板情况:

扫描二维码关注公众号,回复: 17664062 查看本文章

该系列专栏为网课课程笔记,仅用于学习参考。