Это старый вопрос, но я недавно разработал подобный код, так что, возможно, это кому-нибудь поможет.
Да, задержка всегда полезна при расчете. Но это немного сложнее, чем RTT. Время приема-передачи всегда меняется ... код вашей сети может сохранять среднее значение, но отклонение от этого среднего является большим.
Локальный клиент, удаленный клиент и сервер предсказывают текущую позицию, используя алгоритмы. Следующие данные близки к типичным:
- Время: t
- Размещение: положение (x, y, z) и ориентация (x, y, z, w)
- Движение: вектор линейного движения, задающий направление с длиной как скорость (x, y, z), и
вектор вращательного движения, задающий ось с длиной как скорость вращения (x, y, z)
Вам нужны алгоритмы, которые экстраполируют из [T, P, M], установленного в simtime. Я не буду предоставлять их здесь.
Когда клиент регистрирует изменение в приводе корабля в [T, P, M], оно не попадет на сервер до T + deltaT. Но если deltaT находится в пределах допустимых задержек в сети, сервер может сказать: «Да, это произошло в T, я принимаю это». В противном случае он может захотеть исправить клиента, сказав: «Нет, это из-за допусков, это произошло в мое время T '», и в этом случае клиент должен будет ОТМЕНИТЬ все последующие изменения [T, P, M] от исправленного сервером (это означает, что вам нужно сохранить очередь или список из них).
Следующий клиент получит его по адресу T + deltaT + differentdeltaT. Он не может изменить то, что уже имитировал, поэтому, если он не откладывает симуляцию, он прыгнет на удаленный корабль, и вы увидите кадр рывка. Вот почему имитация дистанционных кораблей должна быть отложена на время, постоянно превышающее 2 * типичная дельтаТ. Это должна быть постоянная задержка или задержка, которая постепенно меняется, и во время сильной задержки, тем не менее, вы увидите резкие кадры
Вы можете сгладить все рывки с помощью дополнительного сглаживающего кода, но не делайте этого до тех пор, пока ваш код не станет безупречным, потому что это просто сделает невозможным увидеть, где проблемы.
Вы должны иметь хороший синхронизированный отсчет времени. Большая часть кода делает это довольно небрежно (например, RakNet не делает (или не делает) это очень хорошо). Вот хороший совет: в краткосрочной перспективе вы можете предположить, что все часы работают с одинаковой частотой, и вам нужно только выяснить, что такое смещение, поэтому сохраняйте окно максимального и минимального смещения и закрывайте его по мере обучения; В долгосрочной перспективе вам нужно компенсировать клиентов, чьи часы работают быстро или медленно, поэтому позвольте окну открыться, если вы точно знаете, что оно должно. Вы должны использовать локальный источник времени, который монотонно увеличивается и не зависит от скорости процессора (которая в настоящее время является переменной).
Нет, не откладывайте локальное моделирование, когда перемещается местный "аватар". Казалось бы, слишком безразличным. Вы можете немного задержать его (до 50 мс), чтобы улучшить синхронизацию, но задержка на всем пути к RTT сделает вашу игру разочаровывающе безразличной. Установите опцию для локальной задержки и поиграйте с ней, потому что небольшая последовательная задержка может быть приемлемой и улучшить синхронизацию. Но это не обязательно и может вызвать много проблем, поэтому я рекомендую делать этот код последним. (Если вы пытаетесь сделать FPS-игру ближнего боя, вам нужно будет сделать это и всю другую помощь, которую вы можете получить).
Что касается предотвращения мошенничества и гладкости симуляции: во-первых, клиенты не должны просто экстраполировать последнюю известную позицию, когда меняется официальная позиция. Он должен зарегистрировать корректирующий вектор и медленно перемещаться от старого пути к новому пути для гладкости (но, как я сказал выше, этот код выполняется последним, или он замаскирует другие ошибки). Во-вторых, сервер должен выдерживать широкий диапазон задержек ... даже на машинах в одной и той же сети Ethernet задержка пакетов обычно составляет от 5 мс до 100 мс или около того ... это довольно большой диапазон. Конечно, вам нужно отрезать его и сказать: «Если вы говорите, что переехали в момент времени T, но я получил пакет в T + some_large_number, то я думаю, что вы пытаетесь изменить прошлое и лгать мне». some_large_number не должен быть намного больше среднего RTT, чтобы люди были честными.
Моделирование никогда не будет строго синхронизировано. Они должны оставаться в пределах 400 мс или около того через Интернет, но, безусловно, будут выходить за пределы этого во время задержки ... до 30 секунд или более, и вам нужно терпеть такие вещи, потому что они не редкость. Учитывая, что Интернет ограничен скоростью света в меди, вы всегда можете ожидать, что задержки в одном направлении обычно находятся в диапазоне не менее 100 мс для ваших удаленных клиентов, часто 500 мс или более.
Поэтому я настоятельно рекомендую вам не пытаться делать FPS-игру ближнего боя через Интернет (некоторые крупные компании пытаются, но всегда будут иметь проблемы). Есть приемы, которые вы можете сделать, если вы используете снаряды (запуская их быстро в одной симуляции и медленно в другой), чтобы, несмотря на то, что время выключено, оно выглядело. Кроме того, в FPS-играх используется правило, согласно которому обнаружение удара основано на симуляции атакующих ... оно кажется более неправильным, когда злоумышленник знает, что он мертв по цели, и пропускает его, а затем, когда защитник знает, что он сбился с пути и получает удар в любом случае. Вы должны выбрать один или другой, и психологически это так, как это было сделано. Для рукопашного боя необходим определенный уровень синхронизации, что, честно говоря, невозможно, и большинство игровых компаний не будут касаться MMORPG FPS в ближнем бою, а скорее используют автоматическое нацеливание (попробуйте поиграть в Mortal Online, вы поймете, что я имею в виду).
Удачи.