🤖
1449 in / 1473 out / 2922 total tokens
경마 게임에서 화면상 도착 순서랑 실제 순위가 다르게 나오던 버그를 잡았다. 원인은 슬로우모션 트리거 시점이 서버랑 클라이언트에서 달랐던 것.
클라이언트는 rank === 0으로 미리 정해진 1등을 찾아서 슬로우모션을 걸었다. 근데 서버는 "실제로 앞서가는 말"을 기준으로 판정한다. 게다가 위치 계산도 달랐다. 클라이언트는 말의 왼쪽 끝(currentPos), 서버는 오른쪽 끝(currentPos + visualWidth)을 기준으로 거리를 계산했다.
이게 ~60px(약 6m) 차이를 만들어서, 클라이언트가 서버보다 늦게 슬로우모션에 진입했다. 그 사이에 위치가 뒤죽박죽. 결승 구간에서 순위가 뒤집히는 현상이 발생한 것이다.
수정은 간단했다. 서버와 동일하게 unfinished 말들 중 실제 위치 선두를 찾고, 오른쪽 끝 기준으로 거리 계산. 슬로우모션 진입/해제 타이밍이 서버 판정과 정확히 일치하게 했다.
// 서버와 동일: 아직 결승하지 않은 말 중 실제 선두 찾기
const leader = horseStates
.filter(s => !s.finishJudged)
.reduce((a, b) => a.currentPos > b.currentPos ? a : b);
if (leader && leader.currentPos + visualWidth >= finishLine - 30) {
slowMotionTriggered = true;
}UE5 하다가 웹 게임 만지려니 이런 동기화 이슈가 은근히 빡친다. 서버-클라이언트 판정 로직은 무조건 문서화하고 공유해야 하는데, 혼자 만드는 프로젝트라 그냥 머릿속에만 있어서 이런 걸 자주 놓친다.
클라이언트 판정 로직은 서버랑 같은 기준으로 작성하자. '당연히 이렇겠지' 하고 짜면 100% 다르다.