Я роблю швидку швидку фізичну гру, яка є хокеєм настільним. З двома молотками і однією шайбою. Гра працює на iphone / ipad, і я роблю багатокористувацьку частину через GameCenter.
Так працює мережева система. Клієнт, який позначає зірочку, буде вирішений як сервер, а той, хто приймає запит на відповідність, - це клієнт.
У «сервера» працює фізика, і відповідь є негайною, і клієнт також працює з фізикою, так що між обміном повідомленнями він виглядає гладко. Що я роблю як сервер, це те, що я надсилаю клієнтові свою швидкість шайби та мою позицію, і клієнт коригує свою швидкість шайби / позицію, пов'язану з сервером, щоб підтримувати її синхронізацію. В іншому випадку фізика десинхронізується, і вона прикручується.
Коли затримка в мережі хороша, нижче 100 мс результати дуже хороші, я отримав плавну гру на клієнті, і дивна поведінка мінімальна. Проблема трапляється, коли відставання становить від 150 до 200 мс. У такому випадку трапляється, що шайба мого клієнта вже потрапила в край і перевернув напрямок, але він отримує повідомлення про затримку від сервера і трохи відступає, викликаючи дивне відчуття поведінки м'яча.
Я прочитав кілька речей про це:
Клацніть Приклад синхронізації
Вікіпедія на синхронізації годин
Отже, як я можу це вирішити? Наскільки я прочитав найкращий варіант, який у мене є, - це зробити синхронізацію годин на сервері / клієнті з часовою позначкою, щоб, коли я отримую повідомлення про затримку, пов'язані з моїм годинником, я просто ігнорую тоді і дозволяю клієнтам моделювання робити робота. Чи згодні ви з цим? А оскільки я надсилаю недостовірні дані (UDP), я можу отримати повідомлення із затримкою чи повідомлення не в порядку.
Якщо це найкращий підхід, як я здійснюю синхронізацію годин. Я прочитав кроки, як це зробити, але я не зовсім зрозумів це.
Там сказано, що:
- Клієнт маркує поточний місцевий час на пакеті "запит на час" і відправляє на сервер.
- Після отримання сервером сервер маркує час сервера і повертається
- Після отримання клієнтом клієнт віднімає поточний час від відправленого часу і ділиться на два, щоб обчислити затримку. Він віднімає поточний час від часу сервера, щоб визначити дельту часу клієнт-сервер, і додає з половиною затримки, щоб отримати правильну дельту годинника. (Поки що цей альготим дуже схожий на SNTP)
- Клієнт повторює кроки від 1 до 3 п’ять і більше разів, кожен раз призупиняючи кілька секунд. Інший трафік може бути дозволений у проміжний час, але його слід мінімізувати для найкращих результатів Результати надходжень пакетів накопичуються та сортуються за найменшою затримкою до найвищої латентності. Середня затримка визначається шляхом вибору зразка середньої точки з цього упорядкованого списку.
- Усі зразки вище приблизно 1 стандартного відхилення від медіани відкидаються, а решта зразків усереднюються за допомогою середнього арифметичного.
Дотримуючись цього прикладу, я мав би це:
Давайте робити вигляд, що гра завантажена, і час мого клієнта зараз 0, тож я надсилаю на сервер, що мій час 0.
Повідомлення займає 150 мс, щоб дістатися до сервера, але годинник сервера вже почався і на 1 секунду випереджає клієнта. Коли сервер отримає повідомлення, час буде: 1,15 і відправить цей час клієнту, чи добре ми? Давайте робити вигляд, що наше відставання постійне в 150 мс.
Тепер клієнт отримує час 1,15 і віднімає поточний час від відправленого часу і ділиться на два, щоб обчислити затримку. Що становить: 0,3 - 0 = 0,3 / 2 -> 150 мс.
Він віднімає поточний час від часу сервера, щоб визначити дельту часу клієнт-сервер, і додає на половину затримки, щоб отримати правильну дельту годинника:
Час клієнта: 0,3 Час сервера 1,15
0,3 - 1,15 = .85 + затримка (.15) = 1
Як це синхронізується? Що я пропускаю?
Я вперше про багатокористувацький та мережевий досвід, тому я трохи розгублений.
Дякую.