using UnityEngine; public class VRInputPoseDetector : MonoBehaviour { [Header("参照")] [SerializeField] private Transform headTransform; [SerializeField] private Transform rightHandTransform; [SerializeField] private Transform leftHandTransform; [Header("判定パラメータ")] [SerializeField] private float minForwardDistance = 0.15f; [SerializeField] private float maxForwardDistance = 0.5f; [SerializeField] private float minHeightOffset = -0.35f; [SerializeField] private float maxHeightOffset = -0.1f; [Header("タイマーパラメータ")] [SerializeField] private float requiredPoseTime = 0.3f; [SerializeField] private float poseExitDelay = 0.15f; [Header("視覚フィードバック")] [SerializeField] private Renderer guideRenderer; [SerializeField] private Color defaultColor = new Color(0.5f, 0.5f, 0.5f, 0.05f); [SerializeField] private Color chargingColor = new Color(1f, 0.8f, 0f, 0.2f); [SerializeField] private Color successColor = new Color(0f, 0.6f, 1f, 0.4f); private float poseTimer; private float exitTimer; public bool IsPosing { get; private set; } private void Update() { if (headTransform == null || rightHandTransform == null || leftHandTransform == null) return; Vector3 localRightHand = headTransform.InverseTransformPoint(rightHandTransform.position); Vector3 localLeftHand = headTransform.InverseTransformPoint(leftHandTransform.position); bool isBothHandsGuarding = CheckHandPosition(localRightHand) && CheckHandPosition(localLeftHand); if (isBothHandsGuarding) { exitTimer = 0f; if (!IsPosing) { poseTimer += Time.deltaTime; if (poseTimer >= requiredPoseTime) { IsPosing = true; } } } else { poseTimer = 0f; if (IsPosing) { exitTimer += Time.deltaTime; if (exitTimer >= poseExitDelay) { IsPosing = false; exitTimer = 0f; } } } UpdateVisualFeedback(isBothHandsGuarding); } private bool CheckHandPosition(Vector3 localHandPos) { bool inForwardRange = localHandPos.z >= minForwardDistance && localHandPos.z <= maxForwardDistance; bool inHeightRange = localHandPos.y >= minHeightOffset && localHandPos.y <= maxHeightOffset; return inForwardRange && inHeightRange; } private void UpdateVisualFeedback(bool isBothHandsGuarding) { if (guideRenderer == null) return; if (IsPosing) { guideRenderer.material.color = successColor; } else if (isBothHandsGuarding) { guideRenderer.material.color = chargingColor; } else { guideRenderer.material.color = defaultColor; } } }