개발 노트: 달리기 게임 클래스 6종의 밸런스를 숫자로 확인한 과정
PIXEL RACE 에는 성격이 다른 캐릭터 클래스가 6종 있습니다. 클래스마다 속도와 운이 다르니 어떤 클래스가 유리한지가 늘 문제가 됩니다. 이 글은 "클래스가 공평한가"를 감으로 판단하지 않고 숫자로 확인하려 했던 과정과, 그 과정에서 몇 번 속았던 기록을 정리한 개발 노트입니다. 게임을 만드는 분이 아니어도 "표본이 작은 실험 결과를 어디까지 믿을 수 있나"라는 질문에는 도움이 될 것입니다.
클래스는 어떻게 다른가
각 클래스는 여덟 가지 능력의 배율을 갖습니다. 1.00이 표준이고, 숫자가 클수록 그 능력이 좋습니다. 아래는 그중 눈에 띄는 값만 뽑은 표입니다.
| 클래스 | 기본 속도 | 가속 | 막판 스퍼트 | 아이템 운 | 맷집 | 아이템 회전 | 가하는 충격 |
|---|---|---|---|---|---|---|---|
| 루키 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 | 1.00 |
| 펑크 | 1.05 | 1.32 | 0.96 | 1.00 | 0.92 | 1.00 | 1.05 |
| 쿨가이 | 0.95 | 0.85 | 1.09 | 1.00 | 1.05 | 1.00 | 1.00 |
| 프린세스 | 1.00 | 1.00 | 1.02 | 1.55 | 0.98 | 0.95 | 0.90 |
| 워리어 | 0.995 | 0.95 | 1.01 | 0.90 | 1.52 | 1.05 | 1.16 |
| 레벨 | 0.97 | 1.05 | 1.03 | 1.05 | 0.95 | 1.70 | 1.25 |
설계 방향은 "한 가지가 크게 좋으면 다른 하나는 나쁘게" 입니다. 펑크는 가속이 1.32로 가장 좋지만 막판 스퍼트와 맷집은 표준 이하이고, 쿨가이는 기본 속도와 가속이 낮은 대신 막판 스퍼트가 가장 높습니다. 그런데 이 균형이 실제로 맞는지는 표만 봐서는 알 수 없습니다.
기준은 "평균 순위 3.50"
6명이 달리는 판에서 완전히 공평하다면 어떤 클래스의 평균 순위도 (1+2+3+4+5+6) ÷ 6 = 3.50 이어야 합니다. 평균 순위가 3.50보다 많이 낮으면 유리하고, 높으면 불리합니다. 우승률보다 평균 순위를 보는 이유는 하나입니다. 우승은 6명 중 한 명만 하는 사건이라 표본에서 거의 움직이지 않지만, 평균 순위는 모든 경기에서 값을 얻습니다.
몇 판을 돌려야 믿을 수 있나
한 판의 순위는 1~6 중 하나이고, 완전히 공평한 경우 순위의 표준편차는 √((6²−1)/12) ≈ 1.71 입니다. n경기의 평균 순위가 가진 오차(표준오차)는 여기를 √n 으로 나눈 값입니다.
| 경기 수 | 평균 순위의 표준오차 | 3 표준오차 |
|---|---|---|
| 60 | 0.22 | 0.66 |
| 300 | 0.099 | 0.30 |
| 3000 | 0.031 | 0.094 |
60경기만 돌리면 평균 순위가 3.50에서 ±0.66 이내로 흔들리는 것은 우연입니다. 클래스 사이의 실제 차이는 ±0.2 정도이므로, 60경기는 아예 그 차이를 구분할 수 없습니다. 300경기라도 ±0.3 크기의 차이만 가려내고, 0.1 크기 차이는 3000경기가 되어야 보입니다.
3000경기를 돌려 얻은 기준선
6명 판을 3000경기 돌린 결과입니다(2026년 9월 11일 기록).
| 클래스 | 출전 횟수 | 평균 순위 | 우승 비율 |
|---|---|---|---|
| 펑크 | 3,022 | 3.33 | 19.1% |
| 프린세스 | 2,968 | 3.35 | 19.7% |
| 워리어 | 2,992 | 3.50 | 15.6% |
| 루키 | 3,042 | 3.57 | 14.7% |
| 쿨가이 | 3,000 | 3.61 | 15.9% |
| 레벨 | 2,976 | 3.64 | 14.9% |
3000경기의 3 표준오차는 약 0.09이므로 3.50에서 0.15쯤 벗어난 펑크(3.33)와 프린세스(3.35)는 우연이 아니라 실제로 조금 유리하고, 레벨(3.64)은 조금 불리합니다. 가장 좋은 클래스와 가장 나쁜 클래스의 평균 순위 차이는 약 0.3, 그러니까 한 경기에서 한 계단 차이의 3분의 1 정도입니다. 완벽하게 공평하지는 않지만, 한 클래스가 일방적으로 이기는 수준도 아닙니다.
우승 비율은 균등하게 나누면 6분의 1, 즉 약 16.7%입니다. 가장 높은 클래스가 19.7%, 가장 낮은 클래스가 14.7%로, 그 폭은 5%포인트입니다.
이론값 대신 관측 기준선을 쓴 이유
처음에는 "모든 클래스가 3.50에서 일정 범위 안에 있어야 통과"하는 검사를 만들었습니다. 그런데 이 검사는 게임의 규칙을 건드리지 않은 코드에서도 다섯 번 넘게 실패했습니다. 소리만 바꾼 변경, 테스트 환경에서는 도달할 수 없는 코드를 지운 변경, 심지어 변경이 없는 원본 브랜치에서도 실패했습니다. 재실행하면 통과했습니다.
원인은 이론값 3.50이 실제 값이 아니었기 때문입니다. 위 표에서 보듯 클래스마다 실제 장기 평균은 3.50이 아니라 ±0.2쯤 떨어져 있습니다. 그러니 "3.50에서 얼마나 벗어났나"를 묻는 검사는 처음부터 반쯤 실패하도록 만들어져 있던 셈입니다. 지금은 질문을 바꿨습니다. "이번 변경으로 기준선에서 달라졌는가"를 묻습니다.
- 기준선은 3000경기 결과를 파일로 남겨 두고 비교합니다.
- 허용 범위는 이번 표본의 오차와 기준선의 오차를 함께 반영해 정합니다. 기준선도 표본이기 때문입니다.
- 클래스 6개를 동시에 비교하므로 단일 비교보다 엄격하게, 3 표준오차를 씁니다. 300경기에서 허용 범위는 약 0.31입니다.
- 기준선 자체가 이론값에서 0.40 이상 벗어나면 별도로 실패시킵니다. 공평에서 크게 벗어나는 것은 여전히 막기 위해서입니다.
작은 표본에 속은 기록
1. 지형 폭 조정이 "회귀"로 보였던 일
지형 구간의 폭을 0.045에서 0.030으로 줄였더니, 60경기와 120경기 결과에서 레벨의 평균 순위가 4.13과 3.86으로 나왔습니다. 크게 불리해진 것으로 보여 변경을 되돌렸습니다. 그런데 변경 전후 설정을 각각 300경기로 다시 재 보니 레벨의 평균 순위가 3.65와 3.62로 사실상 같았습니다. 앞의 결과는 표본이 작아서 생긴 우연이었습니다.
2. 아무것도 바꾸지 않은 커밋이 실패한 일
소리와 벽시계 속도만 바꾼 변경에서 프린세스가 3.18로 나와 검사가 실패했습니다. 400경기로 변경 전후를 나눠 비교해 보니 변경 후 3.24와 3.33, 변경 전 3.45와 3.31이었습니다. 차이는 표준오차의 1.5배 정도에 불과했습니다. 게다가 시뮬레이션은 일정한 단위 시간마다 갱신되므로 소리나 벽시계 속도가 순위에 영향을 줄 수 없습니다. 그냥 운이었습니다.
3. 작은 조정을 못 잡는 문제
루키의 기본 속도를 ±8% 바꾸면 평균 순위가 0.47~0.68 움직이고, 300경기 검사가 네 번 모두 실패로 잡아냈습니다. 반면 ±4%(0.2~0.3 이동)는 300경기에서는 네 번 중 한 번만 실패했고, 1000경기로 늘리자 네 번 모두 잡혔습니다. 작은 조정을 확인할 때는 300경기를 통과했다는 사실이 영향이 없다는 뜻이 아닙니다.
이 일에서 얻은 규칙
- 한 번의 실행으로 판단하지 않는다. 실패하면 같은 코드로 다시 돌리고, 표본을 키우고, 의심되는 변경을 되돌려 비교한다.
- 세 가지를 다 하기 전에는 "원인을 찾았다"고 말하지 않는다.
- 필요한 표본 크기를 먼저 계산한다. 0.3 크기의 차이를 보려면 300경기 이상, 0.1이면 3000경기가 필요하다.
- 이론값이 아니라 실제로 관측한 기준과 비교한다.
기록은 화면 속도에 영향받지 않는다
마지막으로 공정성과 관련된 장치 하나. 게임은 화면이 몇 번 그려지든 상관없이 1초에 60번 일정한 단위로만 시뮬레이션을 진행합니다. 그래서 120Hz나 144Hz 모니터에서도 경주 속도가 같고, 완주 기록도 화면 속도가 아니라 시뮬레이션 시간으로 계산합니다. 막판 슬로모션도 화면에 보이는 속도만 늦추기 때문에 결과에는 영향을 주지 않습니다.
이 숫자를 직접 확인하고 싶다면 PIXEL RACE 에서 같은 명단으로 여러 번 돌려 보세요. 스무 판 정도로는 클래스 사이의 차이가 보이지 않는다는 사실부터 체감하게 됩니다.
이 글을 읽고 한 판 해 보고 싶다면 PIXEL RACE 에서 이름만 넣고 바로 시작할 수 있습니다. 가입도 설치도 없습니다.