You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

AR应用中多Image Target对应物体的重置与独立操控问题求助

AR应用问题解决方案

问题描述

我正在开发一款简单的AR应用,设置了8个Image Target,每个目标对应一个子物体。相机追踪到Image Target时显示对应子物体,且同一时间仅能追踪一个目标。我用LeanTouch实现了物体的旋转和捏合缩放功能,但现在遇到两个问题:

  1. 对应的Image Target失去追踪时,如何让每个物体重置到初始状态?
  2. 怎么实现每个物体的独立操控?现在旋转一个物体后,扫描其他Image Target时,对应物体会继承前一个物体的旋转状态。

尝试过的脚本(未生效)

using UnityEngine;
using Vuforia;

public class ResetPositionOnTrackingLost : MonoBehaviour
{
    private ObserverBehaviour observerBehaviour;
    private Vector3 initialPosition;
    private Quaternion initialRotation;
    private Vector3 initialScale;

    void Start()
    {
        observerBehaviour = GetComponent<ObserverBehaviour>();
        if (observerBehaviour != null)
        {
            observerBehaviour.OnTargetStatusChanged += OnTargetStatusChanged;
        }

        // 存储物体的初始位置、旋转和缩放
        initialPosition = transform.localPosition;
        initialRotation = transform.localRotation;
        initialScale = transform.localScale;
    }

    private void OnDestroy()
    {
        if (observerBehaviour != null)
        {
            observerBehaviour.OnTargetStatusChanged -= OnTargetStatusChanged;
        }
    }

    private void OnTargetStatusChanged(ObserverBehaviour behaviour, TargetStatus status)
    {
        if (status.Status == Status.NO_POSE)
        {
            // 目标丢失,重置位置、旋转和缩放
            ResetTransform();
        }
    }

    public void ResetTransform()
    {
        transform.localPosition = initialPosition;
        transform.localRotation = initialRotation;
        transform.localScale = initialScale;
    }
}

解决方案

问题1:目标丢失时重置物体状态

原脚本未生效的核心原因是脚本挂载对象错误,以及状态判断逻辑不完善:

  1. 修正挂载对象:将脚本挂在每个Image Target对应的子物体上,而非Image Target本身——我们需要重置的是子物体的状态,而非追踪目标的姿态。
  2. 完善状态判断:Vuforia中目标丢失时可能触发Status.NO_POSE或Status.NOT_TRACKED,需同时处理两种状态;且要确保目标重新被追踪时,先重置子物体状态再显示。

修改后的脚本:

using UnityEngine;
using Vuforia;

public class ResetOnTrackingStateChange : MonoBehaviour
{
    // 关联对应的Image Target对象
    public ObserverBehaviour imageTarget;
    private Vector3 initialLocalPos;
    private Quaternion initialLocalRot;
    private Vector3 initialLocalScale;

    void Start()
    {
        // 存储子物体相对于父物体的初始本地变换
        initialLocalPos = transform.localPosition;
        initialLocalRot = transform.localRotation;
        initialLocalScale = transform.localScale;

        if (imageTarget != null)
        {
            imageTarget.OnTargetStatusChanged += HandleTargetStatusChange;
            // 初始隐藏子物体
            gameObject.SetActive(false);
        }
    }

    private void OnDestroy()
    {
        if (imageTarget != null)
        {
            imageTarget.OnTargetStatusChanged -= HandleTargetStatusChange;
        }
    }

    private void HandleTargetStatusChange(ObserverBehaviour behaviour, TargetStatus status)
    {
        if (status.Status == Status.TRACKED || status.Status == Status.EXTENDED_TRACKED)
        {
            // 目标被追踪:先重置状态,再显示物体
            ResetToInitialState();
            gameObject.SetActive(true);
        }
        else
        {
            // 目标丢失:隐藏物体并重置状态
            gameObject.SetActive(false);
            ResetToInitialState();
        }
    }

    private void ResetToInitialState()
    {
        transform.localPosition = initialLocalPos;
        transform.localRotation = initialLocalRot;
        transform.localScale = initialLocalScale;
    }
}

使用说明:

  • 给每个子物体挂载该脚本,在Inspector面板中关联对应的Image Target。
  • 子物体初始保持隐藏,仅当Image Target被追踪时才显示并重置状态。

问题2:实现物体独立操控

LeanTouch默认对所有可交互物体生效,导致状态继承。解决思路是仅让当前激活的子物体响应交互:

  1. 组件级控制
    在子物体的LeanRotate、LeanScale组件上,添加状态判断:只有当物体激活时才允许交互。

  2. 代码控制交互权限
    在上述ResetOnTrackingStateChange脚本中扩展逻辑,控制交互组件的启用/禁用:

    // 引用子物体上的Lean交互组件
    public Lean.Touch.LeanRotate leanRotate;
    public Lean.Touch.LeanScale leanScale;
    
    void Start()
    {
        // ... 原有代码 ...
        // 初始禁用交互组件
        if (leanRotate != null) leanRotate.enabled = false;
        if (leanScale != null) leanScale.enabled = false;
    }
    
    private void HandleTargetStatusChange(ObserverBehaviour behaviour, TargetStatus status)
    {
        if (status.Status == Status.TRACKED || status.Status == Status.EXTENDED_TRACKED)
        {
            ResetToInitialState();
            gameObject.SetActive(true);
            // 启用当前物体的交互组件
            if (leanRotate != null) leanRotate.enabled = true;
            if (leanScale != null) leanScale.enabled = true;
        }
        else
        {
            gameObject.SetActive(false);
            ResetToInitialState();
            // 禁用交互组件,避免影响其他物体
            if (leanRotate != null) leanRotate.enabled = false;
            if (leanScale != null) leanScale.enabled = false;
        }
    }
    

通过这种方式,只有当前被追踪显示的子物体才会开启LeanTouch交互,其他物体的交互组件处于禁用状态,不会继承之前的操作状态。


内容的提问来源于stack exchange,提问作者Gerald1111

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 18:52:41