【Unity+Vuforia】使用Assetbundle打包资源到SD卡并读取

我来回答 15821010156 | |被浏览3723次| 0
|2016-10-25 09:44:03

   很多同学反应把模型资源全部放在工程中导出的APK非常大,那么可以用把模型资源打包成Assetbundle(下文简称AB)包的形式,可以存在服务器上,使用的时候下载到SD卡,程序再从SD卡读取资源的方式。这样就可以大大减小APK的大小。   
     Assetbundle的原理及实现代码参考 雨松MOMO 的教程:http://www.xuanyusong.com/archives/2373
     下面介绍我的实现步骤:
      (1)在Assets/Editor文件夹下创建脚本:ExportAssetBundles.cs

[url=]复制代码[/url]

[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em]33

[size=1em]34

[size=1em][size=1em]using UnityEngine;
[size=1em]using UnityEditor;
[size=1em]              
[size=1em]public class ExportAssetBundles : MonoBehaviour {
[size=1em]              
[size=1em]    [MenuItem("Custom Editor/Create AssetBunldes Main")]
[size=1em]    static void CreateAssetBunldesMain ()
[size=1em]    {
[size=1em]        //获取在Project视图中选择的所有游戏对象
[size=1em]        Object[] SelectedAsset = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets);
[size=1em]                     
[size=1em]        //遍历所有的游戏对象
[size=1em]        foreach (Object obj in SelectedAsset)
[size=1em]        {
[size=1em]            string sourcePath = AssetDatabase.GetAssetPath (obj);
[size=1em]            //本地测试:建议最后将Assetbundle放在StreamingAssets文件夹下,如果没有就创建一个,因为移动平台下只能读取这个路径
[size=1em]            //StreamingAssets是只读路径,不能写入
[size=1em]            //服务器下载:就不需要放在这里,服务器上客户端用www类进行下载。
[size=1em]            string targetPath = Application.dataPath + "/StreamingAssets/" + obj.name + ".assetbundle";
[size=1em]  //   if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android))
[size=1em]       if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies))
[size=1em]            {
[size=1em]                Debug.Log(obj.name +"资源打包成功");
[size=1em]            }
[size=1em]            else
[size=1em]            {
[size=1em]                Debug.Log(obj.name +"资源打包失败");
[size=1em]            }
[size=1em]        }
[size=1em]        //刷新编辑器
[size=1em]        AssetDatabase.Refresh ();  
[size=1em]                     
[size=1em]    }
[size=1em]}



        此脚本要注意的地方:
               1、头文件脚本放置的位置;
               2、注意第20行与第21行,分别是用来打包使用在Android平台上的AB文件和使用在PC端上的AB文件)
        在哪个平台测试就要用相应方式导出的AB文件,不能混用(区别在于最后的那个参数);
               3、一次只能打包一个资源(批量打包请继续研究雨松的教程)。
               4、记得在Assets下创建一个StreamingAssets文件夹(如果原本没有的话)
        脚本保存完之后,刷新工程(保存一下),会在Unity菜单栏出现Custom Editor/Create AssetBunldes Main选项。打包流程:将要打包的模型资源保存成prefab → 选中此prefab → 选择Create AssetBunldes Main菜单项 → 导出成功。将导出得到的.assetbundle文件通过数据线放入手机SD卡根目录下等待测试吧。


       (2)打开ImageTarget下的脚本
DefaultTrackableEventHandler.cs
         1、加入头文件
[url=]复制代码[/url]
[size=1em]1

[size=1em][size=1em]using System.Collections;



        

         2、在此类中添加路径变量:(我在PC端测试时才使用到此路径,在Android端时使用了绝对路径)

[url=]复制代码[/url]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em][size=1em]//不同平台下StreamingAssets的路径是不同的,这里需要注意一下。
[size=1em]        public static readonly string PathURL =
[size=1em]            #if UNITY_ANDROID
[size=1em]            "jar:[color=blue !important][size=1em]file://" + Application.dataPath + "!/assets/";
[size=1em]        #elif UNITY_IPHONE
[size=1em]        Application.dataPath + "/Raw/";
[size=1em]        #elif UNITY_STANDALONE_WIN || UNITY_EDITOR
[size=1em]        "[color=blue !important][size=1em]file://" + Application.dataPath + "/StreamingAssets/";
[size=1em]        #else
[size=1em]        string.Empty;
[size=1em]        #endif



         

         3、添加一个函数:

