UNREAL · 게임 시스템
메인메뉴 버튼을 눌렀는데 아무 일도 안 일어난다
일시정지 메뉴의 ‘메인 메뉴’ 버튼이 눌러도 아무 반응이 없었다. 크래시도 없고 에러 로그도 없다. RPC도 GameMode 핸들러도 다 정상으로 실행되는데 화면만 그대로였다. 범인은 조용히 false를 반환하던 상태 머신이었다.
원인 — 화이트리스트가 전이를 조용히 막았다
세션 상태 머신은 IsLegalTransition() 화이트리스트로 허용된 전이만 통과시킨다. 그런데 일시정지 메뉴는 세션 상태를 멈추지 않고 InGame 그대로 둔다. 그래서 버튼이 요청한 전이는InGame → MainMenu였는데, 화이트리스트엔 InGame → Result만 있었다. 전이가 거부되면서 함수는 false만 돌려주고 아무 로그도 안 남겼다. 그래서 ‘버튼 먹통’이라는 증상과 ‘전이 거부’라는 원인 사이 거리가 멀었다.
해결 — 화이트리스트에 한 줄, 그리고 거부 로그
case ERetrieveSessionState::InGame:
return To == ERetrieveSessionState::Result
|| To == ERetrieveSessionState::MainMenu;허용 전이를 한 줄 추가하니 바로 동작했다. 하지만 진짜 교훈은 그다음이다. 화이트리스트가 거부할 때왜 거부했는지 로그를 남기게 고쳤다. 거부 로그가 있었다면 콜 스택을 다 뒤질 필요 없이 원인을 바로 봤을 거다.
배운 점
화이트리스트 기반 상태 머신은 거부를 반드시 로그로 남겨야 한다. 조용한 false는 증상(먹통 버튼)과 원인(거부된 전이) 사이를 벌려 놓는다.
조용한 실패가 디버깅 비용을 가장 많이 잡아먹는다. RPC·핸들러가 ‘정상 실행’된다고 문제가 없는 게 아니다. 마지막 관문에서 조용히 걸러지는 경우를 의심하라.