天天看點

unity3d:Assetbundle模拟加載,同步加載,異步加載,依賴包加載,自動标簽,AB浏覽器,增量打包

AB自動設定标簽

檔案夾中每個prefab,單獨打包成一個assetbundle,使用于模型,單個UI面闆

unity3d:Assetbundle模拟加載,同步加載,異步加載,依賴包加載,自動标簽,AB浏覽器,增量打包

檔案夾内每個檔案夾打包成一個assetbundle,适用于圖集

unity3d:Assetbundle模拟加載,同步加載,異步加載,依賴包加載,自動标簽,AB浏覽器,增量打包

所有AB分發器配置資料在Editor/AssetBundle/Database/AssetPackage中,該目錄下存在目錄的一個映射結構,其中的每個序列化檔案對應一個AB分發器

unity3d:Assetbundle模拟加載,同步加載,異步加載,依賴包加載,自動标簽,AB浏覽器,增量打包

在打包前執行 make tag,通過讀上面對應配置,自動設定ab标簽與名字

public AssetBundleChecker(AssetBundleCheckerConfig config)
        {
            this.config = config;
            assetsPath = AssetBundleUtility.PackagePathToAssetsPath(config.PackagePath);
            importer = AssetBundleImporter.GetAtPath(assetsPath);
        }

        public void CheckAssetBundleName()
        {
            if (!importer.IsValid)
            {
                return;
            }

            var checkerFilters = config.CheckerFilters;
            if (checkerFilters == null || checkerFilters.Count == 0)
            {
                importer.assetBundleName = assetsPath;
                string[] bufName = importer.assetBundleName.Split('.');
                MenuAssetBundle.m_abNameStr.AppendFormat("public const string {0} = \"{1}\";", bufName[0], bufName[0]);
                MenuAssetBundle.m_abNameStr.AppendLine();
            }      

AB打包

采用增量打包方式,隻會打包改動的資源

BuildPipeline.BuildAssetBundles(info.outputDirectory, info.options, info.buildTarget);

調用該函數,unity會自動根據資源的标簽進行打包,而且是增量打包,

  1. 對于資源沒有變更的bundle包,不會觸發重新打包;
  2. 資源沒變,即使生成目錄下的bundle包被删除了,unity也不會重新打包;
  3. 生成目錄下的bundle包對應的manifase被删了,會重新打包;
  4. 可以使用BuildAssetBundleOptions.ForceRebuildAssetBundle參數觸發強制重新打包。

打包完畢把md5資訊寫入

FileStream fs = new FileStream(newFilePath, FileMode.CreateNew);
            StreamWriter sw = new StreamWriter(fs);
            for (int i = 0; i < files.Count; i++)
            {
                string file = files[i];
                //if (file.Contains("StreamingAssets")) continue;
                string ext = Path.GetExtension(file);
                if (file.EndsWith(".meta") || file.Contains(".DS_Store")) continue;

                string md5 = NTG.Util.md5file(file);
                string value = file.Replace(m_OutputPath + "/", string.Empty);

                FileInfo fileInfo = new FileInfo(file);
                int size = (int)(fileInfo.Length / 1024) + 1;

                //if (value != "StreamingAssets" && value != "StreamingAssets.manifest")
                sw.WriteLine(value + "|" + md5 + "|" + size);
            }
            sw.Close(); fs.Close();      

AB包浏覽器

友善檢視一個ab包内具體包含哪些

unity3d:Assetbundle模拟加載,同步加載,異步加載,依賴包加載,自動标簽,AB浏覽器,增量打包

黃色的是代表被多個ab包包含的資源

AB異步加載

編輯器下繞過打包模拟加載

if (SimulateAssetBundleInEditor)
      {
        string[] assetPaths = AssetDatabase.GetAssetPathsFromAssetBundleAndAssetName(assetBundleName, assetName);
        if (assetPaths.Length == 0)
        {
          Debug.LogError("There is no asset with name \"" + assetName + "\" in " + assetBundleName);
          return null;
        }

                // @TODO: Now we only get the main object from the first asset. Should consider type also.
                UnityEngine.Object target = AssetDatabase.LoadMainAssetAtPath(assetPaths[0]);
        operation = new AssetBundleLoadAssetOperationSimulation (target);
      }      

異步加載

static public AssetBundleLoadAssetOperation LoadAssetAsync (string assetBundleName, string assetName, System.Type type,string path = "")
    {
      Log(LogType.Info, "Loading " + assetName + " from " + assetBundleName + " bundle");
  
      AssetBundleLoadAssetOperation operation = null;
            {
                assetBundleName = RemapVariantName (assetBundleName);
        LoadAssetBundle (assetBundleName,false,path);
        operation = new AssetBundleLoadAssetOperationFull (assetBundleName, assetName, type);
  
        m_InProgressOperations.Add (operation);
      }
  
      return operation;
    }      
  1. 加載a生成一個AssetBundleLoadOperation,為異步操作加載
public abstract class AssetBundleLoadOperation : IEnumerator
  {
    public object Current
    {
      get
      {
        return null;
      }
    }
    public bool MoveNext()
    {
      return !IsDone();
    }
    
    public void Reset()
    {
    }
    
    abstract public bool Update ();
    
    abstract public bool IsDone ();
  }      
  1. 找到a所有依賴ab包(例如b,c)
string[] dependencies = m_AssetBundleManifest.GetAllDependencies(assetBundleName);
      if (dependencies.Length == 0)
        return;
        
      for (int i=0;i<dependencies.Length;i++)
        dependencies[i] = RemapVariantName (dependencies[i]);
        
      // Record and load all dependencies.
      m_Dependencies.Add(assetBundleName, dependencies);
      for (int i=0;i<dependencies.Length;i++)
        LoadAssetBundleInternal(dependencies[i], false,path);      
  1. 把b,c加入到m_DownloadingWWWs中,用www加載
  2. AssetBundleManager中update判斷m_DownloadingWWWs每加載完一項,放入到m_LoadedAssetBundles已加載完ab表中
  3. 在AssetBundleManager的Update中周遊m_InProgressOperations中每一項AssetBundleLoadOperation,在a的AssetBundleLoadOperation的update中判斷它的依賴b,c是否全部加載完(在m_LoadedAssetBundles中找到值),依賴全加載完,執行加載a的自身ab的請求m_Request = bundle.m_AssetBundle.LoadAssetAsync (m_AssetName, m_Type);
  4. b,c先加載完,a再加載完,AssetBundleLoadOperation中MoveNext傳回false,代表執行完畢,可以根據ab包執行個體化gameobjec之類

同步加載

static private AssetBundle LoadAssetBundleSync(string abname, string abPath = "")
        {

            AssetBundle bundle = null;
            if (!m_LoadedAssetBundles.ContainsKey(abname))
            {
                //byte[] stream = null;
                string uri;
                if (abPath != "")
                {
                    uri = abPath + "/" + abname;
                }
                else
                {
                    uri = AppConst.AbDataPath + "/" + abname;
                }
                //Debug.Log("Loading AssetBundle: " + uri);

                if (!File.Exists(uri))
                {
                    Debug.LogError(String.Format("AssetBundle {0} Not Found", uri));
                    return null;
                }

                //stream = File.ReadAllBytes(uri);

                bundle = AssetBundle.LoadFromFile(uri);
                //stream = null;
                LoadedAssetBundle loBundle = new LoadedAssetBundle(bundle);
          
                m_LoadedAssetBundles.Add(abname, loBundle);

                if (m_Dependencies != null && m_Dependencies.ContainsKey(abname))
                {
                    for (int i = 0; i < m_Dependencies[abname].Length; i++)
                    {
                        LoadAssetBundleSync(m_Dependencies[abname][i]);
                    }
                }
            }
            else
            {
                LoadedAssetBundle loBundle = null;
                m_LoadedAssetBundles.TryGetValue(abname, out loBundle);
                bundle = loBundle.m_AssetBundle;
            }
            return bundle;
        }      

關于AssetBundle.LoadFromMemroy記憶體翻倍問題

繼續閱讀