kingdong020543
管理员
管理员
  • UID6
  • 粉丝41
  • 关注2
  • 发帖数138
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:6932回复:20

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

楼主#
更多 发布于:2015-09-11 20:41
   欢迎加入AR/VR技术交流群 129340649
      很多同学反应把模型资源全部放在工程中导出的APK非常大,那么可以用把模型资源打包成Assetbundle(下文简称AB)包的形式,可以存在服务器上,使用的时候下载到SD卡,程序再从SD卡读取资源的方式。这样就可以大大减小APK的大小。  
     Assetbundle的原理及实现代码参考 雨松MOMO 的教程:http://www.xuanyusong.com/archives/2373
     下面介绍我的实现步骤:
      (1)在Assets/Editor文件夹下创建脚本:ExportAssetBundles.cs
using UnityEngine;
using UnityEditor;
             
public class ExportAssetBundles : MonoBehaviour {
             
    [MenuItem("Custom Editor/Create AssetBunldes Main")]
    static void CreateAssetBunldesMain ()
    {
        //获取在Project视图中选择的所有游戏对象
        Object[] SelectedAsset = Selection.GetFiltered (typeof(Object), SelectionMode.DeepAssets);
                     
        //遍历所有的游戏对象
        foreach (Object obj in SelectedAsset) 
        {
            string sourcePath = AssetDatabase.GetAssetPath (obj);
            //本地测试:建议最后将Assetbundle放在StreamingAssets文件夹下,如果没有就创建一个,因为移动平台下只能读取这个路径
            //StreamingAssets是只读路径,不能写入
            //服务器下载:就不需要放在这里,服务器上客户端用www类进行下载。
            string targetPath = Application.dataPath + "/StreamingAssets/" + obj.name + ".assetbundle";
  //   if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies, BuildTarget.Android))
       if (BuildPipeline.BuildAssetBundle(obj, null, targetPath, BuildAssetBundleOptions.CollectDependencies))
            {
                Debug.Log(obj.name +"资源打包成功");
            } 
            else
            {
                Debug.Log(obj.name +"资源打包失败");
            }
        }
        //刷新编辑器
        AssetDatabase.Refresh ();   
                     
    }
}
        此脚本要注意的地方:
               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、加入头文件
using System.Collections;
       

         2、在此类中添加路径变量:(我在PC端测试时才使用到此路径,在Android端时使用了绝对路径)
//不同平台下StreamingAssets的路径是不同的,这里需要注意一下。
        public static readonly string PathURL =
            #if UNITY_ANDROID
            "jar:file://" + Application.dataPath + "!/assets/";
        #elif UNITY_IPHONE
        Application.dataPath + "/Raw/";
        #elif UNITY_STANDALONE_WIN || UNITY_EDITOR
        "file://" + Application.dataPath + "/StreamingAssets/";
        #else
        string.Empty;
        #endif
         

         3、添加一个函数:
//读取一个资源
                 
        private IEnumerator LoadMainGameObject(string path)
        {
            WWW bundle = new WWW(path);
                     
            yield return bundle;
                           
            //加载到游戏中
            yield return Instantiate(bundle.assetBundle.mainAsset);
                                 
            bundle.assetBundle.Unload(false);
        }
       

          4、在OnTrackingFound()函数的最后添加下列语句:
          表示识别到识别图之后,加载相应的模型进场景。
//      StartCoroutine(LoadMainGameObject(PathURL + "carcar.assetbundle"));//PC端测试
  //    StartCoroutine(LoadMainGameObject("file:///storage/emulated/0/carcar.assetbundle"));//Android端测试(绝对路径)
        StartCoroutine(LoadMainGameObject("file:///" + Application.persistentDataPath + "/carcar.assetbundle"));//Android端测试(相对路径)
          这三句分别用于PC端测试和Android端测试。Android端的路径请注意路径格式,在真机中Application.persistentDataPath 得到的路径名是
/mnt/sdcard/Android/data/com.xxx.xxx/files,因此AB文件也要相应的找到那个文件夹的位置放置。
         
          5、在OnTrackingLost()函数最后添加下列语句:
          表示在识别图丢失之后将识别图上对应的模型从场景中删除
Destroy(GameObject.Find("carcar(Clone)"));
           从上面语句我们可以注意到,从AB文件读取来的资源会自动在后面添加 (Clone) ,比如我的资源本身名字是carcar的,加入场景后自动变成了carcar(Clone),因此操作时应该对物体名字做出相应的修改。



         (3)创建一个脚本:ModelShow.cs (注意不能放在Editor文件夹中,与步骤(1)区分开来)
          此脚本用来对识别到识别图后加载进场景的模型进行位置、大小等方面的调节,因为模型加载进场景中时默认坐标为0,0,0 ,大小为原始大小,不利于我们观看。
