using UnityEngine; using UnityEngine.Serialization; // 入力に応じたPlayerの行動と状態遷移を管理する [RequireComponent(typeof(DamageReceiver))] [RequireComponent(typeof(HitReaction))] public class PlayerController : MonoBehaviour { [Tooltip("Playerの現在の状態")] [SerializeField] private PlayerState state = PlayerState.Idle; [Tooltip("Playerの移動処理")] [SerializeField] private PlayerMove playerMove; [Tooltip("カメラの回転処理")] [SerializeField] private CameraMove cameraMove; [FormerlySerializedAs("playerAttack")] [Tooltip("Playerの攻撃処理")] [SerializeField] private CharacterAttack characterAttack; private InputSystem_Actions _inputActions; private DamageReceiver _damageReceiver; private HitReaction _hitReaction; private bool _controlEnabled = true; public PlayerState State => state; // 入力と状態判定に必要なオブジェクトを準備する private void Awake() { _inputActions = new InputSystem_Actions(); _damageReceiver = GetComponent(); _hitReaction = GetComponent(); } // Player用Input Actionを有効にする private void OnEnable() { _inputActions.Player.Enable(); _damageReceiver.Died += OnDied; } // Player用Input Actionを無効にする private void OnDisable() { _damageReceiver.Died -= OnDied; _inputActions.Player.Disable(); } // ゲーム状態に応じて入力と進行中の攻撃だけを停止・再開する public void SetControlEnabled(bool controlEnabled) { _controlEnabled = controlEnabled; if (controlEnabled) return; characterAttack.CancelAttack(); if (state != PlayerState.Dead) SetState(PlayerState.Idle); } // 入力と優先度に従って状態を更新し、現在可能な行動を実行する private void Update() { if (state == PlayerState.Dead || !_controlEnabled) return; var moveInput = _inputActions.Player.Move.ReadValue(); var lookInput = _inputActions.Player.Look.ReadValue(); cameraMove.Look(lookInput); if (_hitReaction.IsReacting) { SetState(PlayerState.Damage); return; } if (characterAttack.IsAttacking) { SetState(PlayerState.Attack); return; } if (_inputActions.Player.Attack.WasPressedThisFrame()) { characterAttack.Attack(); if (characterAttack.IsAttacking) { SetState(PlayerState.Attack); return; } } var forward = cameraMove.PlanarForward; var right = cameraMove.PlanarRight; var direction = forward * moveInput.y + right * moveInput.x; direction = Vector3.ClampMagnitude(direction, 1f); playerMove.Move(direction); SetState( direction == Vector3.zero ? PlayerState.Idle : PlayerState.Move); } // 死亡通知を受けた時点で、入力処理とは独立して死亡状態へ遷移する private void OnDied() { characterAttack.CancelAttack(); SetState(PlayerState.Dead); } // 現在の状態を指定された状態へ変更する private void SetState(PlayerState nextState) { if (state == nextState) return; state = nextState; } }