为了方便AR开发交流,博主建立了一个群 :891555732,欢迎一起讨论
当项目中有两个Model Target时如果在初始就激活Model target程序集,如下所示
这样运行动态加载的话是无法识别的,哪怕只激活其中一个也无法识别,而且没有轮廓图
将上面的全部取消勾选,更改动态加载成功识别完整代码如下:
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
using Vuforia;
public class DataSetHandle : MonoBehaviour {
public static void LoadDataSet(string dataSetName)
{
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
IEnumerable datasets = objectTracker.GetDataSets();
objectTracker.Stop();
foreach (var tb in datasets)
{
objectTracker.DeactivateDataSet(tb);
}
DataSet dataSet = objectTracker.CreateDataSet();
if (dataSet.Load(dataSetName))
{
//这里必须要停止跟踪才能激活DataSet
objectTracker.ActivateDataSet(dataSet);
}
objectTracker.Start();
}
public static Transform ConfigTrackable(string trackedName, string trackComName, GameObject modelPre, Transform recogParent)
{
IEnumerable tbs = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();
foreach (TrackableBehaviour tb in tbs)
{
if (tb.TrackableName == trackedName)
{
tb.transform.parent = recogParent;
tb.gameObject.name = trackedName;
//动态添加识别组件
tb.gameObject.AddComponent(Type.GetType(trackComName));
tb.gameObject.AddComponent();
GameObject augmentation = Instantiate(modelPre, tb.transform);
if (tb.CurrentStatus == TrackableBehaviour.Status.TRACKED)
augmentation.gameObject.SetActive(true);
else
augmentation.gameObject.SetActive(false);
return augmentation.transform;
}
}
return null;
}
///
/// 关闭指定识别数据集
///
/// 数据集名称或绝对路径
public static void DeactivateDateset(string datasetName)
{
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
IEnumerable activeDataSets = objectTracker.GetActiveDataSets();
List activeDataSetsToBeRemoved = activeDataSets.ToList();
List dataSetsToBeActive = new List();
foreach (DataSet ads in activeDataSetsToBeRemoved)
{
objectTracker.DeactivateDataSet(ads);
if (!ads.Path.Contains(datasetName))
{
dataSetsToBeActive.Add(ads);
}
else
{
objectTracker.DestroyDataSet(ads, false);
var trackables = ads.GetTrackables();
foreach (var item in trackables)
{
TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(item, true);
}
}
}
objectTracker.Stop();
foreach (DataSet ds in dataSetsToBeActive)
{
objectTracker.ActivateDataSet(ds);
}
objectTracker.Start();
}
//通过名称切换ModelTarget
public void SwitchTargetByName(string activateThisDataset)
{
TrackerManager trackerManager = (TrackerManager)TrackerManager.Instance;
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
IEnumerable datasets = objectTracker.GetDataSets();
IEnumerable activeDataSets = objectTracker.GetActiveDataSets();
List activeDataSetsToBeRemoved = activeDataSets.ToList();
//循环遍历所有活动数据集并停用它们。
foreach (DataSet ads in activeDataSetsToBeRemoved)
{
objectTracker.DeactivateDataSet(ads);
}
//当ObjectTracker同时工作时,不应该交换数据集。
//所以,先停止跟踪器。
objectTracker.Stop();
//然后,查找新的数据集,如果有一个数据集,激活它。
foreach (DataSet ds in datasets)
{
if (ds.Path.Contains(activateThisDataset))
{
objectTracker.ActivateDataSet(ds);
}
}
//最后,启动对象跟踪器。
objectTracker.Start();
}
//此函数将加载并激活指定的数据集。它不会被取消激活
//任何东西,所以确保没有其他模型目标数据集是主动的以避免问题。
public void ActivateTarget(string loadThisDataset)
{
TrackerManager trackerManager = (TrackerManager)TrackerManager.Instance;
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
//Stop the tracker.
objectTracker.Stop();
//创建一个新的数据集对象。
DataSet dataset = objectTracker.CreateDataSet();
//如果数据集存在,加载并激活它。
if (DataSet.Exists(loadThisDataset))
{
dataset.Load(loadThisDataset);
objectTracker.ActivateDataSet(dataset);
}
//Start the object tracker.
objectTracker.Start();
}
}
参考链接:
第一个链接简单明了,我首先采用了第一个链接加载程序集并初始化模型,第二个链接功能齐全,但是是Resources加载程序集,移动平台首先还得先将资源放在Application.persistentDataPath + "/" + "DataDirectory"+"/"目录下,不实用,两者结合非常nice
代码如下:
using System.Collections.Generic;
using UnityEngine;
using Vuforia;
using System.Linq;
public class TrackableSetting : MonoBehaviour
{
public static TrackableSetting Instance;
public void Awake()
{
Instance = this;
}
public void LoadDataSet(string dataSetName)
{
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
IEnumerable datasets = objectTracker.GetDataSets();
foreach (var tb in datasets)
{
objectTracker.DeactivateDataSet(tb);
}
DataSet dataSet = objectTracker.CreateDataSet();
if (dataSet.Load(dataSetName))
{
objectTracker.Stop();//这里必须要停止跟踪才能激活DataSet
objectTracker.ActivateDataSet(dataSet);
objectTracker.Start();
}
}
public Transform ConfigTrackable(string trackedName,GameObject modelPre,Transform recogParent)
{
IEnumerable tbs = TrackerManager.Instance.GetStateManager().GetTrackableBehaviours();
foreach (TrackableBehaviour tb in tbs)
{
if (tb.TrackableName == trackedName)
{
tb.transform.parent = recogParent;
tb.gameObject.name = trackedName;
//下面这两句不能少,需要给它加上这两个组件
tb.gameObject.AddComponent();
tb.gameObject.AddComponent();
GameObject augmentation = Instantiate(modelPre, tb.transform);
if(tb.CurrentStatus == TrackableBehaviour.Status.TRACKED)
augmentation.gameObject.SetActive(true);
else
augmentation.gameObject.SetActive(false);
return augmentation.transform;
}
}
return null;
}
///
/// 关闭指定识别数据集
///
/// 数据集名称或绝对路径
public virtual void DeactivateDateset(string datasetName)
{
ObjectTracker objectTracker = TrackerManager.Instance.GetTracker();
IEnumerable datasets = objectTracker.GetDataSets();
IEnumerable activeDataSets = objectTracker.GetActiveDataSets();
List activeDataSetsToBeRemoved = activeDataSets.ToList();
List dataSetsToBeActive = new List();
foreach (DataSet ads in activeDataSetsToBeRemoved)
{
objectTracker.DeactivateDataSet(ads);
if (!ads.Path.Contains(datasetName))
{
dataSetsToBeActive.Add(ads);
}
else
{
objectTracker.DestroyDataSet(ads, false);
var trackables = ads.GetTrackables();
foreach (var item in trackables)
{
TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(item, true);
}
}
}
objectTracker.Stop();
foreach (DataSet ds in dataSetsToBeActive)
{
objectTracker.ActivateDataSet(ds);
}
objectTracker.Start();
}
}
问题总结:
①.第一篇参考博文大家会看到地下评论说ObjectTracker objectTracker = TrackerManager.Instance.GetTracker
Debug.Log(TrackerManager.Instance);
输出如下:
发现是start函数都执行完后才有值,因此在Update函数中用个参数来判断不为空即执行,完美解决
if(!isInit && TrackerManager.Instance != null)
{
isInit = true;
TrackableSetting.Instance.LoadDataSet("Saturn_5");
//TODO 动态生成,要
Model = TrackableSetting.Instance.ConfigTrackable("Saturn_5", ModelPre[0],transform); //生成模型
if (Model != null)
{
modelTarget = Model.parent.GetComponent();
modelTarget.GuideViewMode = ModelTargetBehaviour.GuideViewDisplayMode.GuideView2D;
}
}
②.移除特定的程序集时出现问题:
解决方案参考链接:https://blog.csdn.net/aiyan1111111/article/details/52814017
原来时我虽然Destroy了程序集,但是并没有将程序集里面的识别对象从 TrackerManager.Instance.GetStateManager()中移除,而第二篇博文中那位老兄应该是没有Destroy物体只是Deactive程序集而已,才没有出现我这个问题,总之增加了如下代码:
var trackables = ads.GetTrackables();
foreach (var item in trackables)
{
TrackerManager.Instance.GetStateManager().DestroyTrackableBehavioursForTrackable(item, true);
}
完整代码已经在上面TrackableSetting脚本更新