- 最后登录
- 2021-7-6
- 注册时间
- 2012-12-27
- 阅读权限
- 90
- 积分
- 76145
 
- 纳金币
- 53488
- 精华
- 316
|
首先,发下参考链接,阿赵的博客,写得很好:
再详细的介绍一下Unity5的AssetBundle 以及 Unity5的AssetBundle的一点使用心得
阿赵文中写过:
“先来说说最多人关心的[color=rgb(85, 85, 85) !important]问题,Unity自己处理依赖关系。
实际上来说,所有需要打包成AssetBundle的资源,你是要先赋予它一个assetBundleName的,在它有了assetBundleName之后,实际上它的信息已经存在于AssetDataBase里面了。所以在打包的时候,只需要调用BuildPipeline.BuildAssetBundles方法,它会把记录了的在AssetDataBase里面的所有资源先计算出依赖关系,再拆分打包。这个步骤是一点问题都没有的。要注意的是,你所有依赖的资源都必须赋予assetBundleName,不然,依赖就不会被拆分。”
我很好奇,使用[color=rgb(85, 85, 85) !important]unity5,这样打包出来的AssetBundle究竟是什么样。于是参照他的方式,做了下实验。
仍然是4张贴图,名字分别是T1,T2,T3,T4。2个材质球,M1,使用贴图T1,T2,T3。材质球M2,使用贴图T4。2个Cube物体,obj1和obj2,分别使用材质M1和M2.将obj1和obj2做成prefab。
打包的代码很简单:- using UnityEngine;
- using UnityEditor;
- public class BuildAssetBundle : MonoBehaviour {
- // Use this for initialization
- void Start () {
-
- }
-
- // Update is called once per frame
- void Update () {
-
- }
- [MenuItem("AssetBundle/BuildAssetBundle")]
- public static void CreateAssetBundle()
- {
- BuildPipeline.BuildAssetBundles("Assets/Output", BuildAssetBundleOptions.None, BuildTarget.StandaloneWindows);
- }
- }
复制代码 1.只打包prefab
点击obj1,new一个AssetBundle name为“obj1”,同样为obj2 new 一个AssetBundle name为“obj2”,分别设置好。使用上面代码生成的菜单,导出AssetBundle。这样打包一共3个AssetBundle文件,分别是obj1,obj2,还有一个跟导出路径同名的output。其余的manifest文件是本地使用,暂时不关注。
使用如下加载代码测试:- using UnityEngine;
- using System.Collections;
- public class ImportAssetBundle : MonoBehaviour {
- // Use this for initialization
- void Start () {
- AssetBundle ab1 = AssetBundle.LoadFromFile("Assets/AssetBundle/obj1");
- if(ab1 != null)
- {
- Debug.Log("ab1 create success!");
- Instantiate(ab1.LoadAsset("oBj1"));
- //Object M1 = ab1.LoadAsset("M1");
- //Debug.Log(M1.name);
- string[] names = ab1.GetAllAssetNames();
- foreach (var elem in names)
- Debug.Log("Asset name is " + elem);
- Object[] objs = ab1.LoadAllAssets();
- foreach (var elem in objs)
- Debug.Log("Obj is " + elem.name);
- Object[] objsWithSub = ab1.LoadAssetWithSubAssets("Obj1");
- foreach (var elem in objsWithSub)
- Debug.Log("Obj with sub assets is " + elem.name);
- }
- AssetBundle ab1Manifest = AssetBundle.LoadFromFile("Assets/AssetBundle/Output");
- if (ab1Manifest != null)
- {
- Debug.Log("ab1Manifest create success!");
- string[] names = ab1Manifest.GetAllAssetNames();
- foreach (var elem in names)
- Debug.Log("asset name is " + elem);
- AssetBundleManifest manifest = ab1Manifest.LoadAsset("AssetBundleManifest") as AssetBundleManifest;
- if(manifest != null)
- {
- Debug.Log("load manifest success");
- string[] AllAB = manifest.GetAllAssetBundles();
- foreach (var elem in AllAB)
- Debug.Log("AssetBundle is " + elem);
- string[] AllDependences = manifest.GetAllDependencies("obj1");
- foreach (var elem in AllDependences)
- Debug.Log("Dependences is " + elem);
- }
- }
- }
-
- // Update is called once per frame
- void Update () {
-
- }
- }
复制代码 大家自行运行结果记忆会更深刻。
分析结果发现, ab1.GetAllAssetNames(),ab1.LoadAllAssets() 能取出来的都只有obj1,而我实例化的obj1立方体可是带有材质和贴图的。放开注释的代码
//Object M1 = ab1.LoadAsset("M1"); //Debug.Log(M1.name);
运行会报错,说是空引用。明明有贴图,材质,可我们就是没法从AssetBundle取出来,只可能是unity自己将我们没有显式设置AssetBundle的资源密封起来了,不让我们去获取。
之后的代码
string[] names = ab1Manifest.GetAllAssetNames(); 在实验中得到的只有一个文件,就是assetbundlemanifest,不区分大小写。这个文件包含了所有的依赖关系。
再看obj1的依赖项
string[] AllDependences = manifest.GetAllDependencies("obj1"); 结果是空的,没有任何依赖项。可是obj1明明依赖了材质M1,还有贴图啊。
猜测,是因为M1等资源没有打包的原因,我们验证一下。
2.将材质,贴图与prefab共同打包到一个AssetBundle下
将M1,T1,T2,T3的AssetBundle设置成obj1,再次打包,最后生成的文件个数没有变化。然而我们运行代码会发现结果出现了部分变化,首先就是M1能够load出来了,验证了只有显示设置AssetBundle name的资源才可以被我们load使用。
最后的依赖资源,manifest.GetAllDependencies("obj1")获取的还是空,看看GetAllDependencies函数定义,获取的是依赖的AssetBundle的名字。obj1依赖的所有东西都在自身所在的AssetBundle里,自然获取不到值。再一次反省,看SDK的注释含义。。。
3.将材质,贴图,prefab分开打包
将M1的AssetBundle设置为M1,重新打包。生成的文件中多了M1的AssetBundle文件。
继续使用加载代码,前面大部分相同,当然这次你不能从obj1的AssetBunble中去load试图获取 M1了。最关键的部分在最后,这次我们可以使用GetAllDependencies获取到obj1的依赖文件M1了。
结语
只打包prefab,省事,但可能造成资源的重复打包,无法复用。如果是唯一性的东西,只有某个物体使用,可以偷懒这么做。但如果想复用东西,老老实实多拆点小的包出来。当然,灵活性最高的就是用4.0那种自己控制的方式。具体的做法根据需求来取舍吧。
|
|