kingdong020543
管理员
管理员
  • UID6
  • 粉丝47
  • 关注2
  • 发帖数141
  • 喜欢达人
  • 社区居民
  • 忠实会员
  • 原创写手
阅读:14425回复:61

【Vuforia+Unity】动态加载识别图和资源

楼主#
更多 发布于:2016-06-16 11:36
欢迎转载,转载请注明:
谢谢合作!
AR/VR学院技术交流②群: 346836719
AR/VR学院技术交流①群:129340649(已满)

图片:arvrshcool.jpg







实现动态加载识别图(不用更新APP,也能对识别图进行更新添加)和模型(包括视频,视频需单独处理)




直接贴代码,有少量注释。




using UnityEngine;
using Vuforia;
using System.Collections;
using System.Collections.Generic;
using System.Xml;
     
public class SDCardDataSetLoader : MonoBehaviour {
     
    public GameObject VideoManager;             //在面板拖Easy Movie Texture的预制体VideoManager进来
    DataSet m_Dataset = null;
    ObjectTracker tracker;
    bool Bool_Loaded = false;
    public static bool initDone = false;            //控制模型加载完后再加载Dataset
    string xmlPath;                     
    public string xmlName;  //例如:StonesAndChips.xml     由Vuforia生成
    int ImageTargetCount ;                      //存放要加载的Dataset中的识别图数量
    List<string> ModelName = new List<string>();            //存放模型名字列表
     
    // Use this for initialization
    void Start () {
        ModelName.Clear();
        ImageTargetCount = 0;
        xmlPath = Application.persistentDataPath + "/Scenes/" + GlobalValue.currentSceneName + "/" + GlobalValue.currentSceneName + ".xml";
        GetXML(xmlPath);
        LoadModel();
    }
         
    // Update is called once per frame
    void Update () {
        if(initDone)
        {
            if (VuforiaRuntimeUtilities.IsVuforiaEnabled() && !Bool_Loaded)
            {
                if (m_Dataset == null)
                {
                    tracker = TrackerManager.Instance.GetTracker<ObjectTracker>();
                    m_Dataset = tracker.CreateDataSet();
     
                }
                Bool_Loaded = m_Dataset.Load(xmlPath, VuforiaUnity.StorageType.STORAGE_ABSOLUTE);
                tracker.ActivateDataSet(m_Dataset);
     
                int i = ImageTargetCount;
                foreach (GameObject go in GameObject.FindObjectsOfType(typeof(GameObject)))
                {
     
                    if (go.name == "New Game Object")
                    {
                        go.name = "ImageTarget_" + ModelName[i - 1];
                        go.AddComponent<TurnOffBehaviour>();
                        go.AddComponent<DefaultTrackableEventHandler>();
                        go.AddComponent<FindSon>();
                        i--;
     
                    }
                }
            }
        }
     
   //     Debug.Log(subGameObject.name);
    }
     
