Это старый вопрос, но недавно я разработал аналогичный код, так что, возможно, это кому-то поможет.
Да, задержка всегда полезна в расчетах. Но это немного сложнее, чем RTT. Время прохождения туда и обратно всегда меняется... ваш сетевой код может сохранять среднее значение, но отклонение от этого среднего значения велико.
Локальный клиент, удаленный клиент и сервер прогнозируют текущую позицию с помощью алгоритмов. Близки к типичным следующие данные:
- Время: т
- Размещение: положение (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+differeltaT. Он не может изменить то, что он уже симулировал, поэтому, если он не откладывает симуляцию, он прыгнет на удаленный корабль, и вы увидите рывковый кадр. Вот почему моделирование кораблей с дистанционным управлением должно происходить с задержкой на время, постоянно превышающее 2*типичная дельтаТ. Это должна быть постоянная задержка или задержка, которая меняется постепенно, и во время серьезных задержек вы все равно увидите рывки кадров.
Вы можете сгладить все рывки с помощью дополнительного сглаживающего кода, но не делайте этого, пока ваш код не станет безупречным во всем остальном, потому что это просто сделает невозможным определение проблем.
Вы должны иметь хорошую синхронизированную привязку времени. Много кода делает это довольно небрежно (например, RakNet не делает (или не делал) это очень хорошо). Вот хороший совет: в краткосрочной перспективе вы можете предположить, что все часы идут с одинаковой скоростью, и вам нужно только выяснить, каково смещение, поэтому держите окно максимального и минимального смещения и закрывайте его, как вы узнаете; В долгосрочной перспективе вам нужно компенсировать клиентов, чьи часы работают быстро или медленно, поэтому позвольте окну открыться, если вы точно знаете, что это необходимо. Вы должны использовать локальный источник времени, который монотонно увеличивается и не зависит от скорости процессора (которая в настоящее время является переменной).
Нет, не откладывайте локальную симуляцию, когда локальный «аватар» движется. Казалось бы, слишком безразлично. Вы можете немного отложить его (возможно, до 50 мс), чтобы улучшить синхронизацию, но задержка на всем пути до RTT сделает вашу игру раздражающе невосприимчивой. Установите параметр локальной задержки и поэкспериментируйте с ним, потому что небольшая постоянная задержка может быть приемлемой и улучшить синхронизацию. Но это не обязательно и может вызвать много проблем, поэтому я рекомендую делать этот код в последнюю очередь. (Если вы пытаетесь сыграть в рукопашную игру FPS, вам нужно будет сделать это и всю другую помощь, которую вы можете получить).
Что касается предотвращения мошенничества и гладкости моделирования: во-первых, клиенты не должны просто экстраполировать из последней известной позиции, когда официальная позиция меняется. Он должен регистрировать корректирующий вектор и медленно переходить от старого пути к новому для плавности (но, как я сказал выше, делайте этот код последним, иначе он замаскирует другие ошибки). Во-вторых, сервер должен допускать широкий диапазон задержек... даже на машинах в той же сети Ethernet задержка пакетов обычно составляет от 5 мс до 100 мс или около того... это довольно большой диапазон. Конечно, вам нужно отрезать его и сказать: «Если вы говорите, что переместились в момент времени T, но я получил пакет в момент времени T + some_large_number, то я думаю, что вы пытаетесь исправить прошлое и лжете мне». some_large_number не должен быть намного больше среднего RTT, чтобы люди оставались честными.
Симуляции никогда не будут строго синхронизированы. Они должны оставаться в пределах 400 мс или около того через Интернет, но, безусловно, будут отклоняться от этого во время задержки ... до 30 секунд или более, и вам нужно мириться с такими вещами, потому что они не являются редкими. Учитывая, что Интернет ограничен скоростью света в меди, вы всегда можете ожидать, что односторонние задержки обычно будут в диапазоне не менее 100 мс минимум для ваших удаленных клиентов, часто 500 мс или больше.
Поэтому я настоятельно рекомендую вам не пытаться делать шутер от первого лица через Интернет (некоторые крупные компании пытаются, но всегда будут проблемы). Есть уловки, которые вы можете использовать, если используете снаряды (запуская их быстро в одной симуляции и медленно в другой), так что даже если тайминг выключен, он выглядит. Кроме того, в FPS-играх используется правило, согласно которому обнаружение попадания основано на моделировании атакующего... кажется более неправильным, когда атакующий знает, что он точно попал в цель, и промахивается, чем когда защитник знает, что он был в стороне, и получает удар. в любом случае. Вы должны выбрать одно или другое, и психологически это было сделано именно так. Ближний бой требует уровня синхронизации, который откровенно невозможен, и большинство игровых компаний не будут касаться рукопашного боя MMORPG FPS, а скорее будут использовать автонацеливание (попробуйте поиграть в Mortal Online, вы поймете, что я имею в виду).
Удачи.
person
Mike Dilger
schedule
18.10.2010