1) 움직이는 상태의 PlayerStateMove
public class PlayerStateMove : PlayerStateGrounded
{
public PlayerStateMove(PlayerController inController, PlayerStateMachine inStateMachine, string inParamName)
: base(inController, inStateMachine, inParamName)
{
}
// State에 돌입
public override void Enter()
{
base.Enter();
}
// State에서 탈출
public override void Exit()
{
base.Exit();
}
// State에서 매 프레임마다 진행
public override void Update()
{
base.Update();
_controller.SetVelocity(_xInput * _controller._moveSpeed, _rigidbody2D.velocity.y);
if (_xInput == 0 || _controller.DoDetectIsFacingWall())
_stateMachine.ChangeState(_controller._idleState);
}
}
PlayerStateMove의 경우 발을 딛고있는 상태에서 수행해야 하므로
PlayerStateGrounded로부터 상속이 이뤄집니다.
Update함수에서는
매 프레임마다 Player의 속도를 설정하고
만약 x축 입력이 들어오지 않거나 플레이어가 벽을 마주한다면
Player의 CurrentState를 PlayerStateIdle로 변경합니다.
2) 점프하는 상태의 PlayerStateJump
public class PlayerStateJump : PlayerState
{
public PlayerStateJump(PlayerController inController, PlayerStateMachine inStateMachine, string inParamName)
: base(inController, inStateMachine, inParamName)
{
}
public override void Enter()
{
base.Enter();
_controller.SetVelocity(_rigidbody2D.velocity.x, _controller._jumpForce);
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if (_rigidbody2D.velocity.y < 0)
_stateMachine.ChangeState(_controller._inAirState);
}
}
PlayerStateJump로 처음 진입하여 Enter 함수가 호출되면
설정한 JumpForce의 값만큼 Player에게 가속도를 부여합니다.
그리고 Update 문에서는 Player의 y축 가속도 값을 읽어서 가속도가 0보다 작다면,
즉 떨어지는 중이라면 Player의 CurrentState를 공중에 떠 있는 PlayerStateInAir로 교체합니다.
3) 공중에 떠 있는 상태의 PlayerStateInAir
public class PlayerStateInAir : PlayerState
{
public PlayerStateInAir(PlayerController inController, PlayerStateMachine inStateMachine, string inParamName)
: base(inController, inStateMachine, inParamName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Exit()
{
base.Exit();
}
public override void Update()
{
base.Update();
if (_controller.DoDetectIsFacingWall())
_stateMachine.ChangeState(_controller._wallSlideState);
if (_controller.DoDetectIsGrounded())
_stateMachine.ChangeState(_controller._idleState);
if (_xInput != 0)
_controller.SetVelocity(_controller._moveSpeed * 0.8f * _xInput, _rigidbody2D.velocity.y);
}
}
PlayerStateInAir의 Update 함수에서는
다음의 3가지를 체크합니다.
우선, 벽과 닿아있는 경우 Player의 CurrentState를 벽에서 미끄러져 내리는 PlayerStateWallSlide로 교체합니다.
그리고 땅과 닿아있는 경우 Player의 CurrentState를 PlayerStateIdle로 교체합니다.
마지막으로 현재 상태에서 x축으로 입력이 들어온다면
0.8의 값을 곱하여 약간 체공하여 떨어지는 느낌을 부여합니다.
4) 대쉬 상태의 PlayerStateDash
public class PlayerStateDash : PlayerState
{
public PlayerStateDash(PlayerController inController, PlayerStateMachine inStateMachine, string inParamName)
: base(inController, inStateMachine, inParamName)
{
}
// State에 돌입
public override void Enter()
{
base.Enter();
_stateTimer = _controller._dashDuration;
}
// State에서 탈출
public override void Exit()
{
base.Exit();
_controller.SetVelocity(0, _rigidbody2D.velocity.y);
}
// State에서 매 프레임마다 진행
public override void Update()
{
base.Update();
if (!_controller.DoDetectIsGrounded() && _controller.DoDetectIsFacingWall())
_stateMachine.ChangeState(_controller._wallSlideState);
_controller.SetVelocity(_controller._dashSpeed * _controller._dashDir, 0);
if (_stateTimer < 0.0f)
_stateMachine.ChangeState(_controller._idleState);
}
}
PlayerStateDash에서는 위와 같은 로직을 수행합니다.
State에 돌입하는 Enter에서는 먼저 State들이 사용하는 타이머인 _stateTimer를 초기화합니다.
State에서 탈출하는 Exit의 경우 Player의 속도를 설정하되,
x값을 0으로 주어 직선으로 떨어지도록 합니다.
마지막으로 Update 에서는 다음의 로직을 수행합니다.
만약, 땅을 딛고 있지 않고 벽을 마주하는 상황이라면
벽에 달라붙는 PlayerStateWallSlide로 CurrentState를 교체합니다.
대쉬하는 동안은 Player에게 가속도를 부여하되 높이는 변하지 않도록 y값을 0으로 줍니다.
만약 _stateTimer가 0보다 작다면,
즉 대쉬시간이 끝났다면 Player의 CurrentState를 PlayerStateIdle로 교체합니다.
'유니티 > 게임 프로젝트' 카테고리의 다른 글
2D RPG - (6) Tilemap을 통한 배경 그리기 + Cinemachine (0) | 2024.12.11 |
---|---|
2D RPG - (5) StateMachine의 구성과 완성 (마지막) (0) | 2024.12.09 |
2D RPG - (3) StateMachine의 구성과 완성 (2) (0) | 2024.12.09 |
2D RPG - (2) StateMachine의 구성과 완성 (1) (0) | 2024.12.08 |
2D RPG - (1) StateMachine의 설계 (0) | 2024.11.25 |