    void LoadModel()
    {
        for (int i = ImageTargetCount; i > 0; i--)
        {
            if (ModelName[i - 1].Contains("video_"))                            //加载Video
            {
                print("video~~~~~~");
                GameObject tmp = Instantiate(VideoManager) as GameObject;
                tmp.name = ModelName[i - 1] + "(Clone)";
            }
            else
            {
                //加载模型 assetbundle 包,请修改成自己的对应地址
                string GameObjectPath = "file:///" + Application.persistentDataPath + "/Scenes/" + GlobalValue.currentSceneName + "/" + ModelName[i - 1] + ".assetbundle";
                StartCoroutine(LoadMainGameObject(GameObjectPath));
            }
        }
        initDone = true;
    }
     
     
    /// <summary>
    /// 解析XML
    /// </summary>
    /// <param name="path">XML地址</param>
    void GetXML(string path)
    {
        int _ImageTargetCount = 0;
        XmlDocument xmlDoc = new XmlDocument();
        xmlDoc.Load(path);
        XmlNodeList nodeList = xmlDoc.SelectSingleNode("QCARConfig").ChildNodes;
        foreach (XmlElement xe in nodeList)
        {
            Debug.Log("NAME :" + xe.Name);
            foreach (XmlElement x1 in xe.ChildNodes)
            {
                     
                if (x1.Name == "ImageTarget")
                {
                    _ImageTargetCount++;
                    Debug.Log("VALUE :" + x1.GetAttribute("name"));
                    ModelName.Add(x1.GetAttribute("name"));
                }
            }
        }
        Debug.Log(_ImageTargetCount);
        ImageTargetCount = _ImageTargetCount;
    }
     
         
    /// <summary>
    /// 加载AssetBundle
    /// </summary>
    /// <param name="path">AssetBundle地址</param>
    /// <returns></returns>
    private IEnumerator LoadMainGameObject(string path)
    {
        WWW bundle = new WWW(path);   
        yield return bundle;
        yield return Instantiate(bundle.assetBundle.mainAsset);
        bundle.assetBundle.Unload(false);
    }
     
    public void BackButton()
    {
        Application.LoadLevel(0);
     
    }
}


using UnityEngine;
using System.Collections;
 
public class FindSon : MonoBehaviour {
 
    // Use this for initialization
    void Start () {
 
    }
     
    // Update is called once per frame
    void Update () {
        if(SDCardDataSetLoader.initDone)
        {
            foreach (GameObject go in GameObject.FindObjectsOfType(typeof(GameObject)))
            {
                if (go.name == (gameObject.name.Substring(12) + "(Clone)"))//识别图名字格式:ImageTarget_(模型名字),此处根据模型名字找它的子物体
                {
                    go.transform.parent = gameObject.transform;
                    go.transform.localScale = new Vector3(1.0f, 1.0f, 1.0f);
                    go.transform.localPosition = new Vector3(0, 0, 0);
 
                    if(go.name.Contains("video_"))//视频(非模型,用的是Easy Movie Texture插件)
                    {
                        go.transform.localEulerAngles = new Vector3(90, 0, 0);
                    }
 
                    go.AddComponent<Move>();
 
                    Renderer[] rendererComponents = go.GetComponentsInChildren<Renderer>(true);
                    Collider[] colliderComponents = go.GetComponentsInChildren<Collider>(true);
                    // Disable rendering:
                    foreach (Renderer component in rendererComponents)
                    {
                        component.enabled = false;
                    }
                    // Disable colliders:
                    foreach (Collider component in colliderComponents)
                    {
                        component.enabled = false;
                    }
 
                    Destroy(gameObject.GetComponent<FindSon>());
                }
            }
        }
    }
}

欢迎分享

imbest
贫民
贫民
  • UID35
  • 粉丝0
  • 关注0
  • 发帖数1
沙发#
发布于:2016-06-17 08:01
你是标题党吗?应注明是对已有识别图进行更换,让人还以为是动态上传制作新的识别图
kingdong020543
管理员
管理员
  • UID6
  • 粉丝47
  • 关注2
  • 发帖数141
  • 喜欢达人
  • 社区居民
  • 忠实会员
  • 原创写手
板凳#
发布于:2016-06-17 09:00
imbest:你是标题党吗?应注明是对已有识别图进行更换,让人还以为是动态上传制作新的识别图回到原帖
灵活运用 什么都能做的到
walkerwong
骑士
骑士
  • UID517
  • 粉丝1
  • 关注0
  • 发帖数44
  • 忠实会员
地板#
发布于:2016-06-19 14:45
请问这代码要贴在哪里?
The story is never end
trk1009
新手
新手
  • UID1904
  • 粉丝0
  • 关注0
  • 发帖数6
4楼#
发布于:2016-07-04 17:14
代码里ImageTarget 里面没有选database  你怎么识别图的?
kingdong020543
管理员
管理员
  • UID6
  • 粉丝47
  • 关注2
  • 发帖数141
  • 喜欢达人
  • 社区居民
  • 忠实会员
  • 原创写手
