티스토리 뷰
드디어 StateMachine을 제대로 적용해봤다. 이해하고 적용하는데 시간이 좀 걸렸지만 코드가 훨씬 깔끔해졌고 확실히 유지보수에 용이할 것 같다!
💻 Unity
Velocity
- Rigidbody.velocity는 물체의 현재 속도를 나타내는 벡터
- 이 벡터는 방향 + 속도의 크기를 함께 가지고 있다
- 예: (1, 0, 0)이면 x축 방향으로 1 단위 속도로 움직이는 중
- 단위는 미터/초(m/s)
Rigidbody rb = GetComponent<Rigidbody>();
void Update()
{
float move = Input.GetAxis("Horizontal");
rb.velocity = new Vector3(move * 5f, rb.velocity.y, 0f);
}
주의사항
Rigidbody 필수 | velocity는 Rigidbody가 있어야 작동 (2D면 Rigidbody2D.velocity) |
직접 제어 | velocity를 직접 설정하면, 힘이나 중력의 영향보다 우선. 즉, 순간 이동처럼 작동할 수 있다 |
이동 제어 | Translate()와 달리, velocity는 물리 연산과 충돌 감지를 포함하므로 자연스럽게 움직인 |
🕹️ 실습 (2D 횡스크롤 2)
StateMachine으로 Player 애니메이션 구현

현재 상태 | 조건 | 전환 상태 |
PlayerIdleState | 이동 입력이 있을 때 | PlayerMoveState |
점프 입력이 있을 때 | PlayerJumpState | |
대시 입력이 있을 때 | PlayerDashState | |
PlayerMoveState | 이동 입력이 없을 때 | PlayerIdleState |
점프 입력이 있을 때 | PlayerJumpState | |
대시 입력이 있을 때 | PlayerDashState | |
PlayerJumpState | 공중에 있을 때 | PlayerAirState |
착지했을 때 | PlayerIdleState 또는 PlayerMoveState | |
PlayerAirState | 착지했을 때 | PlayerIdleState 또는 PlayerMoveState |
PlayerDashState | 대시가 끝났을 때 | PlayerIdleState 또는 PlayerMoveState |
📝 과제
벽타기 구현

// Player.cs
public bool IsWallDetected() // 추가
{
return Physics2D.Raycast(wallCheck.position, Vector2.right, wallCheckDistance * facingDir, whatIsGround);
}
private void OnDrawGizmos()
{
Gizmos.DrawLine(groundCheck.position, new Vector3(groundCheck.position.x, groundCheck.position.y - groundCheckDistance));
Gizmos.DrawLine(wallCheck.position, new Vector3(wallCheck.position.x + wallCheckDistance * facingDir, wallCheck.position.y)); // 수정
}
public void Flip()
{
facingDir = facingDir * -1;
isFacingRight = !isFacingRight;
transform.Rotate(0, 180, 0);
}
public class PlayerAirState : PlayerState
{
public PlayerAirState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName)
: base(_player, _stateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Update()
{
base.Update();
if (player.IsGroundDetected())
{
stateMachine.ChangeState(player.idleState);
}
if (player.IsWallDetected()) // 추가
{
stateMachine.ChangeState(player.hangingState);
}
}
public override void Exit()
{
base.Exit();
}
}
public class PlayerHangingState : PlayerState
{
public PlayerHangingState(Player _player, PlayerStateMachine _stateMachine, string _animBoolName)
: base(_player, _stateMachine, _animBoolName)
{
}
public override void Enter()
{
base.Enter();
}
public override void Update()
{
base.Update();
player.SetVelocity(rb.linearVelocityX, Mathf.Max(rb.linearVelocityY, -player.slideSpeed));
if (Input.GetKeyDown(KeyCode.Space))
{
float jumpDirection = player.facingDir * -1;
rb.linearVelocity = new Vector2(jumpDirection * player.moveSpeed, player.jumpForce);
player.Flip();
stateMachine.ChangeState(player.jumpState);
}
if (!player.IsWallDetected() && !player.IsGroundDetected())
{
stateMachine.ChangeState(player.airState);
}
if (player.IsGroundDetected())
{
stateMachine.ChangeState(player.idleState);
}
}
public override void Exit()
{
base.Exit();
}
}
느리게 슬라이딩
player.SetVelocity(rb.linearVelocityX, Mathf.Max(rb.linearVelocityY, -player.slideSpee
플레이어가 벽에 매달려 있을 때, 중력에 의해 rb.linearVelocityY는 점점 음수로 커진다 (예: -1, -2, -3, ...)
하지만 Mathf.Max(rb.linearVelocityY, -player.slideSpeed) y축 속도가 -player.slideSpeed보다 더 음수(더 빠르게 떨어지는 값)가 되지 않도록 제한한다
반대 방향으로 점프
if (Input.GetKeyDown(KeyCode.Space))
{
float jumpDirection = player.facingDir * -1;
rb.linearVelocity = new Vector2(jumpDirection * player.moveSpeed, player.jumpForce);
player.Flip();
stateMachine.ChangeState(player.jumpState);
}
현재 벽을 바라보는 방향에서 반대 방향으로 가속을 준 후 Flip한 후 점프 동작으로 전환한다
'Unity > 멋쟁이사자처럼' 카테고리의 다른 글
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 33일차 회고 (0) | 2025.04.09 |
---|---|
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 32일차 회고 (0) | 2025.04.09 |
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 30일차 회고 (0) | 2025.04.04 |
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 29일차 회고 (0) | 2025.04.03 |
멋쟁이 사자처럼 부트캠프 유니티 게임 개발 4기 28일차 회고 (0) | 2025.04.03 |