唐老狮–Unity热更新之AssetBundle 出自:https://www.bilibili.com/video/BV1LD4y1m7kF?p=1
AB包理论基础 定义:特定于平台的资产压缩包,有点类似压缩文件。资产包括:模型、贴图、预设体、音效、材质等等
作用:
AB包资源打包
以下使用Asset Bundle Browser打包
在需要打包的资源的Asset Labels下选择标签
Asset Bundle Browse的Build页签
打包后在Assets同级的AssetBundles文件夹内:AssetBundles/PC/
PC:存储所有依赖关系
AB包文件:资源文件
manifest文件:AB包文件信息,当加载时提供关键信息,资源信息,依赖关系,版本信息等等
Build Target:打包平台
Output Path:输出路径
Clear Folder:是否清空文件夹
Copy to StreamingAssets:复制到StreamingAssets
Advanced Settings:
Compression:压缩方式
No Compression:不压缩
Standard Compression(LZMA):压缩最小,解压慢,使用时必须全部解压
Chunk Based Compression(LZ4):压缩较小,解压快,使用时按需解压
了解:一般不勾选
Exclude Type Information:在资源包中 不包含资源的类型信息
Force Rebuild:重新打包时需要重新构建包(和Clear Folders很像),它不会删除无用包
Ignore Type Tree Changes:增量构建检查时,忽略类型数的更改
Append Hash:将文件的哈希值附加到资源包上
Strict Mode:严格模式,如果打包时报错了,则打包直接失败无法成功
Dry Run Build:运行时构建
使用AB包资源文件 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 public Image img;void Start (){ AssetBundle ab = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "model" ); GameObject obj = ab.LoadAsset("Cube" , typeof (GameObject)) as GameObject; Instantiate(obj); AssetBundle.UnloadAllAssetBundles(false ); ab.Unload(false ); StartCoroutine(LoadABRes("head" , "23_11100001" )); } IEnumerator LoadABRes (string ABName, string resName ) { AssetBundleCreateRequest abcr = AssetBundle.LoadFromFileAsync(Application.streamingAssetsPath + "/" + ABName); yield return abcr; AssetBundleRequest abq = abcr.assetBundle.LoadAssetAsync(resName, typeof (Sprite)); yield return abq; img.sprite = abq.asset as Sprite; }
StreamingAssets在PC上可读可写,在Android/IOS上只读
AB包不能重复加载,否则报错
AB包依赖 AB的依赖:一个资源身上用到了别的AB包中的资源,这个时候如果只加载自己的AB包,通过它创建对象,会出现资源丢失的情况。所以需要把依赖包一起加载了才能正常
打包资源时,若依赖项没有打包,会把依赖项自动打包至同一包中
依赖包的核心知识——利用主包 获取依赖信息
1 2 3 4 5 6 7 8 9 10 11 12 13 14 void Start (){ AssetBundle abMain = AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + "PC" ); AssetBundleManifest abManifest = abMain.LoadAsset<AssetBundleManifest>("AssetBundleManifest" ); string [] strs = abManifest.GetAllDependencies("model" ); for (int i = 0 ; i < strs.Length; i++) { AssetBundle.LoadFromFile(Application.streamingAssetsPath + "/" + strs[i]); } }
AB包资源管理器 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.Events;namespace CT.Hotfix { public class ABManager : SingletonMono <ABManager > { private static string PathUrl = Application.streamingAssetsPath + "/" ; #if UNITY_STANDALONE private const string MainABName = "PC" ; #elif UNITY_ANDROID private const string MainABName = "Android" ; #endif private AssetBundle mainAB = null ; private AssetBundleManifest manifest = null ; private Dictionary<string , AssetBundle> abDic = new Dictionary<string , AssetBundle>(); new void Awake () { base .Awake(); } private void LoadAB (string abName ) { if (mainAB == null ) { mainAB = AssetBundle.LoadFromFile(PathUrl + MainABName); manifest = mainAB.LoadAsset<AssetBundleManifest>("AssetBundleManifest" ); } AssetBundle ab; string [] strs = manifest.GetAllDependencies(abName); for (int i = 0 ; i < strs.Length; i++) { if (!abDic.ContainsKey(strs[i])) { ab = AssetBundle.LoadFromFile(PathUrl + strs[i]); abDic.Add(strs[i], ab); } } if (!abDic.ContainsKey(abName)) { ab = AssetBundle.LoadFromFile(PathUrl + abName); abDic.Add(abName, ab); } } #region SyncLoad public T LoadRes <T >(string abName, string resName ) where T : Object { LoadAB(abName); T obj = abDic[abName].LoadAsset<T>(resName); if (obj is GameObject) return GameObject.Instantiate(obj); return obj; } public Object LoadRes (string abName, string resName, System.Type type ) { LoadAB(abName); Object obj = abDic[abName].LoadAsset(resName, type); if (obj is GameObject) return GameObject.Instantiate(obj); return obj; } #endregion #region AsyncLoad public void LoadResAsync <T >(string abName, string resName, UnityAction<T> callback ) where T : Object { StartCoroutine(ReallyLoadResAsync(abName, resName, callback)); } private IEnumerator ReallyLoadResAsync <T >(string abName, string resName, UnityAction<T> callback ) where T : Object { LoadAB(abName); AssetBundleRequest abr = abDic[abName].LoadAssetAsync<T>(resName); yield return abr; if (abr.asset != null ) { if (abr.asset is GameObject) { callback(GameObject.Instantiate(abr.asset) as T); } else { callback(abr.asset as T); } } } public void LoadResAsync (string abName, string resName, System.Type type, UnityAction<Object> callback ) { StartCoroutine(ReallyLoadResAsync(abName, resName, type, callback)); } private IEnumerator ReallyLoadResAsync (string abName, string resName, System.Type type, UnityAction<Object> callback ) { LoadAB(abName); AssetBundleRequest abr = abDic[abName].LoadAssetAsync(resName, type); yield return abr; if (abr.asset != null ) { if (abr.asset is GameObject) { callback(GameObject.Instantiate(abr.asset)); } else { callback(abr.asset); } } } #endregion public void UnLoad (string abName ) { if (abDic.ContainsKey(abName)) { abDic[abName].Unload(false ); abDic.Remove(abName); } } public void ClearAB () { AssetBundle.UnloadAllAssetBundles(false ); abDic.Clear(); mainAB = null ; manifest = null ; } } }
补充:AssetBundle加载 官方链接:https://docs.unity.cn/cn/2019.4/Manual/AssetBundles-Native.html
知乎参考链接:https://zhuanlan.zhihu.com/p/108335937