오늘은 GetFruit 미니게임에서 드론이 혼자 움직이는 버그를 해결했다.
처음엔 isFlap 값이 잘못 들어간 줄 알았는데, 결국 원인은 중력과 상태 관리 구조였다.
포탈을 통해 미니게임으로 들어갈 때 드론이 대각선 방향으로 계속 떠오르는 현상이 있었다.
처음엔 “플랩이 자동으로 눌리는 건가?” 싶었는데 로그를 찍어보니 isFlap은 한 번도 호출되지 않았다.
원인은 단순했다.
중력이 꺼져 있어서 기존 이동 힘이 그대로 남아있던 것.
velocity가 유지된 채로 씬만 전환되니까 중력 없이 그 방향으로 계속 밀려가고 있었던 것이다.
그래서 미니게임 진입 시 Rigidbody2D 값을 전부 리셋하도록 수정했다.
var playerRb = _player.GetComponent<Rigidbody2D>();
playerRb.gravityScale = 1f; // 중력 다시 켜기
playerRb.velocity = Vector2.zero; // 남은 힘 제거
playerRb.angularVelocity = 0f; // 회전값 초기화
변경 후에는 어떤 상태로 들어가도 항상 같은 조건에서 시작된다.
처음엔 아래처럼 여러 bool로 상태를 나누었다.
bool _isPrepare;
bool _isReady;
bool _isStart;
bool _isDead;
int _deadCount;
이렇게 여러 bool 값으로 관리를 하게 되니,
어떤 타이밍에 true로 바꿔야 하는지 계속 헷갈리고,
한쪽이 켜진 채로 다른 쪽이 안 꺼져 있어서 혼자 알아서 시작하는 버그도 발생했다.
OnReady()랑 StartGame()이 같은 프레임에 호출되면서 Ready → Start가 한 번에 넘어가는 일도 있었다.
결국 bool을 전부 없애고 enum으로 바꿨다.
public enum MiniGameState
{
Stop, // 초기 상태
Ready, // 준비 완료
Start, // 실제 시작
Dead, // 사망
End // 종료
}
이제 CurrentState 하나로 전부 관리한다.
protected virtual void Update()
{
if (_controller == null) return;
if (CurrentState is MiniGameState.Stop && CheckStartInput())
{
OnReady();
}
else if (CurrentState is MiniGameState.Ready && CheckStartInput())
{
StartGame();
}
else if (CurrentState is MiniGameState.Start)
{
OnPlaying();
}
}
if 대신 else if로 바꿔서
Ready → Start로 바로 넘어가는 문제도 같이 해결됐다.
| 구분 | 변경 전 | 변경 후 |
|---|---|---|
| 상태 관리 | 여러 bool 조합 | enum 단일 상태 |
| 흐름 제어 | 꼬이기 쉬운 분기 | 명확한 상태 전이 |
| 버그 발생 | Ready→Start 동시 실행 | 단계별 실행 |
| 가독성 | 낮음 | 높음 |
이번 문제는 단순한 버그가 아니라 구조 문제였다.
씬이 바뀌더라도 물리 상태(velocity, gravityScale)는 남아있고,
bool로 나눈 상태는 언제든 꼬일 수 있다.
해결책은 아래와 같다.
enum 하나로 관리 이제는 흐름이 한눈에 보이고,
Ready → Start → Dead → End까지 전이 구조도 명확해졌다.