2021년 9월 25일(토) 잡담 방송중 드러난 버그의 디버깅 썰.
증상 :
점프했다가 떨어질때 바닥보다 약간 높은 위치에서 캐릭터가 멈춤. 이때 애니메이션도 착지 동작이 아닌 상태로 스톱.
원인:
1) 캐릭터 오브젝트 스케일/회전/이동에 변화가 있을 경우 이를 렌더링용 변환 매트릭스에 반영하도록 되어있다. 불필요한 처리를 반복하는 상황을 막기 위해 업데이트 플래그 변수를 1로 세팅하고 이 변수를 체크하여 프레임당 한번만 수행한다.
2)그런데 어떤 경우 이 플래그 변수가 1로 세팅되지 않는 경우가 있다.
3) 게임 프레임이 30프레임이고 렌더링 프레임은 n프레임이다. vsync를 끈 상태에서 프레임레이트가 잘 나와서 300프레임 나오고 있다면 게임 프레임 사이에 렌더링용 9프레임이 삽입되고 이 중간 9프레임 동안 캐릭터의 위치/스케일/회전은 보간된다.
4) 렌더링용 매트릭스는 보간된 좌표에 종속된다. 따라서 보간된 좌표가 변경될 경우 렌더링용 매트릭스를 업데이트 해야한다. 따라서 1)의 상황이 되며 업데이트 플래그 변수를 1로 설정해야한다.
5) 보간이 일어나는 경우 4)를 정확히 처리하고 있으나 보간된 프레임에서 게임 프레임으로 진입하는 경우 보간된 좌표는 원래 목적했던 좌표로 변경되어야 한다. 이 경우 또한 보간된 좌표가 변경되므로 이 시점에서 1)의 상황이 된다. 따라서 업데이트 플래그 변수를 1로 설정해야하는데 이 처리가 빠져있었다.
6) 공교롭게도 대부분의 경우 이 상황의 직후에 캐릭터의 위치를 설정하는 SetPosition()함수가 호출되고 있었고 업데이트 플래그 변수가 1로 설정되었다. 따라서 대부분의 경우는 문제가 드러나지 않는다.
7) 아주 가끔 보간된 프레임에서 게임 프레임으로 진입한 후에 SetPosition()이 호출되지 않을 경우 업데이트 플래그 변수는 1로 설정되지 않는다. 충돌처리용 타원체는 정확히 위치가 갱신되어있고 서버를 비롯한 상위 레이어에서 인식하는 좌표는 정확히 옳지만 렌더링되는 오브젝트는 바로 직전의 보간된 프레임의 위치를 가지고 있다. 이로 인해 실제 위치에 약간 못미친 상태로 렌더링 된다. 낙하중이었다면 지면에 도착하기 직전 상태로 렌더링 된다(오른쪽 그림).
공중에 뜬 상태에서 움직이는 기능하곤 상관없이 이전부터 있던 버그였다.
그런데 왜 이전엔 몰랐느냐 하면, 이게 렌더링 프레임이 충분히 높을때는 티가 잘 안난다.
어제 오늘 멀티 플레이 테스트하느라-로컬머신에 여러개의 클라이언트를 띄워야 했다. 이때 양쪽 클라이언트 모두 균일한 프레임 레이트를 유지하도록 vsync를 켰다. 그래서 게임 클라이언트는 60프레임으로 제한됐고 문제가 잘 드러나게 된것.
원인 찾느라 5시간을 뒤졌네.으.
