점프 버튼을 누르는 시점도, 캐릭터의 초기 속도도 동일한데 프레임레이트만 바꿨더니 점프 높이가 변하는 일이 종종 있습니다.
물리 엔진의 버그인지 계산 방식의 문제인지 궁금해져서 같은 점프를 세 가지 방식으로 짜서 30프레임부터 240프레임까지 시뮬레이션을 돌려봤습니다. 정답이 2.00m인 점프가 어떤 조건에서는 2.17m, 어떤 조건에서는 1.83m까지 나오게됐는데요. 아래에서 정확히 확인해보는 시간을 가져보겠습니다.
2.1m 턱을 넘는 프레임레이트
점프의 초기 속도는 10m/s, 중력은 25m/s²로 가정했습니다. 이 값이면 정확한 최고점은 2.00m이고, 다시 땅에 닿기까지 0.8초가 걸리게 되죠. 위치를 먼저 갱신하는 코드로 돌리면 최고점이 30프레임에서 2.167m, 60프레임에서 2.083m, 144프레임에서 2.035m, 240프레임에서 2.021m였어요.
여기에 높이 2.1m짜리 턱을 세워 보면 결과가 갈리게 됩니다. 30프레임에서는 2.167m라서 턱을 넘고, 60프레임에서는 2.083m라서 17mm가 모자라 넘지 못합니다. 맵도 입력도 그대로인데 프레임레이트 하나로 갈 수 있는 길이 달라진 것이라고 할 수 있습니다.
점프 코드 3가지
같은 점프라도 매 프레임 속도와 위치를 갱신하는 순서에 따라 결과가 달라집니다.
첫 번째는 위치에 속도×프레임 간격을 먼저 더하고 그다음에 속도를 깎는 방식인데요.
두 번째는 순서를 뒤집어 속도를 먼저 깎은 뒤 새 속도로 위치를 플러스합니다.
세 번째는 등가속도 운동 공식을 써서 위치에 속도×간격에서 중력×간격²의 절반을 뺀 값을 더해주고요. 앞의 둘은 오일러 계열이고, 세 번째는 중력이 일정할 때 오차가 생기지 않는 방식입니다.
오차는 v0·dt/2였습니다
위치를 먼저 갱신하는 방식은 최고점이 항상 정답보다 높았고, 속도를 먼저 갱신하는 방식은 항상 낮았는데요. 오차 크기는 초기 속도×프레임 간격÷2와 정확히 맞아떨어졌습니다.
60프레임이면 10×(1/60)÷2로 약 0.083m이고, 2.083m와 2.000m의 차이와 같아요. 간격이 절반이 되면 오차도 절반이 되는 구조이죠.
위키백과가 오일러 방법을 오차가 단계 크기에 비례하는 1차 방법이라고 정리해 둔 내용이 점프 하나에서 그대로 확인됐습니다. 등가속도 공식을 쓴 방식은 30, 60, 144, 240프레임 모두 최고점 오차가 0.0%였어요.
프레임이 흔들리면 어떻게 될까요?
현실의 프레임 간격은 일정하지 않으니, 평균 프레임레이트 30, 60, 144, 240에서 간격이 평균의 30%쯤 흔들리는 점프를 조건마다 5만 6천 번씩 시뮬레이션을 돌렸습니다.
위치를 먼저 갱신하는 방식의 평균 최고점은 2.184m, 2.091m, 2.038m, 2.023m였고, 속도를 먼저 갱신하는 방식은 1.822m, 1.910m, 1.962m, 1.977m였습니다.
등가속도 방식은 1.998m에서 2.000m 사이를 벗어나지 않았죠. 60프레임에서 위치 먼저 갱신 방식의 5~95% 구간은 2.082m에서 2.102m로 2cm 정도였어요. 평균 프레임레이트가 60에서 240으로 달라지며 생긴 6.8cm 차이가 이 흔들림보다 훨씬 컸습니다.

개인적인 견해로는 이 실험에서 가장 의외였던 건 흔들림이 아니라 평균이었다고 말할 수 있어요. 점프 높이를 가른 건 프레임 간격의 평균이었습니다. 다만 흔들림이 있으면 오차가 조금 커지기는 해서, 30프레임에서는 8.3%가 9.2%가 됐어요.
유니티 포럼에는 창 크기나 CPU 사용량을 바꾸면 점프 높이가 달라진다는 질문이 올라와 있습니다. 질문에 코드가 없어 원인을 확정할 수는 없지만 컴퓨터가 바쁘지 않을 때 점프가 낮았다는 증상은 프레임레이트가 높을수록 낮아지는 위치 먼저 갱신 방식의 패턴과 같습니다.
같은 점프라는 착각
지난 포스팅들에서의 실험과 마찬가지로 이 실험에는 한계가 있습니다. 초기 속도와 중력은 내가 고른 값이고, 공기 저항이나 천장 충돌, 버튼을 누른 시간으로 높이를 조절하는 가변 점프는 넣지 않았습니다. 착지 시점도 수식을 바꾼다고 맞지 않았죠. 프레임 단위로 착지를 판정하게 되니 30프레임에서는 정답 0.8초보다 한 프레임 늦은 0.833초가 나왔습니다.
글렌 피들러의 물리 시뮬레이션 글은 프레임마다 시간 간격을 그대로 넘기면 같은 입력에서도 결과가 달라지고, 심하면 벽을 뚫는 일까지 생긴다고 경고하는데요. 그 글이 권하는 고정 간격은 이번에 따로 실험해보진 않았습니다. 결국 프레임레이트가 달라도 점프가 같다는 믿음은, 프레임 간격에 기대지 않는 수식 한 줄이 있을 때만 성립한 것이었습니다.