Files
zhangzheng 2c230960db 修改
2026-03-25 16:58:26 +08:00

126 lines
4.7 KiB
C#

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<UnityEngine.XR.Hands.XRHandTrackingEvents>();
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);
}
/// <summary>
/// 手部关节数据更新时的回调方法
/// </summary>
/// <param name="eventArgs">关节更新事件参数,包含手部关节数据</param>
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
/// <summary>
/// 左手成功识别到手势不断执行操作
/// </summary>
/// <param name="gestureType">左手手势类型</param>
/// <param name="handForward">左手掌心朝向</param>
public abstract void GestureSuccess();
/// <summary>
/// 左手未识别到手势执行操作
/// </summary>
public abstract void GestureFail();
#endregion
}
#endif
}