[url=]复制代码[/url]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em][size=1em]//读取一个资源
[size=1em]                  
[size=1em]        private IEnumerator LoadMainGameObject(string path)
[size=1em]        {
[size=1em]            WWW bundle = new WWW(path);
[size=1em]                     
[size=1em]            yield return bundle;
[size=1em]                           
[size=1em]            //加载到游戏中
[size=1em]            yield return Instantiate(bundle.assetBundle.mainAsset);
[size=1em]                                 
[size=1em]            bundle.assetBundle.Unload(false);
[size=1em]        }



        

          4、在OnTrackingFound()函数的最后添加下列语句:
          表示识别到识别图之后,加载相应的模型进场景。

[url=]复制代码[/url]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em][size=1em]//      StartCoroutine(LoadMainGameObject(PathURL + "carcar.assetbundle"));//PC端测试
[size=1em]  //    StartCoroutine(LoadMainGameObject("[color=black !important][size=1em]file:///storage/emulated/0/carcar.assetbundle"));//Android端测试(绝对路径)
[size=1em]        StartCoroutine(LoadMainGameObject("[color=black !important][size=1em]file:///" + Application.persistentDataPath + "/carcar.assetbundle"));//Android端测试(相对路径)



          这三句分别用于PC端测试和Android端测试。Android端的路径请注意路径格式,在真机中Application.persistentDataPath 得到的路径名是
/mnt/sdcard/Android/data/com.xxx.xxx/files,因此AB文件也要相应的找到那个文件夹的位置放置。
         
          5、在OnTrackingLost()函数最后添加下列语句:
          表示在识别图丢失之后将识别图上对应的模型从场景中删除

[url=]复制代码[/url]
[size=1em]1

[size=1em][size=1em]Destroy(GameObject.Find("carcar(Clone)"));



           从上面语句我们可以注意到,从AB文件读取来的资源会自动在后面添加 (Clone) ,比如我的资源本身名字是carcar的,加入场景后自动变成了carcar(Clone),因此操作时应该对物体名字做出相应的修改。



         (3)创建一个脚本:ModelShow.cs (注意不能放在Editor文件夹中,与步骤(1)区分开来)
          此脚本用来对识别到识别图后加载进场景的模型进行位置、大小等方面的调节,因为模型加载进场景中时默认坐标为0,0,0 ,大小为原始大小,不利于我们观看。

[url=]复制代码[/url]
[size=1em]1

[size=1em]2

[size=1em]3

[size=1em]4

[size=1em]5

[size=1em]6

[size=1em]7

[size=1em]8

[size=1em]9

[size=1em]10

[size=1em]11

[size=1em]12

[size=1em]13

[size=1em]14

[size=1em]15

[size=1em]16

[size=1em]17

[size=1em]18

[size=1em]19

[size=1em]20

[size=1em]21

[size=1em]22

[size=1em]23

[size=1em]24

[size=1em]25

[size=1em]26

[size=1em]27

[size=1em]28

[size=1em]29

[size=1em]30

[size=1em]31

[size=1em]32

[size=1em][size=1em]using UnityEngine;
[size=1em]using System.Collections;
[size=1em]         
[size=1em]public class ModelShow : MonoBehaviour {
[size=1em]         
[size=1em]    public int count;
[size=1em]    GameObject obj;
[size=1em]    // Use this for initialization
[size=1em]    void Start () {
[size=1em]        count = 0;
[size=1em]    }
[size=1em]              
[size=1em]    // Update is called once per frame
[size=1em]    void Update () {
[size=1em]        if (count == 0)
[size=1em]        {
[size=1em]            if (GameObject.Find("carcar(Clone)"))
[size=1em]            {
[size=1em]                obj = GameObject.Find("carcar(Clone)");
[size=1em]                obj.transform.parent = GameObject.Find("ImageTargetCar").transform;
[size=1em]                obj.transform.position = GameObject.Find("ImageTargetCar").transform.position;
[size=1em]                obj.transform.localScale = new Vector3(0.024f, 0.024f, 0.024f);
[size=1em]                count++;
[size=1em]            }
[size=1em]        }
[size=1em]        if (GameObject.Find("carcar(Clone)") == null)
[size=1em]        {
[size=1em]            count = 0;
[size=1em]         
[size=1em]        }
[size=1em]    }
[size=1em]}





         值得注意的是:如果模型身上带有脚本,在工程中最好也存在对应的脚本,加载模型到场景中后会根据脚本名字寻找对应的脚本重载挂在物体上。


          最后一步:导出APK时别忘了打开SD卡读取权限。

         Player Settings → Other Settings → Write Access 选择 External(SDCard)

             完成,导出APK测试吧!


备注:本贴来自http://www.arvrschool.com/read.php?tid=376,如有侵权,烦请告知删除,谢谢!

分享到: 更多

Copyright © 2013-2017 ARinChina-增强现实中国技术论坛   All Rights Reserved.