Unity 심화 - 플레이어 이동 상태 만들기

Amberjack·2024년 2월 20일
0

Unity

목록 보기
39/44

PlayerStateMachine 수정하기

이동 상태 Walk와 Run을 추가해주기 위해 PlayerStateMachine에 추가해주자.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerStateMachine : StateMachine
{
''' 생략
    // States
    public PlayerIdleState IdleState { get; }
    public PlayerWalkState WalkState { get; }
    public PlayerRunState RunState { get; }

''' 생략

    public PlayerStateMachine(Player player)
    {
        this.Player = player;

        IdleState = new PlayerIdleState(this);
        WalkState = new PlayerWalkState(this);
        RunState = new PlayerRunState(this);

        MainCameraTransform = Camera.main.transform;

        MovementSpeed = player.Data.GroundedData.BaseSpeed;
        RotationDamping = player.Data.GroundedData.BaseRotationDamping;
    }
}

각각 PlayerWalkState와 PlayerRunState를 선언하고 PlayerStateMachine 생성자에서 new를 통해 각각의 상태를 새로 만들어준다.

PlayerBaseState.cs

이제 PlayerStateMachine에 Walk와 Run 상태가 추가되었으니, PlayerBaseState에서 이동을 위한 키 입력 처리를 해주어야 한다.

protected virtual void AddInputActionsCallbacks()
{
    // walk 또는 Run 상태 진입 시의 키 입력을 받아오기 위한 이벤트 구독
    PlayerInput input = stateMachine.Player.Input;
    input.PlayerActions.Movement.canceled += OnMovementCanceled;
    input.PlayerActions.Run.started += OnRunStarted;
}

protected virtual void RemoveInputActionsCallbacks()
{
    // 위에서 Walk, Run 상태 진입 시 구독했던 이벤트 해제하기
    PlayerInput input = stateMachine.Player.Input;
    input.PlayerActions.Movement.canceled -= OnMovementCanceled;
    input.PlayerActions.Run.started -= OnRunStarted;
}

pprotected virtual void OnRunStarted(InputAction.CallbackContext context)
{
    
}

protected virtual void OnMovementCanceled(InputAction.CallbackContext context)
{
    
}

PlayerGroundedState.cs

위에서 정의한 OnMovementCanceled을 override하여 처리해준다.

// Player의 상태가 Ground일 때, 이동 키의 입력을 멈추면 Idle 상태로 진입하게 만든다.
// Air 상태일 때나 Attack 상태일 때는 이동 키의 입력을 멈췄다고 Idle로 변경되면 안되기 때문에 Ground에서 처리해준다.
protected override void OnMovementCanceled(InputAction.CallbackContext context)
{
    if (stateMachine.MovementInput == Vector2.zero) return;

    stateMachine.ChangeState(stateMachine.IdleState);
    base.OnMovementCanceled(context);
}

protected virtual void OnMove()
{
    stateMachine.ChangeState(stateMachine.WalkState);
}

주석에 적혀있듯, Player가 Ground 상태일 때만 이동 키의 입력이 멈췄을 때 Idle로 전환되도록 만들어주기 위해 PlayerGroundedState에서 OnMovementCanceled 처리를 해준다.

PlayerWalkState.cs

using UnityEngine.InputSystem;

public class PlayerWalkState : PlayerGroundedState
{
    public PlayerWalkState(PlayerStateMachine playerStateMachine) : base(playerStateMachine)
    {
    }

    public override void Enter()
    {
        stateMachine.MovementSpeedModifier = groundData.WalkSpeedModifier;
        base.Enter();
        StartAnimation(stateMachine.Player.AnimationData.WalkParameterHash);
    }

    public override void Exit()
    {
        base.Exit();
        StopAnimation(stateMachine.Player.AnimationData.WalkParameterHash);
    }

    protected override void OnRunStarted(InputAction.CallbackContext context)
    {
        base.OnRunStarted(context);
        stateMachine.ChangeState(stateMachine.RunState);
    }
}

Walk는 플레이어가 땅에 있어야 할 수 있도록 PlayerGroundedState를 상속받아준다. 이후 Enter()에서 플레이어의 이동 속도 MovementSpeedModifier를 플레이어의 데이터에 있는 걸을 때 이동 속도로 변경해준다.

그리고 StartAnimation으로 Walk 값을 true로 변경해주어 애니메이션을 실행하게 된다. 이 때, Parameter는 Ground와 Walk 둘다 true인 상태가 된다.

그리고 걷는 와중에 달리기 키가 입력이 들어오면 RunState으로 변경해주기 위한 OnRunStarted를 구현해준다.

PlayerRunState.cs

public class PlayerRunState : PlayerGroundedState
{
    public PlayerRunState(PlayerStateMachine playerStateMachine) : base(playerStateMachine)
    {
    }

    public override void Enter()
    {
        // 플레이어 이동 속도를 달리기 속도로 변경하기
        stateMachine.MovementSpeedModifier = groundData.RunSpeedModifier;
        base.Enter();
        StartAnimation(stateMachine.Player.AnimationData.RunParameterHash);
    }

    public override void Exit()
    {
        base.Exit();
        StopAnimation(stateMachine.Player.AnimationData.RunParameterHash);
    }
}

Walk와 마찬가지로 Run 또한 Ground 상태일 때 가능하도록 PlayerGroundedState를 상속받아준다. Enter()에서 플레이어의 이동 속도를 달리기 속도로 변경을 해준다.

PlayerIdleState.cs 수정하기

플레이어는 Idle 상태에서 Walk, Run으로 상태가 변할 것이기 때문에 이를 위해 코드를 수정해준다.

public override void Update()
{
    base.Update();

    if(stateMachine.MovementInput != Vector2.zero)
    {
        // 이동 처리가 들어왔다면 플레이어의 상태를 Idle에서 Walk로 변경해주기
        OnMove();
        return;
    }
}

확인해보기!

0개의 댓글