Unity AssetBundle管理(一)
来源:互联网 发布:lol美服加速器免费mac 编辑:程序博客网 时间:2024/09/21 06:18
AssetBundle 是一种压缩文件,压缩时用到的压缩格式可以在打bundle的时候指定,BuildPipeline.BuildAssetBundles方法第二个参数可以指定压缩格式。
使用AssetBundle流程分为两部
1.把资源打成AssetBundle
先把资源(纹理,材质,模型)指定一个AssetBundle名字和后缀
然后调用BuildPipeline.BuildAssetBundles方法把资源打成AssetBundle
2.从AssetBundle中加载资源
常用的方式为用WWW先把AssetBundle下载下来(通过网络或者是从本地加载),然后从WWW中加载出来AssetBundle,然后从AssetBundle中加载出来资源,然后再把资源实例化(如果是纹理图片之类的可以直接使用)
3.关于内存
先来看看一个AssetBundle资源占的内存情况
用WWW下载完后,WWW会保留一份缓存,从WWW中加载出来AssetBundle后会有一份AssetBundle的缓存,从AssetBundle中加载出来资源后有一份资源的缓存,把资源实例化后会有一份实例化的缓存。所以我们要管理好这些缓存,及时把没用的清理掉。
我们先来写一个自动打AssetBundle的工具
首先创建一个文件夹 Art,我们把项目中需要的资源按类型放到这个文件夹
我们会把这里面的资源的AssetBundle的名字标记为它所在的文件夹的名字
自动标记名字和打Assetbundle的代码如下:
using UnityEngine;using System.Collections;using UnityEditor;using System.IO;using System.Collections.Generic;public class AssetBundleEditor { static string outPath = null; static string assetFullPath = Application.dataPath + "/Art/"; static string assetPath = @"Assets/Art/"; [MenuItem("Itools/BuildeAssetBundle")] public static void BuildeAssetBundle() { outPath = IPathTools.GetEditeABOutPath(); if (Directory.Exists(outPath)) { DirectoryInfo di = new DirectoryInfo(outPath); di.Delete(true); } Debug.Log("outPath "+ outPath); Directory.CreateDirectory(outPath); BuildPipeline.BuildAssetBundles(outPath, BuildAssetBundleOptions.None, EditorUserBuildSettings.activeBuildTarget); AssetDatabase.Refresh(); } [MenuItem("Itools/MarkAssetBundle")] public static void MarkAssetBundle() { AssetDatabase.RemoveUnusedAssetBundleNames(); assetFullPath = FixedWindowsPath(assetFullPath); Dictionary<string, string> bundlePathDic = new Dictionary<string, string>(); DirectoryInfo dir = new DirectoryInfo(assetFullPath); FileSystemInfo[] fileSystemInfo = dir.GetFileSystemInfos(); for (int i=0;i< fileSystemInfo.Length;i++) { FileSystemInfo tmpFile = fileSystemInfo[i]; if (tmpFile is DirectoryInfo) { string tmpPath = Path.Combine(assetFullPath, tmpFile.Name); //SceneOverView(tmpPath); ErgodicDirectory(tmpPath, bundlePathDic); } } AssetDatabase.Refresh(); } //遍历目录 public static void ErgodicDirectory(string path, Dictionary<string, string> bundlePathDic) { DirectoryInfo dir = new DirectoryInfo(path); if (dir != null) { FileSystemInfo[] fileInfo = dir.GetFileSystemInfos(); for (int i = 0; i < fileInfo.Length; i++) { FileSystemInfo tmpFile = fileInfo[i]; string tmpPath = Path.Combine(path, tmpFile.Name); if (tmpFile is DirectoryInfo) { ErgodicDirectory(tmpPath, bundlePathDic); } else { SetAssetBundleName(tmpFile, bundlePathDic); } } } else { Debug.Log("this path is not exit"); } } //设置assetbundle name public static void SetAssetBundleName(FileSystemInfo fileSystemInfo,Dictionary<string, string> bundlePathDic) { FileInfo fileInfo = fileSystemInfo as FileInfo; if (fileInfo.Extension == ".meta") { return; } string assetBundleName = fileInfo.Directory.Name; string fullPath = FixedWindowsPath(fileInfo.DirectoryName); int tmpCount1 = fullPath.Length; int tmpCount2 = assetFullPath.Length; int assetPathCount = tmpCount1 - tmpCount2; string assetBundlePath = fullPath.Substring(tmpCount2, assetPathCount); string path = assetPath + assetBundlePath+"/" + fileInfo.Name; Debug.Log("path "+ path); AssetImporter importer = AssetImporter.GetAtPath(path); //设置assetbundle name importer.assetBundleName = assetBundleName; //设置assetbundle 后缀 if (fileInfo.Extension == ".unity") { importer.assetBundleVariant = "u3d"; } else { importer.assetBundleVariant = "ab"; } //保存bundle的相对路径 int startIndex = fileInfo.FullName.IndexOf("Art"); int endIndex = fileInfo.FullName.Length; int count = endIndex - startIndex; string bundlePath = fileInfo.FullName.Substring(startIndex, count); if (!bundlePathDic.ContainsKey(assetBundleName)) { bundlePathDic.Add(assetBundleName, bundlePath); } } //修正路径 public static string FixedWindowsPath(string path) { path = path.Replace("\\","/"); return path; }}
其中函数MarkAssetBundle,ErgodicDirectory,SetAssetBundleName为标记AssetBundle名字的
函数BuildeAssetBundle为打AssetBundle的
这时我们会在unity菜单中看到这两个工具
加载AssetBundle
先来看一下我们的例子
Art下有三个文件夹Load,Material,Texture,按照我们的规则这三个文件夹下的资源的AssetBundle的名字和这三个文件夹一样。
这样我们用上面写的自动打AssetBundle的工具就打出了三个AsserBundle包分别是load.ab,material.ab,texture.ab,其中后缀.ab是在自动打AssetBundle的工具代码中指定的。其中正方体Cube在load.ab包中,材质m_Material在material.ab中,纹理detail在texture.ab中。
其中正方体Cube用的材质是m_Material,材质m_Material用的纹理是detail。
我们打出的AssetBundle如下:
在文件夹中会看到这些东西
其中以.ab(我们自己指定的)结尾的是我们的AssetBundle包,以.manifest结尾的是该AssetBundle的信息
因为我们的正方体Cube用的材质是m_Material,而m_Material在material.ab中,所以load.ab依赖material.ab
打AssetBundle后会有一个和AssetBundle输出目录一样名字的AssetBundle和.manifest文件,因为我们最终把AssetBundle打到目录StreamingAssets/windows中了,所以我们会看到这样两个文件
其中windows.manifest文件中记录了我们所有的AssetBundle信息和依赖关系
假如我们想从load.ab中加载出来立方体Cube,因为立方体Cube依赖material.ab,所以我们要把material.ab加载出来,又因为material.ab依赖texture.ab,所以我们要把texture.ab加载出来
我们先写一个简单的加载资源的代码,在下一章中我们会把所有AssetBundle的依赖和被依赖关系都管理起来,也会写出对AssetBundle缓存的清理的接口
using UnityEngine;using System.Collections;using System.Collections.Generic;public class Test : MonoBehaviour { string manifestPath = ""; public AssetBundle manifestLoader; public AssetBundleManifest assetManifest; public Dictionary<string, AssetBundle> abDic = new Dictionary<string, AssetBundle>(); bool isManifestFinished = false; // Use this for initialization void Start() { manifestPath = IPathTools.GetABManifestName(); StartCoroutine(LoadManifest()); string path = IPathTools.GetAssetBundlePath() + "/load.ab"; StartCoroutine(LoadAssetBundle(path)); } public IEnumerator LoadManifest() { WWW manifest = new WWW(manifestPath); yield return manifest; if (!string.IsNullOrEmpty(manifest.error)) { Debug.Log(manifest.error); } else { if (manifest.progress >= 1.0f) { isManifestFinished = true; Debug.Log("加载manifest成功"); manifestLoader = manifest.assetBundle; assetManifest = manifestLoader.LoadAsset("AssetBundleManifest") as AssetBundleManifest; //输出所有的AssetBundle的名字 string[] str = assetManifest.GetAllAssetBundles(); for (int i = 0; i < str.Length; i++) { Debug.Log(str[i]); } } } } //加载AssetBundle public IEnumerator LoadAssetBundle(string path) { if (!isManifestFinished) { yield return null; } WWW www = new WWW(path); yield return www; Debug.Log(path); if (!string.IsNullOrEmpty(www.error)) { Debug.Log(www.error); } else { AssetBundle ab = www.assetBundle; if (!abDic.ContainsKey(ab.name)) { abDic.Add(ab.name, ab); Debug.Log("abName " + ab.name); } string[] dependencies = assetManifest.GetAllDependencies(ab.name); for (int i = 0; i < dependencies.Length; i++) { if (!abDic.ContainsKey(dependencies[i])) { string abPath = IPathTools.GetAssetBundlePath() + "/" + dependencies[i]; yield return LoadAssetBundle(abPath); } } //测试实例化立方体Cube if (ab.name.Equals("load.ab")) { AssetBundle mainAb = abDic["load.ab"]; Object o = mainAb.LoadAsset("Cube"); Instantiate(o, Vector3.zero, Quaternion.identity); } } www.Dispose(); } //循环加载AssetBundle依赖 public IEnumerator LoadDependenciesAssetBundle(string path) { if (!isManifestFinished) { yield return null; } WWW www = new WWW(path); yield return www; Debug.Log("依赖 "+path); if (!string.IsNullOrEmpty(www.error)) { Debug.Log(www.error); } else { AssetBundle ab = www.assetBundle; if (!abDic.ContainsKey(ab.name)) { abDic.Add(ab.name, ab); Debug.Log("依赖abName " + ab.name); } string[] dependencies = assetManifest.GetAllDependencies(ab.name); for (int i = 0; i < dependencies.Length; i++) { string abPath = IPathTools.GetAssetBundlePath() + "/" + dependencies[i]; yield return LoadDependenciesAssetBundle(abPath); } } } void Destroy() { //manifestLoader.Unload(false); } }
- Unity AssetBundle管理(一)
- Unity AssetBundle管理(二)
- 揭开Unity AssetBundle庐山真面目(一)
- unity使用AssetBundle使用记录五)--AssetBundle内存管理
- Unity之AssetBundle读取与管理
- Unity之Assetbundle打包记录一
- unity使用AssetBundle使用记录一--打包
- Unity 5.x中的AssetBundle(一)
- unity AssetBundle
- unity-AssetBundle
- <Unity> AssetBundle
- Unity AssetBundle
- Unity 游戏框架搭建 (十一) 简易AssetBundle打包工具(一)
- Unity 游戏框架搭建 (十一) 简易AssetBundle打包工具(一)
- 「翻译」Unity中的AssetBundle详解(一)
- 「翻译」Unity中的AssetBundle详解(一)
- Unity 游戏框架搭建 (十一) 简易AssetBundle打包工具(一)
- unity使用AssetBundle使用记录一(续)--场景打包成AssetBundle并加载
- pip安装
- 记一次手动脱壳
- ndk编译C++,提示找不到头文件(ndk-build error: string: No such file or directory)
- ajax发送json数据到springmvc的controller
- 浏览器定位之 - 百度定位地图显示
- Unity AssetBundle管理(一)
- Linux获取jdk版本中的“1.7.0_75”字符串
- iOS常见的闪退问题及解决方法
- 清除缓存工具类
- 神奇的SpannableString
- jquery实现jsp页面报警
- cygwin "nodosfilewarning" warning
- 多线程之DelayQueue
- Android中Retrifit使用总结