만드는 원리

물리 엔진으로 경주를 만들면 생기는 불공정, 시뮬레이션으로 잡기

주사위와 구슬 경주는 결과를 미리 정하지 않습니다. 대신 '판'이 공정한지 수천 번 돌려서 확인해요.

2026.10.09 · 한그릇 공작소

사다리와 룰렛은 결과를 먼저 정하고 그림을 맞춘다고 앞 글에서 썼어요. 주사위와 구슬 경주는 반대입니다. 물리 엔진이 실제로 굴리고, 멈춘 결과를 그대로 씁니다. 그렇게 하면 보는 재미는 커지는데, 공정한지 확인하는 방법이 완전히 달라져요.

쓰는 도구

화면은 three.js(3D 그래픽), 물리는 cannon-es(충돌·중력 계산)를 씁니다. 둘 다 무료 공개 라이브러리고, 페이지에 처음 들어왔을 때가 아니라 주사위 모드를 눌렀을 때 불러와서 첫 화면을 무겁게 만들지 않았어요.

주사위: 윗면을 어떻게 읽나

주사위를 던지고 나면 물리 엔진은 "이 상자가 이 방향으로 돌아가 있다"는 회전값만 알려 줍니다. 몇이 나왔는지는 직접 계산해야 해요.

  1. 주사위의 여섯 면이 처음에 어느 방향을 보고 있었는지 표로 적어 둡니다. (1은 위, 6은 아래… 이런 식)
  2. 멈춘 뒤 회전값을 각 면 방향에 적용해서, 지금 하늘을 가장 똑바로 보고 있는 면을 찾습니다.
  3. 그 면의 숫자가 결과예요.

가끔 주사위가 벽에 기대 모서리로 서는 일이 있어요. 그럴 땐 "가장 위를 보는 면"이 애매하니까, 면이 충분히 평평하지 않으면 살짝 툭 건드려서 다시 눕힙니다. 진짜 주사위 판에서도 그렇게 하잖아요.

멈춤 판정도 신경 써야 합니다. 물리 엔진이 "이 물체 잠들었음" 표시를 해 주긴 하는데, 미세하게 떨리면서 한참 안 잠들 때가 있어요. 그래서 속도가 아주 작아지면 멈춘 걸로 보는 조건을 하나 더 뒀습니다.

구슬 경주: 가장자리가 유리했다

구슬 경주는 구슬 여러 개를 위에서 떨어뜨려 장애물을 지나 먼저 바닥에 닿는 순서를 겨루는 도구예요. 만들고 나서 몇 판 해 보니 이상하게 양 끝 줄에서 출발한 구슬이 자주 이겼습니다.

눈으로 몇 판 본 걸로는 확신할 수 없어서, 화면 없이 물리 계산만 빠르게 돌리는 시험 장치를 만들었어요. 맵마다 수백 판을 돌리고 우승 구슬이 어디서 출발했는지 셌습니다.

가장자리 출발 구슬의 우승 비율
수정 전60~86%
수정 후12~32%

원인은 단순했어요. 가장자리 구슬은 벽을 타고 미끄러져 내려가면서 장애물을 거의 안 만났습니다. 가운데 구슬만 못에 부딪히며 지그재그로 내려오고요.

몇 가지를 시도했는데 대부분 실패했습니다. 벽에 못을 박으면 구슬이 끼어서 안 내려왔고, 벽에 턱을 만들면 경주 시간이 두 배로 늘었어요. 결국 효과가 있었던 건 벽 근처에 보이지 않는 "튕겨 내는 구역"을 두는 방법이었습니다. 구슬이 벽에 붙으면 안쪽으로 살짝 밀어 줘요. 같은 구슬이 그 구역과 장애물 사이에서 계속 핑퐁 하는 일이 생겨서, 한 번 밀린 구슬은 1초 동안은 다시 안 밀리게 했습니다.

수정 후에는 가장자리 출발 구슬의 우승 비율이 전체 평균과 비슷해졌어요. 한 판 걸리는 시간도 23~30초 안쪽으로 맞췄습니다.

물리 결과가 공정하다는 걸 어떻게 말하나

룰렛은 "확률 1/n"이라고 계산으로 말할 수 있지만, 물리 경주는 그렇게 못 합니다. 대신 판 자체가 특정 위치에 유리하지 않은지를 많이 돌려 보고 확인하는 수밖에 없어요. 출발 순서도 매번 무작위로 섞으니, 판이 고르기만 하면 사람마다 확률은 같아집니다.

맵을 새로 만들거나 튕김 세기를 바꿀 때마다 이 시험을 다시 돌립니다. 손맛 좋게 바꾼 설정이 공정함을 깨는 일이 생각보다 자주 있었거든요.

직접 해 보기: 주사위 굴리기 · 구슬 경주 · 동물 경주