zoukankan      html  css  js  c++  java
  • AssetBundle 点滴

    基本介绍:
    什么是? 一个assets的集合,打包以用来在运行时加载
    在应用中动态的 加载和卸载 新内容。 比如说DLC(downloadable content)

    用处?

    降低磁盘空间的消耗(第一次发布时) + 热更新资源

    AssetBundle 使用LZMA进行压缩,并且相似的Prefabs在打包时能够大大减少空间占用。


    创建AssetBundle,使用Editor代码,可以参考官方的manual:

     1 public class ExportAssetBundles
     2 {
     3     [MenuItem("Custom/Build AssetBundle From Selection - Track dependencies")]
     4     public static void ExportResource()
     5     {
     6         string path = EditorUtility.SaveFilePanel("Save Resource","","New Resource","unity3d");
     7         if(path.Length != 0)
     8         {
     9             Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
    10             BuildPipeline.BuildAssetBundle(Selection.activeObject,selection,path,
    11                 BuildAssetBundleOptions.CollectDependencies|BuildAssetBundleOptions.CompleteAssets);
    12             Selection.objects = selection;
    13         }
    14     }
    15 
    16     [MenuItem("Custom/Build AssetBundle From Selection - No dependency tracking")]
    17     public static void ExportResourceNoTrack()
    18     {
    19         string path = EditorUtility.SaveFilePanel("Save Resource", "", "New Resource", "unity3d");
    20         if(path.Length != 0)
    21         {
    22             
    23             //BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path);
    24             BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path);
    25         }
    26 
    27     }
    28 
    29 }

    下载:

     1 public class LoadAssetBundle : MonoBehaviour 
     2 {
     3     public Object obj;
     4 
     5     /// <summary>
     6     /// 
     7     /// </summary>
     8     /// <typeparam name="T"></typeparam>
     9     /// <param name="asset">bundle的名字</param>
    10     /// <param name="url"></param>
    11     /// <param name="version"></param>
    12     /// <returns></returns>
    13     public IEnumerator DownloadAssetBundle<T>(string asset,string url,int version) where T: Object
    14     {
    15         obj = null;
    16 #if UNITY_EDITOR
    17 
    18         //prefab = Resources.LoadAssetAtPath("Assets/Artwork/mymodel.fbx", typeof(GameObject));
    19         obj = Resources.LoadAssetAtPath("Assets/" + asset, typeof(T));
    20         yield return null;
    21 #else
    22         while (!Caching.ready)
    23             yield return null;
    24         using(WWW www = WWW.LoadFromCacheOrDownload(url,version))
    25         {
    26             if (www.error != null)
    27             {
    28                 Debug.LogError("WWW download has an error "+www.error );                
    29             }
    30             else
    31             {
    32                 AssetBundle bundle = www.assetBundle;
    33                 obj = bundle.Load(asset, typeof(T));
    34                 bundle.Unload(false);
    35             }
    36         }
    37 #endif
    38     }
    39 
    40     

    最好使用上述方式,但使用new WWW(url) 也是可以的。

    上述代码中:Resources.loadAsssetAtPath 避免了重新打包assetbundel,这个函数的用处是 使你想load一个assetbundle一样laod它,它会跳过打包的过程来保证asset始终是最新的(简化操作)

    .mainAsset 当制作assetbundle的时候的传递的第一个参数。
    用处: 存储一个 textAsset 用来表示所有这个assetbundle中的objects信息。

    使用注意:

    url 使用本地 之前加 file://

    从AssetBundle中加载出来的prefab上的脚本是会执行的,只要本地有这个脚本,不然会出现警告:“The referenced script on this Behaviour is missing!” ,脚本不会执行。

    如果想要动态的加载脚本,只能通过编译成dll,然后改为.bytes,再反射加载,再add component。这也是官方推荐的Android下热更新脚本的一种方式。


    LodaAll 的问题:

    首先,对于所有的load,必须要指定type,不然可能由于重名而出现莫名其妙的错误。具体原因可以参见这篇文章的相关介绍:http://www.cnblogs.com/ybgame/p/3973177.html?utm_source=tuicool
    常见错误:
    Object[] objects = bundle.LoadAll();///
    Foreach(Object obj in Objects)
    {
      Instantiate(obj);
    }
    注意: 每个prefab 会出来 4个clone;

    如果是用 Object[] objects = bundle.LoadAll(Typeof(GameObject));
    则: 出来2个clone;
    原因:prefab 中包含了 model 的meshfilter。即prefab是包含model的。
    解决方法:不是将prefab打包,而是仅仅将model打包。这样就只有一个。

    但是如果需要的不仅仅是模型,还要通过加入其他组件,那么就只能采用 名字 来做了

    bundle.Load(“name”,typepf(Gameobject));
    再instantiate 则是一个。
    //使用名字能够保证始终是一个。

    考虑第一个AssetBundle的第一个 也就是 mainAsset 保存名字。然后再一一实例化。

    另一种:

    也可以将这一步放在加载的时候,先加载TextAsset,然后获得名字。
    AssetBundle bundle = www.assetBundle;
    //textAsset 名称为Names
    TextAsset file = bundle.Load("Names", typeof(TextAsset)) as TextAsset;
    string content = file.text;
    string[] names = content.Split(',');
    foreach( string name in names)
    {
    Instantiate(bundle.Load(name, typeof(GameObject)));
    }

    关于打包的思路:

    尽量把具有相同模型不同脚本的物体做成不同的prefab,然后打包在一起,可以较少空间占用。最后可以直接加载使用。
    将大部分 在scene中出现的    存成  prefab。

    然后 有些 prefab 只是脚本或者位置 或者其他不一样 ,那么这些放在一起打包 ,大大减小包的大小。

    完全不关联的东西放  分开 打包。

    基础UI可以打成一个包,重复使用

    另外基础的场景背景 或者 公用背景 可以打在一起 ,每个场景不同的可以分开。

    场景加载中使用Assetbundle的一些思路:

    每次加载对应的场景的时候,需要场景对应的
    AssetBundle url,每个 AssetBundle 中要加载哪些东西,这会对应着一个文件。然后去构建场景。
    类似于MOMO的将场景保存为XML或者Json 文件。http://www.xuanyusong.com/archives/1919

    大部分的场景都是基于同一个场景衍生的,所以可以做一个base场景,然后修改后save as

    有效率的打包AssetBundle。
    随着项目的增大,手动打包很繁杂,所以考虑程序去将项目中的所有需要打包的全部打包。
    比如说 可以有一个 txt文件来map Asset –>Assetbundle。

    由于WWW.LoadfromCacheOrDownload
    是一个异步的过程,
    解决方案:
    1: 先优先加载 主角 或者 需要优先显示的部分,
    再加载其他部分
    2: 使用同步加载,AssetBundle.CreatFromFile
    要求打包的时候不压缩,所以自己使用LZMA压缩,解压。
    AssetBundle下载下来 并且 保存在 本地路径(比如说application.persistantDataPath),再使用AssetBundle.CreatFromFile 。

    一个场景的完整的加载过程可能如下:
    场景构成:
    一个start脚本;
    1:读取配置文件
    2:加载公有的assetbundle
    3:加载私有的assetbundle

    具体还要看不同的情况。需要调节加载的顺序,因为会有相互的依赖性,不然可能会出现错误。

    配置文件的示例:
    Scene1.bytes:
    公用bundle 路径(可以是相对的),公用bundle 路径(可以是相对的)| 私有bundle路径,私有bundle路径
    分割符 ‘|’ ‘,’
    比如: 公用
    Application.persistantDatapath + “/publicBundles”+”/road.assetbunlde”;

    采用自己定义的格式就可以。

    另外,有一个文件记录所有的assetbundle的当前版本,用来供读取。

  • 相关阅读:
    C# 文件操作(读取文本/日志文件,读取文件列表,创建HTML,写入日志文件)
    网页布局与优化
    深度复制与浅度复制
    Silver 操作Cookie
    HTTP Method小结
    C# 主动发起请求代码
    震动放声音
    细数Objective-C中的回调机制
    iOS7隐藏状态栏 status Bar
    本地化UIImagePicker中的文字
  • 原文地址:https://www.cnblogs.com/binpan/p/4330789.html
Copyright © 2011-2022 走看看