using UnityEngine;
using System.Collections;
         
public class ModelShow : MonoBehaviour {
         
    public int count;
    GameObject obj;
    // Use this for initialization
    void Start () {
        count = 0;
    }
             
    // Update is called once per frame
    void Update () {
        if (count == 0)
        {
            if (GameObject.Find("carcar(Clone)"))
            {
                obj = GameObject.Find("carcar(Clone)");
                obj.transform.parent = GameObject.Find("ImageTargetCar").transform;
                obj.transform.position = GameObject.Find("ImageTargetCar").transform.position;
                obj.transform.localScale = new Vector3(0.024f, 0.024f, 0.024f);
                count++;
            }
        }
        if (GameObject.Find("carcar(Clone)") == null)
        {
            count = 0;
         
        }
    }
}


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


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

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

             完成,导出APK测试吧!

欢迎分享

枫叶飘零
论坛版主
论坛版主
  • UID15
  • 粉丝0
  • 关注0
  • 发帖数27
沙发#
发布于:2015-09-14 16:36
好东西
Gaoer
侠客
侠客
  • UID21
  • 粉丝1
  • 关注0
  • 发帖数11
  • 社区居民
板凳#
发布于:2015-09-29 11:18
那关于AB素材包中模型与识别图的相对位置以及相对大小属性版主有所研究吗
alone1209
新手
新手
  • UID809
  • 粉丝0
  • 关注0
  • 发帖数10
地板#
发布于:2016-03-22 16:57
为什么我的在电脑上测试没问题,在手机上没有任何反应啊?
迷之黑
骑士
骑士
  • UID989
  • 粉丝0
  • 关注0
  • 发帖数37
4楼#
发布于:2016-03-25 15:15
这个教程有没有Demo啊。
liugang121
侠客
侠客
  • UID1197
  • 粉丝0
  • 关注1
  • 发帖数37
  • 社区居民
  • 忠实会员
5楼#
发布于:2016-05-21 09:15
楼主为什么我的一打包出现一堆错误??
kingdong020543
管理员
管理员
  • UID6
  • 粉丝41
  • 关注2
  • 发帖数138
  • 社区居民
  • 忠实会员
  • 原创写手
6楼#
发布于:2016-05-22 08:46
liugang121:楼主为什么我的一打包出现一堆错误??回到原帖
脚本编译有错误 检查一下
Taoger
侠客
侠客
  • UID1303
  • 粉丝0
  • 关注0
  • 发帖数2
7楼#
发布于:2016-06-01 17:48
有更详细点的教程吗?层次视图中的Imagetarget要删除吗?要启用云识别吗?
jidianlxh
贫民
贫民
  • UID2284
  • 粉丝0
  • 关注0
  • 发帖数2
8楼#
发布于:2016-08-08 21:11
楼主,你好,我想问下,我在实现了读取SD卡加载模型后,如果加入了交互(LeanTouch)后,有时手指划动几下后,模型会消失,卡住
jidianlxh
贫民
贫民
  • UID2284
  • 粉丝0
  • 关注0
  • 发帖数2
9楼#
发布于:2016-08-08 21:13
楼主,你好,我想问下,我在实现了读取SD卡加载模型后,如果加入了交互(LeanTouch)后,有时手指划动几下后,模型会消失,卡住,不知你那边是否会出现这样的情况!!
xh4010
贫民
贫民
  • UID516
  • 粉丝0
  • 关注0
  • 发帖数5
10楼#
发布于:2016-08-31 10:54
iOS可以吗
少年天蝎
侠客
侠客
  • UID457
  • 粉丝0
  • 关注0
  • 发帖数14
11楼#
发布于:2016-09-24 10:40
嗯,试了一下,是可以的,谢谢大神
langzi001_ar
圣骑士
圣骑士
  • UID91
  • 粉丝4
  • 关注4
  • 发帖数64
12楼#
发布于:2016-09-29 11:10
枫叶飘零:好东西回到原帖
问一下  按照这个做的话  当识别到的时候会有模型闪的一下  该怎么处理呢
xiji321
侠客
侠客
  • UID2476
  • 粉丝0
  • 关注2
  • 发帖数56
13楼#
发布于:2016-10-10 15:35
版主,如果模型已经设置好了位置大小等属性,然后再打包,最后加载完还需要去设定这些属性吗?我在预制中加入了一个capsule模型,已经摆好位置大小,然后生成prefab,再打包成assetbundle,加载后也出现了capsule(clone),但是无法渲染出来。
xiji321
侠客
侠客
  • UID2476
  • 粉丝0
  • 关注2
  • 发帖数56
14楼#
发布于:2016-10-10 15:50
打印了Capsule(Clone)的属性,和打包前设定的一样,就是渲染不出来
[xiji321于2016-10-10 17:30编辑了帖子]
上一页
游客

返回顶部