Unity中如何从TrackedPoseDriver获取面部追踪的centerEyeRotation数据
获取ARKit面部追踪的实时centerEyeRotation数据
我在Unity中用ARKit实现了iOS设备上的面部追踪,功能运行正常,但没法获取面部追踪生成的实时centerEyeRotation数据。我试过两种方法都没成功:
尝试的第一种方法
这段代码获取的TrackedPoseDriver返回的始终是主相机自身的数据:
using System.Collections; using System.Collections.Generic; using UnityEngine; public class getTrackedPoseDriver : MonoBehaviour { bool found; MonoBehaviour mbTrackingPose; MonoBehaviour mb; void Start() { Component[] components = Camera.main.GetComponents(typeof(MonoBehaviour)); found = false; foreach (Component component in components) { string name = component.ToString(); mb = (MonoBehaviour)component; if (name.Contains("UnityEngine.InputSystem.XR.TrackedPoseDriver")) { mbTrackingPose = mb; found = true; Debug.Log(found); Debug.Log(mbTrackingPose.name); break; } } } void Update() { Debug.Log(mbTrackingPose.transform.rotation.y); } }
尝试的第二种方法
确认XRNode.CenterEye有效,但device.TryGetFeatureValue无法获取到centerEyePosition(更不用说旋转数据):
using System.Collections; using System.Collections; using UnityEngine; using UnityEngine.XR; public class centerEyeRotation : MonoBehaviour { Quaternion centEyeRot; Vector3 centEyePos; bool tryGet; void Start() { tryGet = false; InputDevice device = InputDevices.GetDeviceAtXRNode(XRNode.CenterEye); if (device.isValid) { Debug.Log("Device is valid"); if (device.TryGetFeatureValue(CommonUsages.centerEyePosition, out centEyePos)) tryGet = true; Debug.Log("centerEyePosition found"); } } }
正确获取centerEyeRotation的方法
方法一:直接调用ARKit面部子系统(推荐)
ARKit的面部眼动数据属于XRFaceSubsystem的原生输出,这是最可靠的获取方式,因为XRNode.CenterEye更多针对VR头显场景,面部追踪的眼动数据不会自动填充到这个节点。
代码示例:
using UnityEngine; using UnityEngine.XR.ARKit; using UnityEngine.XR.ARFoundation; public class FaceEyeRotationGetter : MonoBehaviour { [SerializeField] private ARFaceManager faceManager; private ARKitFaceSubsystem arkitFaceSubsystem; void Start() { // 获取ARKit面部追踪子系统实例 arkitFaceSubsystem = faceManager.subsystem as ARKitFaceSubsystem; } void Update() { if (arkitFaceSubsystem == null || !arkitFaceSubsystem.running) return; // 遍历所有追踪到的面部(通常只有一个) foreach (var face in arkitFaceSubsystem.trackables) { // 获取左右眼的旋转数据 if (face.TryGetEyePose(ARKitEye.Left, out var leftEyePose)) { Debug.Log("左眼旋转: " + leftEyePose.rotation); } if (face.TryGetEyePose(ARKitEye.Right, out var rightEyePose)) { Debug.Log("右眼旋转: " + rightEyePose.rotation); } // 如果需要双眼平均的中心眼旋转 Quaternion centerEyeRot = Quaternion.Lerp(leftEyePose.rotation, rightEyePose.rotation, 0.5f); Debug.Log("中心眼旋转: " + centerEyeRot); } } }
使用说明:
- 确保场景中存在
ARFaceManager组件,将其拖入脚本的faceManager字段 - 该方法直接读取ARKit原生眼动数据,实时性和准确性有保障
方法二:修正InputDevice获取逻辑
如果一定要用XRNode.CenterEye,需要注意两个关键点:
- 不能只在
Start()中获取一次设备,数据可能在运行时才初始化 - 必须在每一帧尝试获取数据,而不是仅在启动时
修正后的代码:
using UnityEngine; using UnityEngine.XR; public class CenterEyeRotationGetter : MonoBehaviour { void Update() { InputDevice centerEyeDevice = InputDevices.GetDeviceAtXRNode(XRNode.CenterEye); if (centerEyeDevice.isValid) { // 获取中心眼旋转 if (centerEyeDevice.TryGetFeatureValue(CommonUsages.centerEyeRotation, out Quaternion centerEyeRot)) { Debug.Log("CenterEye旋转: " + centerEyeRot); } // 同时获取位置(如果需要) if (centerEyeDevice.TryGetFeatureValue(CommonUsages.centerEyePosition, out Vector3 centerEyePos)) { Debug.Log("CenterEye位置: " + centerEyePos); } } } }
注意:这种方法在ARKit面部追踪场景下兼容性较差,不推荐作为首选方案。
你之前的方法失败原因
- 第一种方法:你获取的是主相机上的
TrackedPoseDriver,这个组件的作用是驱动相机跟随XR设备,它的transform数据就是相机自身的,和面部眼动无关 - 第二种方法:仅在
Start()中尝试一次获取数据,而面部追踪的设备数据可能在启动后才完成初始化,且没有实时更新获取逻辑
内容的提问来源于stack exchange,提问作者cluelessButCurious
相关产品推荐
相关产品推荐

