AssetBundle资源管理,第二步使用协程加载ab包资源--unity学习

为什么要使用协程加载AB包?

因为协程能够实现等待资源异步加载完毕后,再同步处理后续的代码逻辑。也就是说在代码逻辑上是同步,但实际是异步加载的方式,能够保证功能的完整性。

 /**
  加载UI面板
  */
 public IEnumerator loadUIByName(string uiname)
 {
     //加载ab包资源及其依赖的资源   
     string assetBundleName = getUIAssetBundleName(uiname);
     yield return loadAssetBundleWithDependienies(assetBundleName);

     //资源加载完成后,实例化UI对象
     LoadedAssetBundle loadedAssetBundle = getLoadedAssetBundle(assetBundleName);
     AssetBundle assetBundle = loadedAssetBundle.assetBundle;
     if (assetBundle != null)
     {
         GameObject go = assetBundle.LoadAsset<GameObject>(uiname);
         GameObject.Instantiate(go);
         go.name = uiname;
         if (!go.activeSelf)
             go.SetActive(true);

         if(!showInternal(uiname, loadedAssetBundle))
         {
             Debug.Log("showUI:" + uiname + "Error");
         }
     }
 }

在加载ab包的同时,我们需要加载它相关的依赖包,这个依赖包的数据在manifest文件中有记录,通常会直接读取主包的manifest文件,这里面记录了所有包及其依赖信息,所以在加载依赖包之前需要先加载主包数据。

    //加载主包
    private void loadMianAB()
    {
        if (mainBundle == null)
        {
            mainBundle = AssetBundle.LoadFromFile(ROOT_PATH + "AssetBundles");
            mainBundleManifest = mainBundle.LoadAsset<AssetBundleManifest>("AssetBundleManifest");
        }
    }

主包加载后,通过mainBundleManifest.GetAllDependencies(path),可以读取该包所有的依赖包,这些依赖包也都需要加载。当然还会存在依赖包中还有依赖包,这种情况可以使用递归的方式处理,这里就暂时不考虑。

    /**
     加载ab包资源及其所依赖的ab包
     */
    public bool loadAssetBundleWithDependienies(string assetBundleName)
    {
        loadAssetBundleAsyn(assetBundleName);

        //加载依赖包
        string[] dependencies = null;
        string relativePath = assetBundleName;
        dependencies = mainBundleManifest.GetAllDependencies(relativePath);
        foreach (string dependency in dependencies)//遍历依赖包名,加载
        {
            loadAssetBundleAsyn(dependency);
        }

        return true;
    }

ab包的重复加载会报错,所以需要一个字典保存所有加载过的ab包,在加载之前还需要判断该包是否已经加载过,若已加载直接从字典中取,未加载则开启协程加载。

//重复加载报错

The AssetBundle 'player.unity3d' can't be loaded because another AssetBundle with the same files is already loaded.

  /**
   开启协程异步加载ab包资源,若已加载则从缓存中取
   */
  public bool loadAssetBundleAsyn(string abName)
  {
      LoadedAssetBundle bundle = null;
      loadedAssetBundles.TryGetValue(abName, out bundle);
      if (bundle != null)
      {
          bundle.referencedCount++;
          return true;
      }

      StartCoroutine(loadSingleAssetBundle(abName));
      return true;
  }

开启协程加载单个ab包,使用AssetBundle.LoadFromFileAsync(path)异步的方式加载,协程等待加载完成。


    /**
     异步加载单个ab包资源,加载完成后,缓存进已加载字典中
     */
    private IEnumerator loadSingleAssetBundle(string abName)
    {
        LoadingAssetInfo info = new LoadingAssetInfo();
        info.path = ROOT_PATH + abName;
        info.abReq = AssetBundle.LoadFromFileAsync(info.path);

        yield return info.isDone;

        //Debug.Log("协程加载" + abName + "完成");
        loadedAssetBundles.Add(abName, new LoadedAssetBundle(info));
        assetBundleNames.Add(abName);
    }

这里的loadingAssetInfo封装了加载信息:是否完成、进度、错误、引用等,方便以后扩展成www的加载方式。loadedAssetBundle封装了ab包引用,计数引用,卸载等方法。这些都可以根据自己的需要灵活使用。

总结一下加载的过程,首先开启主协程进行加载,在主协程中开启多个分支协程,进行异步加载单个ab包资源,等到所有的分支协程都已完成异步加载后,主协程也完成了使命,执行后续打开界面的流程。

  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值