5楼#
发布于:2016-07-05 12:02
trk1009:代码里ImageTarget 里面没有选database  你怎么识别图的?回到原帖
不需要选的  用了我的代码加载之后是自动匹配  。
trk1009
新手
新手
  • UID1904
  • 粉丝0
  • 关注0
  • 发帖数6
6楼#
发布于:2016-07-05 15:20
FindSon脚本 你是用来做什么的
kingdong020543
管理员
管理员
  • UID6
  • 粉丝47
  • 关注2
  • 发帖数141
  • 喜欢达人
  • 社区居民
  • 忠实会员
  • 原创写手
7楼#
发布于:2016-07-05 17:45
trk1009:FindSon脚本 你是用来做什么的回到原帖
已更新
trk1009
新手
新手
  • UID1904
  • 粉丝0
  • 关注0
  • 发帖数6
8楼#
发布于:2016-07-07 16:54
kingdong020543:已更新回到原帖
thanks
Zachary
贫民
贫民
  • UID2055
  • 粉丝0
  • 关注0
  • 发帖数1
9楼#
发布于:2016-07-21 15:08
请问这个程序的Hirearchy里面有哪些部件?
kingdong020543
管理员
管理员
  • UID6
  • 粉丝47
  • 关注2
  • 发帖数141
  • 喜欢达人
  • 社区居民
  • 忠实会员
  • 原创写手
10楼#
发布于:2016-07-21 22:26
Zachary:请问这个程序的Hirearchy里面有哪些部件?回到原帖
只有一个挂载了此脚本的ARCamera和一个光源Light
fanglinyuan
贫民
贫民
  • UID2092
  • 粉丝0
  • 关注1
  • 发帖数1
11楼#
发布于:2016-07-24 13:12
编译失败啊
string GameObjectPath = "file:///" + Application.persistentDataPath + "/Scenes/" + GlobalValue.currentSceneName + "/" + ModelName[i - 1] + ".assetbundle";

这个 GlobalValue.currentSceneName不存在

go.AddComponent<Move>();   这个Move组件也不存在

能否给一个完整的工程示范呢
多谢啦
kingdong020543
管理员
管理员
  • UID6
  • 粉丝47
  • 关注2
  • 发帖数141
  • 喜欢达人
  • 社区居民
  • 忠实会员
  • 原创写手
12楼#
发布于:2016-07-24 18:30
fanglinyuan:编译失败啊
string GameObjectPath = "file:///" + Application.persistentDataPath + "/Scenes/" + GlobalValue.currentSceneName +...
回到原帖
GlobalValue.currentSceneName 是相应进入的场景的名字
go.AddComponent<Move>(); 这个用不到就先注释掉,这个是模型的交互控制脚本
燕临江
侠客
侠客
  • UID2156
  • 粉丝0
  • 关注1
  • 发帖数12
  • 社区居民
13楼#
发布于:2016-07-29 16:28
大神,我水平较低- -,那啥,能不能详细一些说一下,原理,和方法。
kingdong020543
管理员
管理员
  • UID6
  • 粉丝47
  • 关注2
  • 发帖数141
  • 喜欢达人
  • 社区居民
  • 忠实会员
  • 原创写手
14楼#
发布于:2016-07-29 16:34
燕临江:大神,我水平较低- -,那啥,能不能详细一些说一下,原理,和方法。回到原帖
代码的关键就是Dataset.Load
这个Vuforia自带的函数能够生成N个ImageTarget(N = Dataset里识别图的数量),并自动按顺序匹配识别图,这些都不需要你操作,你要做的只是往这些ImageTarget下面添加那张识别图要显示的模型。
    建议先在Unity的Editor上运行,主要观察场景内有什么物体生成了。
上一页
游客

返回顶部