一、创建Assetbundle
在unity3d开发的游戏中,无论模型,音频,还是图片等,我们都做成Prefab,然后打包成Assetbundle,方便我们后面的使用,来达到资源的更新。
一个Assetbundle可以打包一个模型(这里的模型不单单指的是预制模型,可以是Project视图下的任何东西),也可以是多个模型,但两种打包方式占用的空间不一样。
比如我打包三个一样的模型(只不过他们的脚本不一样创建三个空的GameObject(One,Two,Three),分别挂载脚本One,Two,Three)。如果我为每个模型单独打包生成One,Two,Three三个Assetbundle,其所占的空间是A,B,C,但是A+B+C != D.由此可知想通的资源尽可能的打包到一起,他们共用一套资源。不相同的模型尽量分开打包。
二、分开打包(注意这个脚本必须放在Editor文件夹内,Editor文件夹没有的话需自己创建)
///
/// 将选中的预制分别打包
///
[MenuItem("AssetBundleDemo/Create AssetBundles By themselves")]
static void CreateAssetBundleThemelves(){
//获取要打包的对象(在Project视图中)
Object[] selects = Selection.GetFiltered (typeof(Object),SelectionMode.DeepAssets);
//遍历选中的对象
foreach(Object obj in selects){
//这里建立一个本地测试
//注意本地测试中可以是任意的文件,但是到了移动平台只能读取路径StreamingAssets里面的
//StreamingAssets是只读路径,不能写入
string targetPath = Application.dataPath + "/AssetBundleLearn/StreamingAssets/" + obj.name + ".assetbundle";//文件的后缀名是assetbundle和unity都可以
if(BuildPipeline.BuildAssetBundle(obj,null,targetPath,BuildAssetBundleOptions.CollectDependencies)){
Debug.Log(obj.name + "is packed successfully!");
}else{
Debug.Log(obj.name + "is packed failly!");
}
}
//刷新编辑器(不写的话要手动刷新,否则打包的资源不能及时在Project视图内显示)
AssetDatabase.Refresh ();
}
SelectionMode.DeepAssets
这个选择模式意味着如果选择中包含多个文件,那么他将包含这个文件视图中的所有资源。
他还有其他的各种选项(以下是官方文档)
SelectionMode can be used to tweak the selection returned by Selection.GetTransforms.
The default transform selection mode is: SelectionMode.TopLevel | SelectionMode.ExcludePrefab | SelectionMode.Editable.
Unfiltered | Return the whole selection. |
TopLevel | Only return the topmost selected transform. A selected child of another selected transform will be filtered out. |
Deep | Return the selection and all child transforms of the selection. |
ExcludePrefab | Excludes any prefabs from the selection. |
Editable | Excludes any objects which shall not be modified. |
Assets | Only return objects that are assets in the Asset directory. |
DeepAssets | If the selection contains folders, also include all assets and subfolders within that folder in the file hierarchy. |
最核心的方法:BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies)
参数1:它只能放一个对象,因为我们这里是分别打包,所以通过循环将每个对象分别放在了这里。
参数2:可以放入一个数组对象。
参数3:要打包到的路径
参数4:默认情况下打的包只能在电脑上用,如果要在手机上用就要添加一个参数。
Android上:
BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.Android)
IOS上:
BuildPipeline.BuildAssetBundle (obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies,BuildTarget.iPhone)
另外,电脑上和手机上打出来的Assetbundle不能混用,不同平台只能用自己的。
三、一起打包 ///
/// 将选中的预制打包到一起
///
[MenuItem("AssetBundleDemo/Create AssetBundles Together")]
static void CreateAssetBundleTogether(){
//要打包的对象
Object[] selects = Selection.GetFiltered (typeof(Object),SelectionMode.DeepAssets);
//要打包到的路径
string targetPath = Application.dataPath + "/AssetBundleLearn/StreamingAssets/Together.assetbundle";
if(BuildPipeline.BuildAssetBundle(null,selects,targetPath,BuildAssetBundleOptions.CollectDependencies)){
Debug.Log("Packed successfully!");
}else{
Debug.Log("Packed failly!");
}
//刷新编辑器(不写的话要手动刷新)
AssetDatabase.Refresh ();
}
}
四、读取
using UnityEngine;
using System.Collections;
public class ReanAssetbundle : MonoBehaviour {
//不同平台下StreamingAssets的路径是不同的,这里需要注意一下。
public static readonly string m_PathURL =
#if UNITY_ANDROID
"jar:file://" + Application.dataPath + "!/assets/";
#elif UNITY_IPHONE
Application.dataPath + "/Raw/";
#elif UNITY_STANDALONE_WIN || UNITY_EDITOR
"file://" + Application.dataPath + "/AssetBundleLearn/StreamingAssets/";
#else
string.Empty;
#endif
void OnGUI(){
if(GUILayout.Button("加载分开打包的Assetbundle")){
StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "One.assetbundle"));
StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "Two.assetbundle"));
StartCoroutine(LoadGameObjectPackedByThemselves(m_PathURL + "Three.assetbundle"));
}
if(GUILayout.Button("加载打包在一起的Assetbundle")){
StartCoroutine(LoadGameObjectPackedTogether(m_PathURL + "Together.assetbundle"));
}
}
//单独读取资源
private IEnumerator LoadGameObjectPackedByThemselves(string path){
WWW bundle = new WWW (path);
yield return bundle;
//加载
yield return Instantiate (bundle.assetBundle.mainAsset);
bundle.assetBundle.Unload (false);
}
IEnumerator LoadGameObjectPackedTogether (string path)
{
WWW bundle = new WWW (path);
yield return bundle;
Object one = bundle.assetBundle.Load ("One");
Object two = bundle.assetBundle.Load ("Two");
Object three = bundle.assetBundle.Load ("Three");
//加载
yield return Instantiate (one);
yield return Instantiate (two);
yield return Instantiate (three);
bundle.assetBundle.Unload (false);
}
}