在AR的开发过程中有时候会需要用到脱卡功能,脱卡功能是指即使识别图丢失的情况下被识别出来的模型也不会消失;
实现脱卡功能有以下几种解决思路:
- 在Vuforia插件的默认条件下,当识别图离开摄像头时间,ImageTarget 的SetActive (false),所以其子物体(model)也就不显示了,因此解决的办法就是在Target (false)时间将模型放到一个合适的位置,这样就能实现脱卡,当Target (true)时,再回到原来位置;
- 将Vuforia 中默认的设定修改下,当识别图离开时不做模型的隐藏即可,
当然这两种方法根源就是当识别图在摄像画面中消失后不隐藏模型;
首先来看下识别图消失,模型跟着隐藏也就是不脱卡的根源是哪里:
经过查找不难发现在ImageTarget 物体上有一个脚本组件名为“DefaultTrackableEventHandler” ,在这个脚本里面主要控制识别图显示和丢失时的两种操作:
在OnTrackingFound和OnTrakingLost两个方法中分别控制了ImageTarget的子物体的渲染组件及碰撞体组件的显示与隐藏;
既然问题的根源已经找到了,那么我们只需要让模型在显示之后不隐藏,就可以实现脱卡功能;
接下来进入到脱卡功能制作过程:
重新写识别图时显示与隐藏被识别出的物体的方法:
这里直接上代码:
using System.Collections.Generic;
using UnityEngine;
public class Manager : MonoBehaviour
{
public static Manager Instance;public List<Transform> allImageTarget = new List<Transform>();public string lastTranckName = "";public bool lost = false;private Transform ARCamera;private Vector3 lostCamPos = new Vector3(0, 4.9f, -3.5f);public Transform arcam;private void Awake(){
ARCamera = GameObject.Find("ARCamera").transform;Instance = this;}void Update(){
if (lost){
ARCamera.localPosition = lostCamPos;ARCamera.localRotation = Quaternion.Euler(55, 0, 0);ARCamera.localRotation = Quaternion.identity;}}public void HideallModel(){
foreach (Transform imageTarget in allImageTarget){
imageTarget.GetComponent<MyTrackable>().HiderThisModel();}}
以上脚本主要控制当识别图消失之后,设置模型显示的位置,根据实际情况可以自己调整数值;,然后就是最后的公有方法HideallModel,可以运用在多张识别图脱卡的情况,假设扫了第一张识别图,显示第一个模型,再扫第二张图时想要第一个模型消失,则执行HideallModel方法即可;否则不做处理;如果扫描N个识别图都不隐藏模型,但想设置一个清空操作,则添加一个按钮,点击按钮执行HideallModel方法即可;
using UnityEngine;
using Vuforia;
/// <summary>
/// A custom handler that implements the ITrackableEventHandler interface.
/// </summary>
public class MyTrackable : MonoBehaviour,ITrackableEventHandler
{
private TrackableBehaviour mTrackableBehaviour;private bool isFirstfound = false;void Start(){
Manager.Instance.allImageTarget.Add(this.transform);HiderThisModel();mTrackableBehaviour = GetComponent<TrackableBehaviour>();if (mTrackableBehaviour){
mTrackableBehaviour.RegisterTrackableEventHandler(this);}}public void OnTrackableStateChanged(TrackableBehaviour.Status previousStatus,TrackableBehaviour.Status newStatus){
if (newStatus == TrackableBehaviour.Status.DETECTED ||newStatus == TrackableBehaviour.Status.TRACKED ||newStatus == TrackableBehaviour.Status.EXTENDED_TRACKED){
isFirstfound = true;Manager.Instance.lost = false;if (Manager.Instance.lastTranckName == mTrackableBehaviour.TrackableName){
return;}else{
// Manager.Instance.HideallModel(); //扫描到不同的识别图先隐藏所有的模型ShowThisModel();}}else{
if (isFirstfound){
Manager.Instance.lastTranckName = mTrackableBehaviour.TrackableName;Manager.Instance.lost = true;}}}/// <summary>/// 显示当前模型/// </summary>public void ShowThisModel(){
foreach (Transform child in this.transform){
child.gameObject.SetActive(true);}}/// <summary>/// 隐藏当前模型/// </summary>public void HiderThisModel(){
foreach (Transform child in this.transform){
child.gameObject.SetActive(false);}}
将新写的方法代替Vuforia 默认的方法:
Manager 方法挂在层级面板的任何一个物体身上即可;
最后测试结果:
脱卡后: