AssetBundle
设置资源AB
基本上unity所包含的资源文件,除了脚本文件都可以设置成ab资源。
生成AB资产
生成AB有两种方式
- 自定义打包
- AssetBundles-Browser-master插件
- 预览AB
这里使用插件打包,对于目前所有ab资源一目了然,如有ab设置错误也会有错误提示,我们已经设置好ab资源用它打开如图
正是因为unity支持‘/’来分层,所以我们用文件层次来设置ab名称
才使得对应ab包层级目录结构清晰明确 2. 打包设置根据当前ab资源选择不同压缩模式比较
压缩模式 | UnCompression | LZ4 | LZMA |
---|---|---|---|
Andriod平台大小 | 325kb | 160kb | 119kb |
- LZ4 解压读取速度快(推荐)
- LZMA 压缩率高,文件占用空间小,解压比较慢
获取AB加载
大致流程图示
下面示例从服务器中获取 tom ab资源一系列流程
要测试在服务中的ab资源
测试代码
1.连接服务器,获取主依赖
调用入口
StartCoroutine(GetDepends(host, "AB_Andriod_LZ4"));
具体实现
////// 服务器地址 /// string host = @"https://ab-test-1258795305.cos.ap-shanghai.myqcloud.com/"; ////// ab-依赖 /// public Dictionarydic_AB = new Dictionary (); /// /// 获取主依赖,本地存储依赖关系,下载全部ab /// /// 服务器根地址 /// 服务器下ab根文件名,以及主ab文件名称 ///IEnumerator GetDepends(string host_path, string dir_name) { dic_AB.Clear(); //目录跟路径 string root_path = host_path + "/" + dir_name; //获取主ab,拿到manifest获取依赖关系 AssetBundleManifest assetBundleManifestServer = null; //服务器 总的依赖关系 UnityWebRequest ServerManifestWWW = UnityWebRequestAssetBundle.GetAssetBundle(root_path + "/" + dir_name); Debug.Log("HTTP : " + ServerManifestWWW.url.ToString()); yield return ServerManifestWWW.SendWebRequest(); assetBundleManifestServer = (AssetBundleManifest)DownloadHandlerAssetBundle.GetContent(ServerManifestWWW).LoadAsset("AssetBundleManifest"); //存储各依赖关系 string[] depends_name = assetBundleManifestServer.GetAllAssetBundles(); for (int i = 0; i < depends_name.Length; i++) { AB_DATA ab_data = new AB_DATA(); ab_data.name = depends_name[i]; UnityWebRequest target_uwq = UnityWebRequestAssetBundle.GetAssetBundle(Path.Combine(root_path, ab_data.name)); yield return target_uwq.SendWebRequest(); if (target_uwq.isDone) { //下载ab到本地 StartCoroutine(DownLoadAssetBundelAbdSave(Path.Combine(root_path, ab_data.name))); //depends var depends = assetBundleManifestServer.GetAllDependencies(ab_data.name); ab_data.depends_name = new string[depends.Length]; for (int j = 0; j < depends.Length; j++) { ab_data.depends_name[j] = depends[j]; } dic_AB.Add(depends_name[i], ab_data); } } }
2.缓存已下载的ab资源
////// 下载AB文件并保存到本地 /// ///IEnumerator DownLoadAssetBundelAbdSave(string url) { WWW www = new WWW(url); yield return www; if (www.isDone) { //表示资源下载完毕使用IO技术把www对象存储到本地 SaveAssetBundle(Path.GetFileName(url), www.bytes, www.bytes.Length); } } /// /// 存储AB文件到本地 /// private void SaveAssetBundle(string fileName, byte[] bytes, int count) { string dir_path = Application.persistentDataPath + "/" + fileName; Debug.Log("存储路径 : " + dir_path); Stream sw = null; FileInfo fileInfo = new FileInfo(dir_path); sw = fileInfo.Create(); sw.Write(bytes, 0, count); sw.Flush(); sw.Close(); sw.Dispose(); Debug.Log(fileName + "下载并存储完成"); }
3.从本地磁盘读取ab并实例化
调用入口
private void LoadStream_OnClick() { //设置要加载的目标物体名 string ab_name = "tom.prefab"; string dir_path = Application.persistentDataPath + "/" + ab_name; //从已缓存的字节文件中加载tom StartCoroutine(LoadABFormStream(dir_path)); //加载tom所需的依赖 string[] ad_names = dic_AB[ab_name].depends_name; for (int i = 0; i < ad_names.Length; i++) { string dir_path_depends = Path.Combine(Application.persistentDataPath, ad_names[i]); //加载依赖时,直接加载出其ab包即可,不需要分解其依赖类型再去实例,unity自会处理 AssetBundle.LoadFromFile(dir_path_depends); //所以下面部分就不需要了 // StartCoroutine(LoadABFormStream(dir_path_depends)); } }
相关方式实现
////// 从字节文件读取ab,并且实例化 /// /// ///IEnumerator LoadABFormStream(string dir_path) { FileStream fileStream = new FileStream(dir_path, FileMode.Open, FileAccess.Read); AssetBundleCreateRequest request = AssetBundle.LoadFromStreamAsync(fileStream); yield return request; AssetBundle myLoadedAssetBundle = request.assetBundle; if (myLoadedAssetBundle == null) { Debug.Log("Failed to load AssetBundle!"); yield break; } //实例化ab InstanceAB_FormAssetBundle(myLoadedAssetBundle, myLoadedAssetBundle.name); fileStream.Close(); } private void InstanceAB_FormAssetBundle(AssetBundle assetBundle, string obj_name) { Object gameObject = null; if (obj_name.Contains(".mat")) { gameObject = assetBundle.LoadAsset (obj_name); Instantiate ((Material)gameObject); } else if (obj_name.Contains(".prefab")) { gameObject = assetBundle.LoadAsset (obj_name); Instantiate ((GameObject)gameObject); } }