Как программист, вы когда-нибудь представляли себе, как реализуются многопользовательские игры?
Для непосвященных игры кажутся волшебными: двое или более игроков разделяют общий опыт онлайн, как будто они на самом деле находятся в одном и том же виртуальном мире. Игра выглядит как гигантское волшебство, прекрасное и захватывающее, но как разработчики мы знаем, что реальность не такая, как мы видим, это всего лишь иллюзия. Общая реальность, которую вы чувствуете, на самом деле является приближением к тому, что воспринимается в данный момент с вашей собственной уникальной точки зрения и местоположения.
1. Одноранговая синхронизация кадров
Первоначальные игры были объединены в одноранговую сеть, где каждый компьютер был подключен друг к другу и обменивался информацией через ячеистую топологию. Вы до сих пор можете видеть, что эта модель существует в играх RTS, и она по какой-то причине интересна, возможно, потому, что это первый способ, с помощью которого большинство людей думают о том, как работают игровые сети.
Основная идея обработки игровой информации заключается в абстрагировании и преобразовании игровых данных в серию командных сообщений, и когда каждое преобразование обрабатывается, оно напрямую превращается в состояние игры. Например: перемещение юнитов, нападение на объекты, строительство зданий. Все это требует, чтобы каждый компьютер игрока в сети, начиная с команды инициализации, выполнял одни и те же команды и преобразовывал данные.
Конечно, это слишком упрощенное объяснение, и оно также скрывает много деталей, но мы можем узнать, как работает сеть игр RTS, благодаря этой базовой идее. Если вы хотите узнать больше сетевых моделей, пожалуйста, нажмите:1500 Archers on a 28.8: Network Programming in Age of Empires and Beyond.
Они кажутся такими простыми и элегантными, но, к сожалению, у них есть несколько факторов, которые нас ограничивают.
Первое ограничение заключается в том, что крайне сложно поддерживать полностью детерминистически непротиворечивое состояние игры, особенно сохраняя одинаковый результат каждого преобразования на каждой машине. Например, юнит, у которого пути на двух машинах немного различаются, на одной машине прибывает раньше, начинает бой и превращает его в победу, а на другой машине проигрывает, прибыв чуть позже. Подобно тому, как бабочка взмахивает крыльями, а затем вызывает ураган на другой стороне мира, крошечная разница во времени может привести к полной рассинхронизации двух сторон.
Второе ограничение, чтобы гарантировать, что все игроки в игре имеют одинаковый результат, необходимо дождаться поступления данных текущего раунда всех игроков, прежде чем моделировать и играть в этом раунде. Это означает, что каждый игрок в игре должен ждать игрока с наибольшей сетевой задержкой. Игры RTS обычно маскируют эту задержку, предоставляя немедленную звуковую обратную связь и / или проигрывая анимацию пения (перехода), но в конечном итоге реальные действия, влияющие на игру, не происходят до тех пор, пока не пройдет эта задержка.
Третье ограничение, т.к. синхронизация изменений состояний в игре синхронизируется посредством отправки командных сообщений. Следовательно, чтобы иметь в игре одно и то же состояние игрока, все игроки должны начать игру с одного и того же начального состояния. Это означает, что каждый игрок должен присоединиться к комнате до начала игры, а затем начать игру вместе, хотя теоретически возможно разрешить некоторым игрокам присоединиться к игре позже, но иметь полностью детерминированную начальную точку в текущей игре. довольно большой, поэтому такая ситуация не является обычной.
Несмотря на эти ограничения, которые нас беспокоят, эта модель хорошо работает для игр RTS и до сих пор существует в играх, таких как "Command and Conquer", "Age of Empires"и"Starcraftи т. д. Причина в том, что в RTS-игре более тысячи юнитов, и все эти юниты имеют свои состояния, которые необходимо синхронизировать, и их данные слишком велики для обмена между игроками. При желании мы можем синхронизировать только с помощью этих команд изменения состояния игры.
Итак, это знакомство с одноранговой моделью онлайн-игр с кадровой синхронизацией.Что касается других типов игр, современные технологии уже начали появляться. Давайте теперь начнем сDoom, Quake так же какUnrealВ классической игре мы вместе начали наблюдать за технической эволюцией экшн-игр.
2. Клиент/Сервер (архитектура c/s)
В эпоху экшн-игр ограничения вышеуказанной синхронизации кадровDoom В играх стало более очевидным, что, хотя в локальной сети все было хорошо, для интернет-пользователей это было ужасно:
Хотя можно на одну кошку (модем) поставить двеDoom Машины связаны друг с другом через Интернет, но они очень медленно играют вместе. Соединение варьировалось от невоспроизводимого (например, PPP-соединение 14,4 Кбит/с) до слегка пригодного для воспроизведения (например, 28,8-килобитного соединения cat, использующего сжатые данные драйвера SLIP). Так как эти соединения имеют незначительную полезность, в этой статье основное внимание будет уделено только прямым сетевым соединениям.
Эта проблема связана с тем, что сетевая часть Doom изначально предназначена только для локальной сети и использует представленную ранее модель одноранговой синхронизации кадров. Вводимая информация каждого игрока (например, ключевые кнопки и т. д.) синхронизируется с другими в каждом раунде, и любой игрок должен дождаться получения информации о ключевых кнопках всех других игроков, прежде чем воспроизводить этот кадр анимации, чтобы имитировать воспроизведение.
То есть, прежде чем вы сможете повернуться (трансформироваться), переместиться или выстрелить, вы должны дождаться ввода от игрока-кота (модулятора) с наибольшей задержкой. Одна только мысль о том, что парень выше написал о том, что «эти связи имеют предельную полезность», вызывает скрежет и разочарование.
Чтобы изменить эту ситуацию, в игры можно играть только в локальных сетях, а также в университетских сетях и крупных предприятиях с хорошими связями.Необходимо изменить эту сетевую модель. Это стало реальностью и было реализовано в 1996 году, когда Джон Кармак выпустил Quake, в котором модель P2P была заменена архитектурой клиент/сервер (C/S).
Теперь игроки в игре больше не могут запускать один и тот же код и напрямую общаться друг с другом, машина каждого игрока является «клиентом», и все они общаются и взаимодействуют через машину, называемую «сервером». Окончательное определение состояния игры больше не зависит от совместного подтверждения каждой клиентской машины, а сервер определяет окончательный результат. Каждый клиент подобен тупому терминалу, используемому для показа примерной производительности, реальное состояние игры выполняется на сервере.
В чистой архитектуре c/s вам не нужно запускать код игры локально, а отправлять некоторую входную информацию, такую как нажатия клавиш, движения мыши, щелчки и т. д., на сервер. Сервер обновит ваш статус игрока в игровом мире, а затем ответит вашему клиенту пакетом, содержащим информацию о вашем персонаже и данные о ближайшем игроке. Все клиенты делают интерполированный прогноз между каждым обновлением сообщения, чтобы улучшить плавное перемещение объектов во время каждого обновления состояния, поэтому у вас есть сетевая игра клиент/сервер.
Это уже огромный шаг вперед. Опыт игры зависит от соединения между клиентом и сервером, а не от игрока с наибольшей задержкой в игре. Это позволяет игрокам свободно входить и выходить из игры, в то же время добавляя больше онлайн-игроков, поскольку клиент/сервер снижает среднюю пропускную способность на одного игрока.
Но есть еще некоторые проблемы в архитектуре c/s:
Я помню, что я учитывал все сетевые решения от DOO до Quake, но дело в том, что я использовал неверные предположения, чтобы сделать хорошую сетевую игру. Моя первоначальная цель проектирования заключалась в том, чтобы сетевая задержка пользовательская кошка > провайдерская кошка > сервер > провайдерская кошка > пользовательская кошка > клиент. Боже, это так грубо.
Хорошо, я сделал неправильную настройку. Я использую широкополосный доступ T1 дома, поэтому я просто не понимаю жизнь в сети PPP. Я исправлю это сейчас.
Проблема, конечно, в задержке.
В следующий раз Джон изменит индустрию, когда выпустит QuakeWorld.
3. Прогнозирование на стороне клиента
В оригинальной игре Quake вы бы почувствовали отставание между компьютером и сервером. Например, если вы нажмете кнопку, чтобы двигаться вперед, прежде чем вы действительно начнете двигаться, вам нужно подождать, пока пакет данных не будет отправлен сервером, а затем ответить вашему клиенту, прежде чем вы сможете двигаться. Нажмите кнопку, чтобы выстрелить, и такое же ожидание требуется перед вашим выстрелом.
Если вы играли в какие-либо FPS-игры, такие как: Modern Warfare, вы заметите, что никаких задержек не происходит. Итак, как же ведут себя игры в жанре fps в многопользовательских ситуациях, когда ваши движения не кажутся задержкой?
Эта проблема решается в двух частях. Первая часть — это мобильное прогнозирование на стороне клиента, которое было разработано Джоном Кармаком для игры QuakeWorld и позже объединено с модулем Unreal Network Тима Суини. Вторая часть — компенсация задержки, разработанная в Counterstrike Яном Бернье из Valve. Итак, в этой главе мы сосредоточимся на первой части — сокрытии задержки движения пользователя.
Рассказывая о своем грядущем проекте QuakeWorld, Джон Кармак сказал:
Теперь я позволяю клиенту прогнозировать движение пользователя, пока не ответит авторитетная информация сервера. Это серьезное структурное изменение. Клиенту необходимо знать ряд основных свойств о твердости объекта, трении, гравитации и т. д. Мне грустно видеть, что клиент уходит как терминал, но как прагматик я должен выйти за рамки этого идеала.
Итак, теперь нам нужно запустить больше кода на стороне клиента, чтобы устранить задержку. Это больше не тупой терминал, который просто отправляет входные данные на сервер, а затем вставляет возвращаемую информацию. Теперь клиентская машина может запускать часть игрового кода, который может локально предсказывать движения вашего персонажа и мгновенно реагировать на ваш ввод.
Теперь, когда вы сразу же нажимаете вперед, ваша игра будет двигаться вперед немедленно, больше не ожидая, пока данные будут передаваться туда и обратно между клиентом и сервером, чтобы ответить на вашу операцию.
Трудность с этим подходом заключается не в предсказании, которое работает так же, как обычный игровой код, обновляя состояние персонажа во времени на основе ввода игрока. Сложность заключается в том, как клиент вносит исправления на основе информации сервера, когда клиент и сервер не проверяют, что (действия) делает персонаж игрока.
Теперь вы думаете: эй, если код работает на клиенте, почему бы не полагаться на информацию клиента? Клиенты могут запускать свой собственный код для олицетворения роли, и им нужно только сообщать серверу эту информацию каждый раз при отправке пакета. Если каждый клиент отправляет на сервер одну и ту же информацию, сообщая серверу «это мое текущее местоположение», это приведет к таким проблемам. Клиентов можно легко взломать и контролировать, так что в RPG чит может мгновенно увернуться от удара способности противника или телепортироваться за вами, когда вы стреляете.
Таким образом, в играх FPS клиент каждого игрока как можно скорее может предсказать, как будет действовать и двигаться его собственный персонаж, но, в конце концов, статус персонажа каждого игрока полностью зависит от сервера. Как то, что Тим Суини написал вThe Unreal Networking ArchitectureКак описано в: «Сервер является ведущим».
Вот тут становится интересно. Если существует несоответствие между клиентом и сервером, клиент должен преобладать и обновляться на основе информации сервера, но из-за задержки между клиентом и сервером исправление сервера должно быть прошлым действием. Например, если сообщение проходит 100 мс от клиента к серверу, а затем 100 мс обратно, то любые исправления, сделанные сервером, являются действиями клиента 200 мс назад, то есть именно тогда, когда клиент предсказал движение персонажа.
Если каждое действие клиента корректируется сервером, то вы увидите, что клиент возвращается в исходное положение, поэтому клиент не сможет выполнять какие-либо заранее предсказанные операции. Так как же решить эту проблему и при этом сохранить прогнозирование клиента?
Решение состоит в том, чтобы создать буфер на стороне клиента, а затем использовать его для циклического просмотра состояния персонажа и исходного ввода игрока. Когда клиент получает информацию об исправлении от сервера, он сначала отбрасывает в буфере информацию о состоянии, которая старше исправленного состояния (возвращенного сервером), а затем воспроизводит входную информацию, хранящуюся в буфере, на основе (исправленного) состояния. правильное состояние.Ретрансляция этих входных данных варьируется от правильного состояния до текущего времени прогнозирования. По сути, клиент просто, казалось бы, невидимо «перематывает и воспроизводит» последние n кадров движения локального персонажа игрока, сохраняя при этом остальной мир неизменным.
Такой подход позволяет игроку чувствовать, что в управлении игрой нет задержек, а также улучшает согласованность кода, выполняемого между клиентом и сервером — согласованные результаты при одинаковом вводе. Конечно, исправления случаются редко, как описывает это Тим Суини:
...лучшее как для клиента, так и для сервера: во всех случаях сервер авторитетен. Почти все время смоделированные данные клиента и данные сервера совпадают, поэтому положение клиента редко корректируется. Есть только несколько редких случаев, таких как попадание ракеты в игрока или столкновение с врагом (монстром), тогда может потребоваться исправить ситуацию с локальным клиентом.
То есть положение (поведение) игрока должно корректироваться сервером только в том случае, если на персонажа игрока влияет какое-то внешнее событие, влияющее на ввод игрока, и клиент не может их предсказать. Конечно, если игрок попытается сжульничать, это обязательно будет исправлено сервером.
Это переведенная статья, в основном для сетевого дизайна игры.В настоящее время были объяснены основные решения для реализации онлайн-игр.Если вас больше интересует английский язык, перейдите по ссылке в конце статьи.Если вы чувствуете что с переводом что-то не так, пожалуйста, оставьте сообщение Исправить. Оригинальный адрес:Нажмите здесь, чтобы увидеть исходный текст
-------------------------------------------------------------------------------------------------------
Обновляйте темы разработки игр, обратите внимание на мой публичный номер
Big Code Hou уделяет внимание личностному росту и разработке игр и стремится продвигать прогресс отечественного сообщества игровых технологий.