using UnityEngine; namespace Stary.Evo.RKTools { #if Evo_Xreal public abstract class GestureXrealBase : MonoBehaviour { [SerializeField] private UnityEngine.XR.Hands.Handedness m_Handedness; private UnityEngine.XR.Hands.XRHandTrackingEvents handTrackingEvents = null; [SerializeField] [Tooltip("The hand shape or pose that must be detected for the gesture to be performed.")] private ScriptableObject m_HandShapeOrPose; [SerializeField] [Tooltip( "The minimum amount of time the hand must be held in the required shape and orientation for the gesture to be performed.")] float m_MinimumHoldTime = 0.2f; [SerializeField] [Tooltip("The interval at which the gesture detection is performed.")] private float m_GestureDetectionInterval = 0.1f; private float m_TimeOfLastConditionCheck; private UnityEngine.XR.Hands.Gestures.XRHandShape m_HandShape; private UnityEngine.XR.Hands.Gestures.XRHandPose m_HandPose; private bool m_WasDetected; // 上一帧是否检测到手势 private bool m_PerformedTriggered; // 手势执行事件是否已触发 private float m_HoldStartTime; // 手势开始保持的时间 protected void OnEnable() { var trackingEvents = GameObject.FindObjectsOfType(); if (handTrackingEvents == null) { foreach (var track in trackingEvents) { if (track.handedness == m_Handedness) { handTrackingEvents = track; break; } } } handTrackingEvents.jointsUpdated.AddListener(OnJointsUpdated); m_HandShape = m_HandShapeOrPose as UnityEngine.XR.Hands.Gestures.XRHandShape; m_HandPose = m_HandShapeOrPose as UnityEngine.XR.Hands.Gestures.XRHandPose; } void OnDisable() { handTrackingEvents.jointsUpdated.RemoveListener(OnJointsUpdated); } /// /// 手部关节数据更新时的回调方法 /// /// 关节更新事件参数,包含手部关节数据 void OnJointsUpdated(UnityEngine.XR.Hands.XRHandJointsUpdatedEventArgs eventArgs) { // 检查是否在检测间隔内,避免过于频繁的检测 if (!isActiveAndEnabled || Time.timeSinceLevelLoad < m_TimeOfLastConditionCheck + m_GestureDetectionInterval) return; // 检查手部是否被跟踪,以及是否满足形状或姿势条件 var detected = handTrackingEvents.handIsTracked && (m_HandShape != null && m_HandShape.CheckConditions(eventArgs) || m_HandPose != null && m_HandPose.CheckConditions(eventArgs)); // 处理检测状态的变化 if (!m_WasDetected && detected) { // 开始检测到手势,记录开始时间 m_HoldStartTime = Time.timeSinceLevelLoad; } else if (m_WasDetected && !detected) { // 手势结束,重置触发状态并触发结束事件 m_PerformedTriggered = false; GestureFail(); // m_Background.color = m_BackgroundDefaultColor; } // 更新检测状态 m_WasDetected = detected; // 检查是否满足保持时间要求 if (!m_PerformedTriggered && detected) { var holdTimer = Time.timeSinceLevelLoad - m_HoldStartTime; if (holdTimer > m_MinimumHoldTime) { // 满足保持时间,触发手势执行事件 GestureSuccess(); m_PerformedTriggered = true; // m_Background.color = m_BackgroundHiglightColor; } } // 更新上次检查时间 m_TimeOfLastConditionCheck = Time.timeSinceLevelLoad; } #region 需要被重写的方法 /// /// 左手成功识别到手势不断执行操作 /// /// 左手手势类型 /// 左手掌心朝向 public abstract void GestureSuccess(); /// /// 左手未识别到手势执行操作 /// public abstract void GestureFail(); #endregion } #endif }