Я пытаюсь получить предсказание / согласование на стороне клиента, работающее для модели клиент / сервер. Я использовал Scenekit для рендеринга трехмерного мира и обработки физических расчетов.
Чтобы это работало, мне нужна возможность заставить симуляцию физики «вычислять» заданное количество кадров (применять силы, проверять коллизии, обновлять положения / ориентацию узлов), не отображая эти обновления. Таким образом, когда я определяю, что у клиента было неверное предсказание относительно того, что сервер отправляет обратно, я могу переориентировать все узлы в симуляции физики в соответствии с тем, что отправил сервер (включая установку физических свойств, таких как скорость / angular скорость ), а затем перемотайте вперед по «событиям», которые сервер еще не обработал, чтобы вернуться к текущему моменту времени клиента.
Я понимаю, что SceneKit не использует детерминированный c физический движок, но Я надеюсь, что смогу получить что-то, что выглядит «достаточно хорошо» (моя система ошибочных прогнозов имеет порог для определения того, не совпадает ли данный прогноз с серверным).
Процесс выглядит примерно так:
- Клиент запускает симуляцию физики локально на основе локальных входов / текущего локального состояния симуляции
- Клиент генерирует собственные пакеты хоста каждый раз, когда запускается симуляция физики, кэшируя их на текущую дату кадра.
- Клиент получает пакет хоста от сервера s определение того, как должна выглядеть физическая симуляция. Этот пакет основан на пакете, который клиент отправлял серверу в прошлом. Пакет хоста содержит идентификатор (дату), который клиент связал со своим пакетом, который он ранее отправил на сервер.
- Клиент просматривает свою предыдущую кэшированную версию того, как он видел мир физики в прошлом для этого Дата. Если он слишком сильно отличается от того, что отправил хост, мы определяем, что у нас было неверное предсказание и его необходимо исправить.
- Клиент переориентирует все узлы в сцене, чтобы они соответствовали состоянию пакета хоста ( установка положения, вращения, скорости, angular скорость, и т.д. c)
- Затем клиент перебирает все пакеты, которые он отправил на сервер ПОСЛЕ даты хост-пакета (клиентские пакеты, которые сервер имеет еще не обработанные как часть этого хост-пакета), и повторно применяет их к соответствующим узлам.
- Часть, с которой я борюсь: каждый раз, когда клиент применяет набор исторических c пакетов к узлов в части 6, мне нужно заставить симуляцию физики «обработать» эти изменения (применить силы, генерируемые этими пакетами, проверить наличие коллизий, обновить позиции узлов), прежде чем перейти к следующему набору пакетов, которых у сервера еще нет обработано.
Я попытался поиграть с timeStep физического мира, но похоже, что это увеличивает свойство также уменьшает прилагаемые силы за физический «цикл» (мы получаем больше физических симуляций, но конечный результат - просто более «точное» моделирование за счет перемещения физических тел на меньшие расстояния перед проверкой столкновений).
Я пробовал играть со скоростью физического мира, но а) увеличение этого значения снижает точность моделирования физики, б) по какой-то причине сцены, созданные в редакторе сцен, имеют скорость по умолчанию 6 вместо 1, поэтому определение подходящее значение здесь немного сбивает с толку, и c) похоже, что оно не повлияет до следующей попытки запуска симуляции.
Я попытался поиграть с sceneTime вида сцены, увеличивая его на 1 каждый раз, когда я обрабатываю набор исторических входных данных, которые, как я думал, работают, но при более тщательном исследовании кажется, что это ничего не дает.
Я попытался приостановить сцену, применить свои изменения и затем воспроизвести сцену, но приостановка сцены также приостанавливает симуляцию физики.
Есть ли способ, чтобы SCNPhysicsWorld обновлял физическую симуляцию вручную / многократно в al oop, без запуска каких-либо вызовов рендеринга?