Files
VRProject/Assets/Scripts/VRPunchAttack.cs
2026-07-01 14:08:37 +09:00

149 lines
6.3 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using UnityEngine;
using UnityEngine.InputSystem; // Input Systemを使うために必要
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 = 2.0f; // パンチとして判定する最低速度 (m/s)
[SerializeField] private float damageMultiplier = 10.0f; // ダメージ倍率
[SerializeField] private float hapticAmplitude = 0.5f; // 通常ヒットの振動の強さ
[SerializeField] private float hapticDuration = 0.1f; // 通常ヒットの振動の長さ
[Header("パリィ設定")]
[SerializeField] private float minParrySpeed = 1.0f; // パリィできるパンチとして判定する最低速度 (m/s)
[SerializeField] private float parryStunDuration = 3.0f; // スタン時間(秒)
[SerializeField] private float parryHapticAmplitude = 0.9f; // パリィ成功時の振動の強さ
[SerializeField] private float parryHapticDuration = 0.25f; // パリィ成功時の振動の長さ
// ─────────────────────────────────────────
private void OnEnable()
{
if (velocityAction.action != null)
{
velocityAction.action.Enable();
}
}
private void OnDisable()
{
if (velocityAction.action != null)
{
velocityAction.action.Disable();
}
}
void Start()
{
Rigidbody rb = GetComponent<Rigidbody>();
rb.isKinematic = true;
rb.useGravity = false;
GetComponent<Collider>().isTrigger = true;
}
private void OnTriggerEnter(Collider other)
{
// コントローラーの現在の移動速度を取得
Vector3 velocity = velocityAction.action.ReadValue<Vector3>();
float speed = velocity.magnitude;
//【パリィ判定】当たったオブジェクトが敵の拳だった場合
if (other.CompareTag("EnemyFist"))
{
Debug.Log($"🛡️ [パリィチェック] 敵の拳と接触。プレイヤーの手の速度: {speed:F2} m/s / 構え状態: {poseDetector.IsPosing}");
// 条件構え状態IsPosingである、もしくは、弾くための速度が一定以上出ている場合
if (poseDetector.IsPosing || speed >= minParrySpeed)
{
// 敵の親オブジェクトからEnemyAIスクリプトを検索
EnemyAI enemyAI = other.GetComponentInParent<EnemyAI>();
if (enemyAI != null)
{
// 敵の攻撃コンボを強制中断し、スタン状態にする
enemyAI.TriggerParryStun(parryStunDuration);
// パリィ成功用の強力な振動をプレイヤーに返す
TriggerHaptics(parryHapticAmplitude, parryHapticDuration);
Debug.Log($"🛡️ 【ジャストパリィ成功!】 敵の体勢を崩しました。スタン時間: {parryStunDuration}秒");
return; // パリィが成立した場合は以降のパンチ処理は行わない
}
}
BossController boss = other.GetComponentInParent<BossController>();
if (boss != null)
{
// ボスにパリィ成立を通知(噛みつき・突進中であれば自動でスタンへ移行)
boss.TriggerParryStun();
}
else
{
Debug.Log("🧱 ガード(または速度不足):敵の攻撃は防いだが、弾き返せなかった。");
return;
}
}
// ────────────────────────────────────────────────────────────────────────
// パンチ攻撃の処理
Debug.Log($"[InputSystem接触] {other.name} に触れました。センサー速度: {speed:F2} m/s");
if (speed >= minPunchSpeed)
{
IDamageble damageble = other.GetComponentInParent<IDamageble>();
if (damageble != null)
{
DamageInfo info = new DamageInfo();
// 構えからパンチするとダメージ2倍、ゲージ取得度2倍
if (poseDetector.IsPosing)
{
info.amount = (speed * damageMultiplier) * 2f;
info.isPoseBonus = true;
if (PlayerStatusManager.Instance != null) PlayerStatusManager.Instance.AddGauge(20f);
}
else
{
info.amount = speed * damageMultiplier;
info.isPoseBonus = false;
if (PlayerStatusManager.Instance != null) PlayerStatusManager.Instance.AddGauge(10f);
}
info.hitPosition = other.transform.position;
info.punchDirection = velocity.normalized;
if (PlayerStatusManager.Instance != null)
{
info.amount *= PlayerStatusManager.Instance.CurrentAttackMultiplier;
}
damageble.TakeDamage(info);
Debug.Log($"パンチ成功 ダメージ: {info.amount:F1}");
// 通常ヒットの振動を発生
TriggerHaptics(hapticAmplitude, hapticDuration);
}
}
else
{
Debug.Log($"スピードが足りません。必要: {minPunchSpeed} / 現在: {speed:F2}");
}
}
/// 引数に応じて指定された強さと長さでコントローラーを振動させる
private void TriggerHaptics(float amplitude, float duration)
{
UnityEngine.XR.InputDevice device = InputDevices.GetDeviceAtXRNode(controllerNode);
if (device.isValid)
{
device.SendHapticImpulse(0, amplitude, duration);
}
}
}