AssetBundle系列——共享资源打包/依赖资源打包

AssetBundle普及:http://www.xuanyusong.com/archives/2405

http://www.xuanyusong.com/archives/2373

http://liweizhaolili.blog.163.com/blog/static/162307442015282017852/

AssetBundle系列——共享资源打包/依赖资源打包

 

  有人在之前的博客中问我有关共享资源打包的代码,其实这一块很简单,就两个函数:

  BuildPipeline.PushAssetDependencies():依赖资源压栈;

  BuildPipeline.PopAssetDependencies():依赖资源出栈。

  直接看代码,下面为打包示例代码,Prefab1和Prefab2共享贴图资源Tex1,在打包时将Tex1单独打包,而Prefab1和Prefab2对应的assetbundle包中不实际包含Tex1资源,而是记录Tex1资源的引用:

复制代码
using UnityEditor;
using UnityEngine;
using System.IO;
using System.Collections;
using System.Collections.Generic;

public class PushAndPop 
{
    [MenuItem("Test/BuildAssetBundle")]
    static void Execute()
    {
        string SavePath = "C:\\";

        BuildAssetBundleOptions buildOp = BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets 
            | BuildAssetBundleOptions.DeterministicAssetBundle;

        BuildPipeline.PushAssetDependencies();
        // 共享资源Tex1.tga
        Object sharedAsset = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Test/Tex1.tga");
        BuildPipeline.BuildAssetBundle(sharedAsset, null, SavePath + sharedAsset.name + ".assetbundle", buildOp, BuildTarget.StandaloneWindows);

        // Prefab1,引用了Tex1.tga
        BuildPipeline.PushAssetDependencies();
        Object p1Asset = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Test/P1.prefab");
        BuildPipeline.BuildAssetBundle(p1Asset, null, SavePath + p1Asset.name + ".assetbundle", buildOp, BuildTarget.StandaloneWindows);
        BuildPipeline.PopAssetDependencies();

        // Prefab2,引用了Tex1.tga
        BuildPipeline.PushAssetDependencies();
        Object p2Asset = AssetDatabase.LoadMainAssetAtPath("Assets/Resources/Test/P2.prefab");
        BuildPipeline.BuildAssetBundle(p2Asset, null, SavePath + p2Asset.name + ".assetbundle", buildOp, BuildTarget.StandaloneWindows);
        BuildPipeline.PopAssetDependencies();

        BuildPipeline.PopAssetDependencies();

        EditorUtility.DisplayDialog("", "Completed", "OK");
        AssetDatabase.Refresh();
    }

}
复制代码

  可以看到,Push和Pos都是成对使用,一个Push/Pop对就相当于一个Layer(层),层可以嵌套,内层可以依赖外层的资源。也就是说内层某资源在打包时,如果其引用的某个资源已经在外层加载了,那么内层的这个资源包就会包含该资源的引用而不是资源本身。Push/Pop实际上维持了一个依赖的堆栈。

  那么,在加载依赖资源包时,需要注意的是:先加载依赖的资源,然后加载其他资源,需要确保这个顺序。下面的代码演示如何使用依赖资源包:

复制代码
using UnityEngine;
using System.Collections;

public class NewBehaviourScript : MonoBehaviour 
{
    void OnGUI()
    {
        // 清空本地缓存
        if (GUI.Button(new Rect(0f, 0f, 100f, 20f), Caching.spaceOccupied.ToString()))
        {
            Caching.CleanCache();
        }

        if (GUI.Button(new Rect(0f, 30f, 100f, 20f), "Load Share Res"))
        {
            StartCoroutine(Load(@"file://C:\Tex1.assetbundle", 1));
        }

        if (GUI.Button(new Rect(0f, 60f, 100f, 20f), "Load And Instantiate Prefab"))
        {
            StartCoroutine(LoadAndInstantiate(@"file://C:\P1.assetbundle", 1));
            StartCoroutine(LoadAndInstantiate(@"file://C:\P2.assetbundle", 1));
        }
    }

