前段时间做了一个项目,刚好使用到了AssetBundle资源打包的东西,于是花了点时间研究了一下AssetBundle.
AssetBundle 打包
我用NGUI插件加载了一张图片,并且把它拖拽为预制名为Texture3.prefab 和 Texture4.prefab .下面是我的打包函数
[MenuItem("Assets/Build AssetBundle From Selection - Track dependencies")]
static void ExportResource () {
// 打开保存面板,获得选择的路径
string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource", "unity3d");
if (path.Length != 0) {
// 选择要保存的对象
Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
//开始打包
BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets,BuildTarget.StandaloneWindows);
//打包完成提示
EditorUtility.DisplayDialog("", "Build Completed", "OK");
//刷新资源目录
AssetDatabase.Refresh();
}
}
说明一下:
1.我们打包的资源的后缀格式可以是 ".assetbundle" 或者 ".unity3d" 。笔者这里使用的是后者
2. 解释一下打包函数的参数,第一个参数 Selection.activeObject 是我们打包的mainAsset ,
第二个参数 selection 是我们选择的对象过滤后的物体,可以为空,第三个参数 path 是 打包的资源的
保存路径 ,第四个参数是打包选项 ,我这里选用的两个选项 分别代表 打包所有有关联的对象和强制
打包全部的资源,详情请查找API文档 第五个参数是打包的平台。
AssetBundle加载
下面是我写的加载函数:
public string[] textureName;
// Use this for initialization
void Start () {
for (int i = 0; i < textureName.Length; i++)
{
StartCoroutine(LoadAssetBundle(PlatflamPath() + textureName[i] + ".unity3d", textureName[i]));
}
}
static public IEnumerator LoadAssetBundle(string filepath,string assetName) {
WWW www = new WWW(filepath);
yield return www;
if (www == null) {
Debug.Log(" www is null ");
}
else if (www.error != null) {
Debug.Log("error " + www.error);
}
else if (www.isDone) {
AssetBundle assetBundle = www.assetBundle;
AssetBundleRequest requet = assetBundle.LoadAsync(assetName, typeof(GameObject));
yield return requet;
if (requet.isDone) {
GameObject obj = Instantiate(requet.asset) as GameObject;
}
}
www.Dispose();
www = null;
}
static public string PlatflamPath()
{
return string.Format("file://{0}", Application.streamingAssetsPath) + "/";
}
AssetBundle依赖资源\共享资源打包
上面的两个预制都是用了同一张图片,我们可以将这张图片打到没一个包里面去,我们上面将的就是这种情况。这样子做的话有些弊端,比如内存有点让费,并且当这张图片有所改变的时候,两个包需要重新打包。当然,我们也可以使用AssetBundle的依赖资源\共享资源进行打包。主要会使用到下面两个函数,
BuildPipeline.PushAssetDependencies():依赖资源压栈;
BuildPipeline.PopAssetDependencies():依赖资源出栈。
笔者将上表面的Texture3.prefab复制了两份,改为Texture1.prefab 和 Texture2.prefab。还准备好预制的图片
下面是我的打包函数:
[MenuItem("Assets/Build Rely AssetBundle")]
static public void ExportRelyAssetBundle() {
string filePath = Application.streamingAssetsPath+"/";
if (filePath.Length <= 0) {
return;
}
BuildAssetBundleOptions buildOp = BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets
| BuildAssetBundleOptions.DeterministicAssetBundle;
BuildPipeline.PushAssetDependencies();
Object shared = AssetDatabase.LoadMainAssetAtPath("Assets/Textures/rainDrop.png");
BuildPipeline.BuildAssetBundle(shared, null, filePath + shared.name + ".unity3d", buildOp, BuildTarget.StandaloneWindows);
BuildPipeline.PushAssetDependencies();
Object tex1 = AssetDatabase.LoadMainAssetAtPath("Assets/Textures/Texture1.prefab");
BuildPipeline.BuildAssetBundle(tex1, null, filePath + tex1.name + ".unity3d", buildOp, BuildTarget.StandaloneWindows);
BuildPipeline.PopAssetDependencies();
BuildPipeline.PushAssetDependencies();
Object tex2 = AssetDatabase.LoadMainAssetAtPath("Assets/Textures/Texture2.prefab");
BuildPipeline.BuildAssetBundle(tex2, null, filePath + tex2.name + ".unity3d", buildOp, BuildTarget.StandaloneWindows);
BuildPipeline.PopAssetDependencies();
BuildPipeline.PopAssetDependencies();
EditorUtility.DisplayDialog("", "Build Completed", "OK");
AssetDatabase.Refresh();
}
AssetBundle依赖资源\共享资源加载
public string[] textureName;
public string picName;
// Use this for initialization
void Start () {
if (picName.Length > 0)
{
StartCoroutine(LoadAssetTexture(PlatflamPath() + picName + ".unity3d", picName));
}
for (int i = 0; i < textureName.Length; i++)
{
StartCoroutine(LoadAssetBundle(PlatflamPath() + textureName[i] + ".unity3d", textureName[i]));
}
}
static public IEnumerator LoadAssetBundle(string filepath,string assetName) {
WWW www = new WWW(filepath);
yield return www;
if (www == null) {
Debug.Log(" www is null ");
}
else if (www.error != null) {
Debug.Log("error " + www.error);
}
else if (www.isDone) {
AssetBundle assetBundle = www.assetBundle;
AssetBundleRequest requet = assetBundle.LoadAsync(assetName, typeof(GameObject));
yield return requet;
if (requet.isDone) {
GameObject obj = Instantiate(requet.asset) as GameObject;
}
}
www.Dispose();
www = null;
}
static public string PlatflamPath()
{
return string.Format("file://{0}", Application.streamingAssetsPath) + "/";
}
static public IEnumerator LoadAssetTexture(string filepath, string assetName)
{
WWW www = new WWW(filepath);
yield return www;
if (www == null)
{
Debug.Log(" www is null ");
}
else if (www.error != null)
{
Debug.Log("error " + www.error);
}
else if (www.isDone)
{
AssetBundle assetBundle = www.assetBundle;
}
www.Dispose();
www = null;
}
注意事项:
加载的时候需要加载图片,再加载跟它有关联的对象,笔者试过先加载后者,图片资源会丢失。另外,Push和Pos都是成对使用。
相比之下,后者打包的方式前者节省空间。具体使用情况还是视个人情况而定。
吐槽一下,第一次写博客,没想到写个博客都这么麻烦,写博客确实不是那么的简单。刚看了一下草稿,我了勒个去,排版简直不能看,还是默默的排版去。
参考博客 :AssetBundle系列——共享资源打包/依赖资源打包