AR应用中多Image Target对应物体的重置与独立操控问题求助
AR应用问题解决方案
问题描述
我正在开发一款简单的AR应用,设置了8个Image Target,每个目标对应一个子物体。相机追踪到Image Target时显示对应子物体,且同一时间仅能追踪一个目标。我用LeanTouch实现了物体的旋转和捏合缩放功能,但现在遇到两个问题:
- 对应的Image Target失去追踪时,如何让每个物体重置到初始状态?
- 怎么实现每个物体的独立操控?现在旋转一个物体后,扫描其他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:目标丢失时重置物体状态
原脚本未生效的核心原因是脚本挂载对象错误,以及状态判断逻辑不完善:
- 修正挂载对象:将脚本挂在每个Image Target对应的子物体上,而非Image Target本身——我们需要重置的是子物体的状态,而非追踪目标的姿态。
- 完善状态判断: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默认对所有可交互物体生效,导致状态继承。解决思路是仅让当前激活的子物体响应交互:
组件级控制
在子物体的LeanRotate、LeanScale组件上,添加状态判断:只有当物体激活时才允许交互。代码控制交互权限
在上述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
相关产品推荐
相关产品推荐