    // 加载
    IEnumerator Load(string url, int version)
    {
        WWW www = WWW.LoadFromCacheOrDownload(url, version);
        yield return www;
    }

    // 加载并实例化
    IEnumerator LoadAndInstantiate(string url, int version)
    {
        WWW www = WWW.LoadFromCacheOrDownload(url, version);
        yield return www;

        if (!System.String.IsNullOrEmpty(www.error))
        {
            Debug.Log(www.error);
        }
        else
        {
            Object main = www.assetBundle.mainAsset;
            GameObject.Instantiate(main);
        }
    }

}
复制代码

  先按第二个按钮,然后再按第三个按钮就能够正确显示两个Prefab,如果直接进行第三步操作,则实例化出来的Prefab会缺少贴图。

  另外我们可以从assetbundle包的大小来看一下:

  如果不打依赖包,两个prefab都打完整包,得到的包的大小为:

  P1.assetbundle      56K

  P2.assetbundle      38K

  如果打依赖包,得到的包的大小为:

  Tex1.assetbundle      10k

  P1.assetbundle      47K

  P2.assetbundle      29K

  规律是不是很明显。



2.读取Assetbundle 

unity5已经封装好了接口,所以依赖打包并没有那么神秘和复杂了


打包:
1.定义好资源的assetBundleName
2.BuildPipeline.BuildAssetBundles,指定资源目录和压缩类型

生成:
1.Assetbundle文件,加载时的首要文件,包含所有资源的依赖信息
2.每个文件对应一个.manifest,不用管他,但是可以打开查看他引用了哪些资源。

加载:
1.获取AssetBundle文件
2.LoadAsset("AssetBundleManifest")转换为AssetBundleManifest
3.通过manifest.GetAllDependencies("测试文件"),获取它依赖的ab,得到的是AB数组,并下载它
4.最后下载名为(测试文件)的资源即可。

测试代码:
  1. using UnityEngine;  
  2. using System.Collections;  
  3.   
  4. public class LoadAssetbundle MonoBehaviour  
  5.       
  6.     void Start()  
  7.      
  8.         // 1.加载Manifest文件  
  9.         AssetBundle manifestBundle=AssetBundle.CreateFromFile(Application.dataPath +"/ab/Assetbundle");  
  10.         if(manifestBundle != null 
  11.          
  12.             AssetBundleManifest manifest (AssetBundleManifest)manifestBundle.LoadAsset("AssetBundleManifest");  
  13.             // 2.获取依赖文件列表  
  14.             string[] cubedepends manifest.GetAllDependencies("assets/res/1.prefab");  
  15.             AssetBundle[] dependsAssetbundle new AssetBundle[cubedepends.Length];  
  16.             for(int index 0index cubedepends.Length; index++)  
  17.              
  18.                 // 3.加载所有的依赖资源  
  19.                 dependsAssetbundle[index]=AssetBundle.CreateFromFile(  
  20.                     Application.dataPath +"/../Assetbundle/"+cubedepends[index]);  
  21.              
  22.   
  23.             // 4.加载资源  
  24.             AssetBundle cubeBundle=AssetBundle.CreateFromFile(  
  25.                 Application.dataPath +"/ab/assets/res/1.prefab" );  
  26.             GameObject cube=cubeBundle.LoadAsset("1"as GameObject;  
  27.             if(cube!=null 
  28.              
  29.                 Instantiate(cube);  
  30.              
  31.          
  32.      

坑tips:
如果材质球的名称和它引用的贴图名称一样,材质球内存占有量就会像包含了贴图的内存一样。

换版本tips:
4.6项目移植到5.0.2,ab包无法加载,重新打包即可。
不改打包代码,多数文件大小增大2k
改为最新打包代码,不做依赖,多数文件大小增大2-4%左右

tips:
如果做依赖,会生成很多零碎的文件,开发期不建议使用,以免增加不必要的工作量。和美术定义好资源规范才是重点。(个人意见,不喜随你便Unity学习(六)5.x依赖打包)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值