using System.Collections.Generic; using UnityEngine; public enum State { IDLE, MOVE, JUMP, Attack, Damaged, Dead } public class StateMachine { private IState _state; private State _currentState; private PlayerMove _player; // PlayerMove 인스턴스를 저장 private Dictionary _states = new Dictionary(); public StateMachine(State state, PlayerMove player) { _player = player; // PlayerMove 인스턴스 저장 _states.Add(State.IDLE, new IdleState(player)); _states.Add(State.MOVE, new MoveState(player)); _states.Add(State.JUMP, new JumpState(player)); _states.Add(State.Attack, new AttackState(player)); _states.Add(State.Dead, new DeadState(player)); _currentState = state; _state = _states[state]; _state.Enter(); } public void Update() { _state.Update(); State newState = _state.CheckTransition(); if (_currentState != newState) { _state.Exit(); SetTransition(newState); } } // 오버로드된 SetTransition 메서드 추가 public void SetTransition(State state, Vector2 targetPosition) { _currentState = state; _state = new DamagedState(_player, targetPosition); // _player 변수 사용 _state.Enter(); } public void SetTransition(State state) { _currentState = state; _state = _states[state]; _state.Enter(); } } public interface IState { void Enter(); void Update(); void Exit(); State CheckTransition(); } public class IdleState : IState { private static readonly int IsMoving = Animator.StringToHash("isMoving"); private static readonly int IsJumping = Animator.StringToHash("isJumping"); private PlayerMove _player; public IdleState(PlayerMove player) { _player = player; } public void Enter() { _player.Animator.SetBool(IsMoving, false); _player.Animator.SetBool(IsJumping, false); } public void Update() { } public void Exit() { } public State CheckTransition() { if (_player.Inputs.Jump) { return State.JUMP; } // 수정: 좌우 어느 방향으로든 입력이 있을 때 MOVE 상태로 전환 if (_player.Inputs.Move != Vector2.zero) { return State.MOVE; } if (_player.Inputs.Attack) { return State.Attack; } return State.IDLE; } } public class MoveState : IState { private static readonly int IsMoving = Animator.StringToHash("isMoving"); private PlayerMove _player; public MoveState(PlayerMove player) { _player = player; } public void Enter() { _player.Animator.SetBool(IsMoving, true); } public void Update() { float horizontalInput = _player.Inputs.Move.x; if (horizontalInput != 0) { Vector3 newScale = _player.transform.localScale; newScale.x = horizontalInput > 0 ? -1f : 1f; _player.transform.localScale = newScale; } _player.RigidBody.AddForce(Vector2.right * horizontalInput * _player.maxSpeed, ForceMode2D.Force); if (Mathf.Abs(_player.RigidBody.linearVelocity.x) > _player.maxSpeed) { _player.RigidBody.linearVelocity = new Vector2(Mathf.Sign(_player.RigidBody.linearVelocity.x) * _player.maxSpeed, _player.RigidBody.linearVelocity.y); } } public void Exit() { _player.Animator.SetBool(IsMoving, false); } public State CheckTransition() { if (_player.Inputs.Jump) { return State.JUMP; } if (_player.Inputs.Move == Vector2.zero) { return State.IDLE; } if (_player.Inputs.Attack) { return State.Attack; } return State.MOVE; } } public class JumpState : IState { private static readonly int IsJumping = Animator.StringToHash("isJumping"); private PlayerMove _player; public JumpState(PlayerMove player) { _player = player; } public void Enter() { _player.RigidBody.AddForce(Vector2.up * _player.jumpPower, ForceMode2D.Impulse); _player.Animator.SetBool(IsJumping, true); } public void Update() { float horizontalInput = _player.Inputs.Move.x; if (horizontalInput != 0) { Vector3 newScale = _player.transform.localScale; newScale.x = horizontalInput > 0 ? -1f : 1f; _player.transform.localScale = newScale; } } public void Exit() { _player.Animator.SetBool(IsJumping, false); } public State CheckTransition() { if (_player.Inputs.Attack) { return State.Attack; } if (_player.RigidBody.linearVelocity.y < 0) { Debug.DrawRay(_player.RigidBody.position, Vector3.down, Color.green); RaycastHit2D rayHit = Physics2D.Raycast(_player.RigidBody.position, Vector3.down, 1, LayerMask.GetMask("Platform")); if (rayHit.collider != null && rayHit.distance < 0.7f) { return State.IDLE; } } return State.JUMP; } } public class AttackState : IState { private PlayerMove _player; private float _attackDuration = 0.5f; // 공격 지속 시간 private float _attackStartTime; public AttackState(PlayerMove player) { _player = player; } public void Enter() { // 애니메이션 없이 오브젝트만 활성화 _player.attackCollider.gameObject.SetActive(true); _attackStartTime = Time.time; } public void Update() { float horizontalInput = Input.GetAxisRaw("Horizontal"); if (horizontalInput != 0) { Vector3 newScale = _player.transform.localScale; newScale.x = horizontalInput > 0 ? -1f : 1f; _player.transform.localScale = newScale; } } public void Exit() { _player.attackCollider.gameObject.SetActive(false); } public State CheckTransition() { if (Time.time >= _attackStartTime + _attackDuration) { return State.IDLE; } return State.Attack; } } public class DamagedState : IState { private PlayerMove _player; private float _invincibilityTime = 1f; private float _damagedStartTime; private Vector2 _targetPosition; public DamagedState(PlayerMove player, Vector2 targetPosition) { _player = player; _targetPosition = targetPosition; } public void Enter() { _player.hp--; Debug.Log("플레이어가 맞았습니다. 현재 HP: " + _player.hp); _player.gameObject.layer = LayerMask.NameToLayer("PlayerDamaged"); _player.SpriteRenderer.color = new Color(1, 1, 1, 0.5f); _damagedStartTime = Time.time; int direction = (_player.transform.position.x - _targetPosition.x) > 0 ? 1 : -1; _player.RigidBody.AddForce(new Vector2(direction * 5f, 0f), ForceMode2D.Impulse); } public void Update() { } public void Exit() { _player.gameObject.layer = LayerMask.NameToLayer("Player"); _player.SpriteRenderer.color = new Color(1, 1, 1, 1); } public State CheckTransition() { if (_player.hp <= 0) { return State.Dead; } if (Time.time >= _damagedStartTime + _invincibilityTime) { return State.IDLE; } return State.Damaged; } } public class DeadState : IState { private PlayerMove _player; public DeadState(PlayerMove player) { _player = player; } public void Enter() { Debug.Log("플레이어 사망"); _player.Die(); } public void Update() { // 사망 상태에서는 어떤 로직도 수행하지 않습니다. } public void Exit() { } public State CheckTransition() { // 사망 상태에서는 전환이 없습니다. return State.Dead; } }