업데이트 (논리 틱)와 드로우 (렌더 틱) 비율을 분리하려고합니다.
업데이트하면 전 세계의 모든 객체의 위치가 그려집니다.
여기서는 여러분이 요청한 것, 외삽 법, 그리고 또 다른 방법 인 보간법의 두 가지 다른 가능성을 다루겠습니다.
1.
외삽 은 다음 프레임에서 객체의 (예측 된) 위치를 계산 한 다음 현재 객체 위치와 객체가 다음 프레임에 위치 할 위치 사이를 보간하는 위치입니다.
이렇게하려면 그려 각 개체는이 연결되어 있어야 velocity
하고 position
. 객체가 다음 프레임에 위치 할 위치를 찾으려면 velocity * draw_timestep
객체의 현재 위치에 추가 하여 다음 프레임의 예상 위치를 찾으십시오. draw_timestep
이전 렌더 틱 (일명 이전 그리기 호출) 이후 경과 된 시간입니다.
이것을 그대로두면, 예측 된 위치가 다음 프레임의 실제 위치와 일치하지 않을 때 객체가 "깜박 거린다"는 것을 알 수 있습니다. 깜박임을 제거하려면 예측 위치 및 저장할 수 있습니다 LERP LERP 요소로 이전 업데이트 틱 이후 경과 된 시간을 사용하여 이전에 예측 위치 및 각 무승부 단계에서 새로운 예측 위치 사이를. 이렇게하면 빠르게 움직이는 객체가 갑자기 위치를 변경하는 경우 여전히 동작이 좋지 않으며 해당 특수한 경우를 처리 할 수 있습니다. 이 단락에서 언급 한 모든 내용은 외삽 법을 사용 하지 않는 이유 입니다.
2.
보간 은 마지막 두 업데이트의 상태를 저장하고 마지막 이전 업데이트 이후로 경과 한 현재 시간을 기반으로 두 업데이트 사이를 보간하는 위치입니다. 이 설정에서 각 객체는 관련되어 있어야합니다position
하고 previous_position
. 이 경우, 우리의 그림은 현재 게임 상태보다 최악의 업데이트 틱을 나타내고, 현재 업데이트 틱과 정확히 같은 상태를 나타냅니다.
내 의견으로는, 구현하기가 더 쉽고, 현재 업데이트 된 상태 뒤에 1 초 (예 : 1/60 초)의 작은 부분을 그리는 것이 좋기 때문에 내가 설명한대로 보간을 원할 것입니다.
편집하다:
위의 방법으로 구현을 수행하기에 충분하지 않은 경우 여기에 설명 된 보간 방법을 수행하는 방법의 예가 있습니다. 외삽 법은 다루지 않겠습니다. 왜냐하면 여러분이 선호하는 실제 시나리오는 생각할 수 없기 때문입니다.
드로어 블 개체를 만들면 그리기에 필요한 속성 ( 그리기에 필요한 상태 정보)이 저장됩니다.
이 예에서는 위치와 회전을 저장합니다. 색상 또는 질감 좌표 위치와 같은 다른 속성을 저장하고 싶을 수도 있습니다 (예 : 질감이 스크롤되는 경우).
렌더 스레드가 데이터를 그리는 동안 데이터가 수정되는 것을 방지하려면 (예 : 렌더 스레드가 그리는 동안 한 객체의 위치가 변경되지만 다른 객체는 모두 아직 업데이트되지 않은 경우) 일부 유형의 이중 버퍼링을 구현해야합니다.
객체는 두 개의 사본을 저장합니다 previous_state
. 나는 배열에 넣어와로 참조됩니다 previous_state[0]
및 previous_state[1]
. 마찬가지로 두 개의 사본이 필요합니다 current_state
.
이중 버퍼의 어느 복사본이 사용되는지 추적하기 위해 state_index
업데이트 및 그리기 스레드 모두에 사용할 수 있는 변수를 저장합니다 .
업데이트 스레드는 먼저 자체 데이터 (원하는 데이터 구조)를 사용하여 개체의 모든 속성을 계산합니다. 그리고, 사본 current_state[state_index]
에 previous_state[state_index]
, 그림에 대한 새로운 데이터 관련, 복사 position
및 rotation
에 current_state[state_index]
. 그런 다음 state_index = 1 - state_index
현재 사용되는 이중 버퍼 사본을 뒤집습니다.
위 단락의 모든 내용은 잠금 장치를 사용하여 수행해야합니다. current_state
. 업데이트 및 그리기 스레드는 모두이 잠금을 해제합니다. 상태 정보를 복사하는 동안에 만 잠금이 해제됩니다.
그런 다음 렌더 스레드에서 다음과 같이 위치 및 회전에 대한 선형 보간을 수행합니다.
current_position = Lerp(previous_state[state_index].position, current_state[state_index].position, elapsed/update_tick_length)
elapsed
마지막 업데이트 틱 이후 렌더 스레드에서 경과 한 시간은 어디 이며 update_tick_length
고정 업데이트 속도가 틱당 소요되는 시간입니다 (예 : 20FPS 업데이트 update_tick_length = 0.05
).
Lerp
위 의 기능 이 무엇인지 모르는 경우 주제에 대한 위키 백과의 기사를 확인하십시오 : 선형 보간 . 그러나 lerping이 무엇인지 모른다면 보간 된 도면으로 분리 된 업데이트 / 도면을 구현할 준비가되지 않았을 것입니다.