Сохранение синхронизации в многопользовательской RTS-игре, в которой используется арифметика с плавающей запятой.

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

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

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

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

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


person Calmarius    schedule 22.12.2009    source источник
comment
Должен ли компьютер каждого игрока моделировать все или только то, что находится в их поле зрения?   -  person Jason Aller    schedule 22.12.2009
comment
Им нужно все смоделировать.   -  person Calmarius    schedule 24.12.2009


Ответы (4)


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

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

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

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

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

person Peter Alexander    schedule 22.12.2009
comment
Даже два экземпляра одной и той же архитектуры могут иметь разные результаты с плавающей запятой из-за таких вещей, как управляющее слово FPU, переупорядочение инструкций ЦП на основе использования конвейера и т. Д. - person Kylotan; 25.12.2009
comment
Я знаю, что ЦП изменит порядок инструкций, но я не верю, что он изменит порядок операций с плавающей запятой таким образом, чтобы нарушить детерминизм. - person Peter Alexander; 28.12.2009
comment
Он где-то читал, что операции с плавающей запятой не ассоциативны (из-за округления), и разница в один бит может иметь значение или может вызвать рассинхронизацию. Даже разные версии .NET могут иметь разные оптимизаторы JIT, которые могут давать разные результаты. И я просто не могу попросить своих пользователей установить .NET 2.0 (потому что я хочу, чтобы он работал с Mono и в Linux). Поэтому я решил создать класс с фиксированной точкой и заменить (почти) все двойные следующим образом: stackoverflow.com/questions/605124/fixed-point-math-in-c (вероятно, он столкнулся с той же проблемой) - person Calmarius; 28.12.2009

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

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

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

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

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

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

person AlwaysLearning    schedule 01.09.2010
comment
На самом деле, в играх P2P, где каждый клиент моделирует мир по своему усмотрению, довольно легко обеспечить безопасность. Все, что вам нужно сделать, это отправить друг другу контрольную сумму данных моделирования (например, количество ресурсов, количество зданий и т. Д.), И если кто-то отправит другую контрольную сумму, то он либо рассинхронизируется, либо обманывает, и вы просто выкидываете его из игры. . - person Smilediver; 26.08.2011

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

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

person Drew Dormann    schedule 22.12.2009
comment
Как он заявил в исходном сообщении, состояние игры будет состоять из тысяч объектов, что сделает невозможной синхронизацию всего состояния. Я не знаю ни одной стратегии в реальном времени, в которой использовался бы этот подход - все они синхронизируются путем синхронизации ввода и обеспечения детерминированности моделирования. - person Peter Alexander; 22.12.2009

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

Обычно сервер хранит состояние (положение / ориентацию / тип) всех юнитов игроков.

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

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

person gingerbreadboy    schedule 23.12.2009