Синхронизация в многопользовательской RTS-игре с использованием арифметики с плавающей запятой - PullRequest
7 голосов
/ 22 декабря 2009

Я пишу 2D космическую RTS-игру на C #. Одиночная игра работает. Теперь я хочу добавить многопользовательскую функциональность. Я гуглил это, и кажется, что есть только один способ непрерывно перемещать тысячи юнитов без мощного сетевого соединения: отправлять только команды через сеть, выполняя одинаковую симуляцию для каждого игрока.

И теперь возникла проблема, что весь двигатель везде использует двойники. А вычисления с плавающей запятой сильно зависят от оптимизации компилятора и архитектуры процессора, поэтому очень сложно поддерживать синхронизацию. И это вообще не основано на сетке, а имеет простой физический движок для перемещения космических кораблей (космические корабли имеют импульс и момент импульса ...). Так что перекодировать весь материал для использования фиксированной точки было бы довольно громоздким (но, вероятно, единственным решением).

Итак, у меня есть 2 варианта:

  • Попрощайтесь с текущим кодом и перезапустите с нуля, используя целые числа
  • Создавайте игровую локальную сеть только там, где достаточно пропускной способности, чтобы иметь 8 игроков с тысячами юнитов и отправлять позиции и ориентацию и т. Д. Почти в каждом кадре ...

Так что я искал лучшие мнения (или даже советы по переносу кода в фиксированную точку, не испортив все…)

Ответы [ 4 ]

2 голосов
/ 22 декабря 2009

Конечно, все ваши клиенты будут использовать один и тот же двоичный файл, поэтому оптимизация компилятора не влияет на проблемы синхронизации.

Кроме того, если вы планируете использовать только одну архитектуру (или, по крайней мере, разрешаете людям играть друг против друга, если они используют одну и ту же архитектуру), то это тоже не имеет значения.

Я сделал то же самое, используя плавающие точки в играх на C # для iPhone и настольных ПК, и они дают одинаковые результаты, даже если iPhone ARM, а настольный компьютер x86.

Просто убедитесь, что игра точно выполняет те же вычисления, и у вас все будет в порядке.

Если ничего не помогло, просто замените все экземпляры float в вашей игре на стандартный арифметический класс с фиксированной точкой. Таким образом, вы можете быть на 100% уверены, что ваши вычисления являются детерминированными в разных архитектурах, хотя природа арифметики с фиксированной запятой может отрицательно повлиять на вашу игру.

1 голос
/ 01 сентября 2010

Я немного поздно отвечаю на это, но с точки зрения безопасности игры симуляция должна выполняться только на сервере / хосте (то есть: не доверяйте клиентам, они могут обманывать):

  1. Клиенты должны только отправлять свои движения / команды на сервер (который отбрасывает неверные данные или фиксирует их в игровых пределах), поэтому клиент, говорящий «Я бегу со скоростью 10 000 м / с», оказывается зажатым сервер, чтобы сказать 10 м / с).

  2. Сервер / хост сообщает клиентам только о том, что происходит в пределах их поля зрения (то есть: игроку с координатами 0,0 не сообщают о двух ИИ, сражающихся друг с другом на 200,0, если он может видеть только радиус 50 единиц вокруг себя.

Это вторая часть, которая экономит полосу пропускания - симуляция на сервере / хосте может иметь тысячи объектов для управления, но клиентам нужно знать только около 100 или 200 вещей в пределах их собственного поля зрения.

Единственная складка в этой ситуации - это такие вещи, как динамический огонь (пули, ракеты и т. Д.), Радиус действия которого может быть больше радиуса обзора клиента. Сервер / хост сообщает клиентам свое происхождение и начальную траекторию / целевой объект, затем клиенты моделируют свой путь в соответствии с теми же правилами, но убийства действительны только при моделировании на сервере / хосте.

Сериализация состояния мира, специфичного для клиента, и сжатие его перед передачей также может быть огромным выигрышем, особенно если свойства вашего класса доступны только Public, когда это необходимо. (Обычно я избегаю XML, но мы значительно улучшили коэффициенты сжатия в одном приложении, выполнив сериализацию в XML и сжимая его по сравнению с сериализацией в двоичный формат и сжимая его. Я подозреваю, что в этом участвовал ограниченный диапазон используемых символов ASCII, YMMV.)

0 голосов
/ 23 декабря 2009

Для чего конкретно вы используете удвоения? Не могли бы вы использовать вместо десятичной?

Как правило, сервер будет хранить состояние (положение / ориентация / тип) всех юнитов игроков.

Когда игрок1 перемещает юнит либо ... инструкция на перемещение отправляется на сервер или ... обновленное состояние отправляется на сервер

Когда клиент проигрывателя должен визуализировать сцену, сервер отправляет обратно информацию о состоянии всех подразделений в запрошенной области действия.

0 голосов
/ 22 декабря 2009

Общепринятым методом является то, чтобы все клиенты периодически описывали свое текущее состояние другим клиентам.

Когда два компьютера не согласны с состоянием объекта, предположительно из-за ошибки с плавающей запятой, в игре есть какое-то правило, чтобы определить, какой из них правильный, и все клиенты корректируются, чтобы соответствовать ему.

...