Unity、Vuforia与HoloLens中球体相对图像目标定位异常问题
问题描述
我正在使用Unity、Vuforia和HoloLens开发AR应用,目标是在Vuforia图像目标的相对指定位置(如相对于图像目标原点的(1, 2, 3)处)创建球体。
已尝试操作
- 手动操作:在Unity Inspector中将球体作为Vuforia图像目标的子物体,设置位置为(1, 2, 3),球体显示位置正确。
- 脚本创建:通过脚本创建球体时,位置不符合预期。
代码尝试
我原本用以下方式定位球体:
sphere.transform.position = targetTransform.position + localPosition;
其中targetTransform是Vuforia目标ObserverBehaviour的Transform组件,但脚本创建的球体与手动放置的位置不一致。
完整脚本
SphereManager类
public class SphereManager { private GameObject sphere; private Vector3 localPosition; public SphereManager(Vector3 position) { localPosition = position; } public void CreateSphere(Transform targetTransform) { if (sphere == null) { sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.SetParent(targetTransform, false); sphere.transform.position = targetTransform.position + localPosition; sphere.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); } } public void DestroySphere() { if (sphere != null) { GameObject.Destroy(sphere); sphere = null; } } public bool IsSphereActive() => sphere != null; }
SphereCreator类
public class SphereCreator : MonoBehaviour { public Vector3 pose = Vector3.zero; private SphereManager sphereManager; private ObserverBehaviour observerBehaviour; void Start() { sphereManager = new SphereManager(pose); observerBehaviour = GetComponent<ObserverBehaviour>() ?? GetComponentInChildren<ObserverBehaviour>() ?? GetComponentInParent<ObserverBehaviour>(); if (observerBehaviour) { observerBehaviour.OnTargetStatusChanged += OnTargetStatusChanged; } else { Debug.LogWarning("ObserverBehaviour component not found."); } } private void OnTargetStatusChanged(ObserverBehaviour behaviour, TargetStatus targetStatus) { if (targetStatus.Status == Status.TRACKED || targetStatus.Status == Status.EXTENDED_TRACKED) { sphereManager.CreateSphere(behaviour.transform); } else { sphereManager.DestroySphere(); } } private void OnDestroy() { if (observerBehaviour != null) { observerBehaviour.OnTargetStatusChanged -= OnTargetStatusChanged; } } }
核心问题:脚本创建的球体与Inspector手动放置的球体无法对齐,如何在脚本中设置位置确保两者一致?
解决方案
问题出在你设置球体位置的逻辑上。当球体作为图像目标的子物体时,应该使用局部坐标定位,这和你手动在Inspector中操作的逻辑完全一致。
修改步骤
在SphereManager的CreateSphere方法中,替换设置position的代码,改为直接设置localPosition:
public void CreateSphere(Transform targetTransform) { if (sphere == null) { sphere = GameObject.CreatePrimitive(PrimitiveType.Sphere); sphere.transform.SetParent(targetTransform, false); // 关键修改:使用局部坐标匹配手动操作逻辑 sphere.transform.localPosition = localPosition; sphere.transform.localScale = new Vector3(0.5f, 0.5f, 0.5f); } }
原因解释
- 手动操作时,你在Inspector中设置的是球体相对于父物体(图像目标)的局部位置。
- 原代码中
targetTransform.position + localPosition计算的是世界坐标,会忽略图像目标的旋转、缩放等变换信息,导致位置偏移。 - 使用
localPosition可以直接将球体放置在相对于图像目标原点的指定位置,完全对齐手动放置的效果。
额外优化
如果图像目标存在缩放,可根据需求调整局部位置以适配缩放后的空间:
// 若父物体有缩放,按比例调整局部位置(可选) sphere.transform.localPosition = Vector3.Scale(localPosition, targetTransform.localScale);
内容的提问来源于stack exchange,提问作者Morteza Namvar
相关产品推荐
相关产品推荐

