using UnityEngine; using UnityEngine.InputSystem; using UnityEngine.XR; [RequireComponent(typeof(Collider))] [RequireComponent(typeof(Rigidbody))] public class VRInputPunch : MonoBehaviour { [SerializeField] private InputActionProperty velocityAction; [SerializeField] private XRNode controllerNode = XRNode.RightHand; [SerializeField] private VRInputPoseDetector poseDetector; [Header("パンチパラメータ")] [SerializeField] private float minPunchSpeed = 1.0f; [SerializeField] private float damageMultiplier = 10.0f; [SerializeField] private float hapticAmplitude = 0.5f; [SerializeField] private float hapticDuration = 0.1f; [Header("パリィパラメータ")] [SerializeField] private float parryStunDuration = 3.0f; [SerializeField] private float parryHapticAmplitude = 0.9f; [SerializeField] private float parryHapticDuration = 0.25f; private const string EnemyFistTag = "EnemyFist"; private void OnEnable() { if (velocityAction.action != null) velocityAction.action.Enable(); } private void OnDisable() { if (velocityAction.action != null) velocityAction.action.Disable(); } private void Start() { Rigidbody rb = GetComponent(); rb.isKinematic = true; rb.useGravity = false; GetComponent().isTrigger = true; } private void OnTriggerEnter(Collider other) { Vector3 velocity = velocityAction.action != null ? velocityAction.action.ReadValue() : Vector3.zero; float speed = velocity.magnitude; if (other.CompareTag(EnemyFistTag)) { if (poseDetector != null && poseDetector.IsPosing) { if (TryProcessParry(other)) return; } } if (speed >= minPunchSpeed) { ProcessPunchAttack(other, speed, velocity); } } private bool TryProcessParry(Collider other) { EnemyAI enemyAI = other.GetComponentInParent(); if (enemyAI != null) { enemyAI.TriggerParryStun(parryStunDuration); TriggerHaptics(parryHapticAmplitude, parryHapticDuration); return true; } BossController boss = other.GetComponentInParent(); if (boss != null && boss.TriggerParryStun()) { TriggerHaptics(parryHapticAmplitude, parryHapticDuration); return true; } return false; } private void ProcessPunchAttack(Collider other, float speed, Vector3 velocity) { IDamageable damageable = other.GetComponentInParent(); if (damageable == null) return; bool isPosing = poseDetector != null && poseDetector.IsPosing; DamageInfo info = new DamageInfo { amount = speed * damageMultiplier * (isPosing ? 2f : 1f), isPoseBonus = isPosing, hitPosition = other.transform.position, punchDirection = velocity.normalized }; if (PlayerStatusManager.Instance != null) { PlayerStatusManager.Instance.AddGauge(isPosing ? 20f : 10f); info.amount *= PlayerStatusManager.Instance.Buffs.CurrentAttackMultiplier; } damageable.TakeDamage(info); TriggerHaptics(hapticAmplitude, hapticDuration); } private void TriggerHaptics(float amplitude, float duration) { // 明示的に UnityEngine.XR.InputDevice と指定して型衝突を回避 UnityEngine.XR.InputDevice device = InputDevices.GetDeviceAtXRNode(controllerNode); if (device.isValid) { device.SendHapticImpulse(0, amplitude, duration); } } }