• (转)【风宇冲】Unity3D教程宝典之AssetBundles:第一讲


    自:http://blog.sina.com.cn/s/blog_471132920101gz8z.html

    原创文章如需转载请注明:转载自风宇冲Unity3D教程学院

           
                                         AssetBundles第一讲:基本使用

    AssetBundles是从unity导出你选择的assets,它使用特有的压缩格式并且应用可以实时去读取它。包括模型贴图音频等任何asset类型,甚至整个场景。压缩大小基本能达到zip的效果。AssetBundles从设计时就定位为可以很简单就下载到应用里。如果你想包括自定义的binary数据,就要用.bytes后缀,Unity将作为TextAssets导入他们。
     
    注意:
    AssetBundles并不像Unity官方说的那样,各种unity版本兼容。经测试在unity4中创建的ab,在4中正常使用,但在3.5.0里无法正常使用。说明用AB不能向下兼容。

    开发阶段:
    (1)创建AssetBundles:
    不能是scene objects的objects使用BuildPipeline.BuildAssetBundle 
    targetplatform要指定,不能用默认参数,默认模式是webplayer
     
    1. using UnityEngine;
    2. using UnityEditor;
    3. public class ExportAssetBundles {
    4.     [MenuItem("Assets/Build AssetBundle From Selection - Track dependencies")]
    5.     static void ExportResource () {
    6.         // Bring up save panel
    7.         string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource","unity3d");
    8.         if (path.Length != 0) {
    9.             // Build the resource file from the active selection.
    10.             Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
    11.             BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, 
    12. path, BuildAssetBundleOptions.CollectDependencies |BuildAssetBundleOptions.CompleteAssets
    13. ,BuildTarget.StandaloneWindows);
    14.             Selection.objects = selection;
    15.         }
    16.     }
    17.     [MenuItem("Assets/Build AssetBundle From Selection - No dependency tracking")]
    18.     static void ExportResourceNoTrack () {
    19.         // Bring up save panel
    20.         string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource","unity3d");
    21.         if (path.Length != 0) {
    22.             // Build the resource file from the active selection.
    23.             BuildPipeline.BuildAssetBundle(Selection.activeObject, Selection.objects, path);
    24.         }
    25.     }
    26. }
    bool BuildPipeline.BuildAssetBundleExplicitAssetNames(Object[] assets, string[] assetName, string pathName, BuildAssetBundleOptions assetBundleOptions, Buildtarget targetPlatform)
    创建bundle并自定义名称。assetName的长度及排列与assets对应。并不是真正改变物体的名称,只是在assetBundle.Load的时候有个唯一对应的名称
     

    对上面代码仅需修改第11行。将BuildPipeline.BuildAssetBundle(Selection.activeObject, selection, 

    path, BuildAssetBundleOptions.CollectDependencies | BuildAssetBundleOptions.CompleteAssets

    ,BuildTarget.StandaloneWindows); 里的第一个参数mainAsset去掉,并在selection也就是Object[]之后加string[] assetName即可

     
    1. [MenuItem("Assets/Build AssetBundle From Selection Names- Track dependencies")]
    2.     static void ExportResourceWithNames () {
    3.         // Bring up save panel
    4.         string path = EditorUtility.SaveFilePanel ("Save Resource", "", "New Resource","unity3d");
    5.         if (path.Length != 0) {
    6.             // Build the resource file from the active selection.
    7.             Object[] selection = Selection.GetFiltered(typeof(Object), SelectionMode.DeepAssets);
    8. string[] names = new string[selection.Length];
    9. for(int i =0;i
    10. {
    11. names[i] = i+"_"+ selection[i].name;
    12. }
    13.             BuildPipeline.BuildAssetBundleExplicitAssetNames( selection,names, 
    14. path, BuildAssetBundleOptions.CollectDependencies |BuildAssetBundleOptions.CompleteAssets
    15. ,BuildTarget.StandaloneWindows);
    16.             Selection.objects = selection;
    17.         }
    18.     }
     
     
     
     
    1. using System;
    2. using System.IO;
    3. using UnityEngine;
    4. public class LoadAssetBundle : MonoBehaviour {
    5. private AssetBundle assetBundle;
    6. private AssetBundleCreateRequest request;
    7. void Update () {
    8. }
    9. void OnGUI()
    10. {
    11. if(GUI.Button(new Rect(0,0,100,50),"Load"))
    12. {
    13. byte[] bs = File.ReadAllBytes(Application.dataPath+ "/withNames.unity3d");
    14. request = AssetBundle.CreateFromMemory(bs);
    15. }
    16. if(GUI.Button(new Rect(0,50,100,50),"Check"))
    17. {
    18. if(request.isDone == true)
    19. {
    20. assetBundle = request.assetBundle;
    21. UnityEngine.Object obj = assetBundle.Load("0_Cube");
    22. Instantiate(obj);
    23. }
    24. }
    25. }
    将场景做成AB时,BuildPipeline.BuildStreamedSceneAssetBundle
    将一个或者多个场景打包到asset bundle里,可以为任何平台,并总创建单一的压缩.unity3d文件。
    在下载后,可以用WWW.LoadFromCacheOrDownload从缓存里读取。 
    1. using UnityEngine;
    2. using UnityEditor;
    3. public class BuildScene : MonoBehaviour {
    4. [MenuItem ("Build/BuildWebplayerStreamed")]
    5. static void BuildScenes()
    6. {
    7. string [] levels = new string[1];
    8. levels[0] = "Assets/scene.unity";
    9. BuildPipeline.BuildStreamedSceneAssetBundle(levels, "Assets/myLevel.unity3d",BuildTarget.StandaloneOSXIntel);
    10. }
    11. }


    兼容性
    Platform compatibility for AssetBundles
      Standalone Webplayer iOS Android
    Editor Y Y Y Y
    Standalone Y Y    
    Webplayer Y Y    
    iOS     Y  
    Android       Y

    (2)上传AssetBundles: 基于你所使用的服务器决定如何上传。

    使用阶段:
    (1)下载AssetBundles:
    1 AssetBundle.CreateFromFile: 
       (1)只能用于pc和mac standalone
       (2)只支持Uncompressed:也就是在build的时候buildoption还要加上UncompressedAssetBundle 。
       (3)必须得是绝对路径。
           AssetBundle assetBundle = AssetBundle.CreateFromFile("D:/myBundle4.unity3d");

    2 AssetBundle.CreateFromMemory(bs);

    1. using System;
    2. using System.IO;
    3. using UnityEngine;
    4. public class LoadAssetBundle : MonoBehaviour {
    5.     private AssetBundle assetBundle;
    6.     private AssetBundleCreateRequest request;
    7.     void Update () {
    8.         if(request!=null)
    9.             print(request.progress);
    10.     }
    11.    
    12.     void OnGUI()
    13.     {
    14.         if(GUI.Button(new Rect(0,0,100,50),"Load"))
    15.         {
    16.             byte[] bs = File.ReadAllBytes("D:/myBundle.unity3d");
    17.             request = AssetBundle.CreateFromMemory(bs);
    18.         }
    19.        
    20.        
    21.         if(GUI.Button(new Rect(0,50,100,50),"Check"))
    22.         {
    23.             if(request.isDone == true)
    24.             {
    25.                 print("name: "+request.assetBundle.mainAsset.name);
    26.                 Instantiate(request.assetBundle.mainAsset);
    27.             }
    28.         }
    29.     }
    30. }

    3 AssetBundle bundle = www.assetBundle;
    注:WWW也是可以读取本地文件的,
    只需要在路径前file://即可,如
    WWW myWWW = new WWW("file://E://LSY/wamp/www/cat.jpg");
    1. using System;
    2. using System.IO;
    3. using UnityEngine;
    4. using System.Collections;
    5. public class LoadAssetBundle : MonoBehaviour {
    6.     private AssetBundle assetBundle;
    7.     private string address = "http://127.0.0.1/AssetBundles/myBundle.unity3d";
    8.    
    9.     void OnGUI()
    10.     {
    11.         if(GUI.Button(new Rect(0,0,100,50),"Load web"))
    12.         {
    13.             StartCoroutine(Load());
    14.         }
    15.     }
    16.    
    17.     IEnumerator Load() {
    18.        // Download the file from the URL. It will not be saved in the Cache
    19.        string    AssetName="";
    20.        WWW www = new WWW(address);
    21.        yield return www;
    22.        if (www.error != null)
    23.            throw new Exception("WWW download had an error:" + www.error);
    24.        AssetBundle bundle = www.assetBundle;
    25.        if (AssetName == "")
    26.            Instantiate(bundle.mainAsset);
    27.        else
    28.            Instantiate(bundle.Load(AssetName));
    29.                // Unload the AssetBundles compressed contents to conserve memory
    30.                bundle.Unload(false);
    31.    }
    32. }
    WWW.LoadFromCacheOrDownload
    下载过程中可以更换下载地址,并保证版本一致, Webplayer的cache限制在50MB以内。
    与普通的www下载仅仅是一句代码的区别
    WWW www = new WWW(address);
    WWW www = WWW.LoadFromCacheOrDownload(address,1);
    1. using System;
    2. using System.IO;
    3. using UnityEngine;
    4. using System.Collections;
    5. public class LoadAssetBundle : MonoBehaviour {
    6.     private AssetBundle assetBundle;
    7.     private string address = "http://127.0.0.1/AssetBundles/myBundle.unity3d";
    8.    
    9.     void OnGUI()
    10.     {
    11.         if(GUI.Button(new Rect(0,0,100,50),"Load web"))
    12.         {
    13.             StartCoroutine(Load());
    14.         }
    15.     }
    16.    
    17.     IEnumerator Load() {
    18.        string    AssetName="";
    19.        WWW www = WWW.LoadFromCacheOrDownload(address,1);
    20.        yield return www;
    21.        if (www.error != null)
    22.            throw new Exception("WWW download had an error:" + www.error);
    23.        AssetBundle bundle = www.assetBundle;
    24.        if (AssetName == "")
    25.            Instantiate(bundle.mainAsset);
    26.        else
    27.            Instantiate(bundle.Load(AssetName));
    28.                // Unload the AssetBundles compressed contents to conserve memory
    29.                bundle.Unload(false);
    30.    }
    31. }

    (2)使用AssetBundles里的资源:
    bool AssetBundle.Contains(string name) bundle中是否含有名为name的asset

    Object AssetBundle.Load(string name) 读取bundle中名称为name的asset

    Object AssetBundle.LoadAll()
    UnityEngine.Object[] objs = assetBundle.LoadAll();
    在本例中assetBundle.mainAsset是GameObject,但是并不代表assetBundle.LoadAll();的返回值数组的第一个数据是GameObject即obj[0]等于assetBundle.mainAsset
    【风宇冲】Unity3D教程宝典之AssetBundles:第一讲

    assetBundle.mainAsset

    AssetBundle.Unload(bool unloadAllLoadedObjects)
    清空bundle里的所有资源。释放相关内存。清空后不能再通过该bundle创建物体。
    unloadAllLoadedObjects为false: AssetBundle里的数据将会被释放,不影响已经scene中已经创建的相关物体。
    unloadAllLoadedObjects为true: 不仅AssetBundle里的数据将会被释放,从该bundle创建的贴图材质等等asset将会被清空。如果scene中已经物体使用这些,连接将丢失。


    【风宇冲】Unity3D教程宝典之AssetBundles:第一讲

    【风宇冲】Unity3D教程宝典之AssetBundles:第一讲

     
    读取场景:
    当AssetBundle下载好后,直接Application.LoadLevel("scene");即可
     
    1. //******************************************************
    2. //AssetBundle.CreateFromMemory -> LoadLevel
    3. //******************************************************
    4. using System;
    5. using System.IO;
    6. using UnityEngine;
    7. public class LoadAssetBundle : MonoBehaviour {
    8. private AssetBundle assetBundle;
    9. private AssetBundleCreateRequest request;
    10. void Update () {
    11. }
    12. void OnGUI()
    13. {
    14. if(GUI.Button(new Rect(0,0,100,50),"Load"))
    15. {
    16. byte[] bs = File.ReadAllBytes(Application.dataPath+ "/myLevel.unity3d");
    17. request = AssetBundle.CreateFromMemory(bs);
    18. }
    19. if(GUI.Button(new Rect(0,50,100,50),"Check"))
    20. {
    21. if(request.isDone == true)
    22. {
    23. Application.LoadLevel("scene");
    24. }
    25. }
    26. }
    27. }
     
    总结:
    制作AssetBundle主要有
    BuildPipeline.BuildAssetBundle 非场景
    2 BuildPipeline.BuildStreamedSceneAssetBundle  场景
     
    使用AssetBundle主要有
    1 AssetBundle.CreateFromFile   只能是Uncompressed格式
    2 AssetBundle.CreateFromMemory    需要处理request
    3 AssetBundle bundle = www.assetBundle;  www又分为2种
      (1)WWW www = new WWW(address);
      (2)WWW www = WWW.LoadFromCacheOrDownload(address,1,crc);
              其中网游用的最多的是LoadFromCacheOrDownload,因为第一次下载后就存在本地缓存了,之后就直接从本地缓存读取.crc是用来做数据校验的。
     

    其中推荐 LoadFromCacheOrDownload。不推荐CreateFromMemory,因为需要一个解析建AB结构的过程,比较耗时。CreateFromFile也不是很推荐,因为只支持非压缩格式,所以占容量比较多。

    预制体打包成AssetBundle时:预制体可以搭脚本,并且指定关系等都可以照常使用。

    要求:

    (1)但是脚本必须是工程里有的

    (2)AssetBundle里预制体上搭载的脚本必须和工程里的脚本一致。

    否则会提示错误。

  • 相关阅读:
    HDU2066一个人的旅行(dijkstra)
    HDU2544最短路(dijkstra)
    iOS 入门 界面UI 界面跳转
    Lua 函数作为参数传递时的注意事项
    成为Lua高手之metatable
    Android 之 声音捕捉
    Lua 多变长参数传递之三点(...)
    iOS之声音捕捉
    iOS ZXing 二维码模块的加入
    Windows 7 系统的系统界面语言切换成风骚的英文
  • 原文地址:https://www.cnblogs.com/wonderKK/p/4266681.html
Copyright © 2020-2023  润新知