МУЛЬТИПЛЕЕРПОДКЛЮЧИВШИЕСЯ ПОЗЖЕ ИГРОКИ
Подключившиеся позже игроки
Игрок, который подключается к игре после того, как машина получила повреждения, не видит аварию, но повреждения остаются. Сервер хранит состояние каждого тела, и инстанс, который подключается позже, получает это состояние вместе с репликацией. Отдельной настройки для подключившихся позже нет. Поведение возникает из того, как каждый класс реплицирует собственное состояние, поэтому эта страница проходит классы по одному.
Что получает подключившийся
Заголовок раздела «Что получает подключившийся»Вмятины. Чанки сервера приходят одним реплицированным массивом. Подключившийся инстанс строит свою решётку из них. Геометрия решётки вычисляется на каждом инстансе по тем же ассетам и настройкам, поэтому оба инстанса должны использовать один профиль. Чанк, индекс которого выходит за пределы решётки или чья контрольная сумма не совпадает, засчитывается как неверный, и инстанс оставляет тот чанк, который у него был. Чанк другого поколения ремонта ждёт, пока не придёт нужное поколение.
OnDamageChanged срабатывает, как только чанки построили решётку, если повреждение не равно нулю. Подключившемуся для этого не нужен отдельный путь в коде.
Грязь. Грязь локальна для каждого инстанса и никогда не передаётся по сети. Кузов подключившегося начинается без грязи и строит свою из колёс, которые видит. Мойка реплицируется через счётчик мойки, поэтому подключившийся после мойки тоже начинает чистым.
Навесные детали. Список деталей, которые сервер отделил, приходит вместе с поколением. Деталь, которую сервер отделил, скрывается сразу, без падения, когда подключившийся впервые видит кузов. На этом месте срабатывает On Detached с bHiddenAtOnce, равным true, на первом тике таймера после BeginPlay. Её место также вырезается из коллизии кузова, чтобы другие машины встречали открытое место. Деталь, которую отпустили качаться, начинает качаться из закрытого положения, и для неё срабатывает On Started Swinging.
Разрушаемые элементы. Уровень каждого элемента приходит вместе с поколением кузова, и подключившийся показывает каждый элемент на этом уровне. Первый показ элемента не запускает событие уровня. Срабатывает ли событие для уже имеющихся повреждений подключившегося, зависит от порядка прихода: если уровни элементов приходят до того, как эктор начал игру, выравнивание при начале игры событий не вызывает; если они приходят позже, каждое изменение уровня вызывает событие. Недавние события разрушения несут время сервера. Событие старше Break Event Max Age Seconds не проигрывает разлёт. Эта настройка, по умолчанию 2 секунды, находится в Project Settings › Plugins › Crushform Breakable › Network. Подключившийся, чьё состояние игры ещё не пришло, считает каждое событие устаревшим.
Поваленные деревья. Состояние дерева реплицируется: поддалось ли оно или успокоилось, место и поворот, где оно успокоилось, и время сервера последнего изменения. Подключившийся ставит поваленное дерево туда, где оно успокоилось. OnYielded, OnSettled и OnRespawned не срабатывают для состояния старше Break Event Max Age Seconds или до того, как пришло состояние игры. OnHit и OnLanded приходят из локальной физики, поэтому их не задерживают. Дерево, которое прошло респаун, пока подключившегося не было, сразу переходит в позу покоя.
Стёкла. Трещины каждой панели реплицируются, и подключившийся их видит. Первая репликация панели не воспроизводит звук, поэтому трещина, которую подключившийся не видел, ничего не воспроизводит.
Опасности. Движущиеся ловушки полигона Proving Ground не реплицируют ничего. Каждый инстанс вычисляет их позу по игровому времени сервера, поэтому подключившийся видит ту же фазу.
Проверка работы
Заголовок раздела «Проверка работы»Запустите listen-сервер, затем врежьте седан в стену, в дерево и в забор. Дерево падает и забор ломается, только когда в них врезается машина, поэтому тест требует езды, а не консольной команды. Затем добавьте игрока, который подключается после повреждений. Есть два способа:
- В редакторе. Откройте Editor Preferences › General › Experimental › PIE и отметьте Allow late joining. Задайте Net Mode — Play As Listen Server и нажмите Play. Когда уровень запустится, нажмите Add Client на панели Play. Новый клиент подключается к работающему серверу.
- Вторым экземпляром игры. Запустите его из папки
Binaries\Win64движка с адресом сервера:UnrealEditor.exe "<path to your .uproject>" 127.0.0.1:17777 -game -windowed. Порт — это Server Port в настройках Play, по умолчанию 17777.
В подключившемся экземпляре введите Crushform.Stats. Строка седана говорит client view, с поколением сервера и числом чанков больше нуля, а счётчик received растёт по мере прихода чанков. Вмятина, которую сделал сервер, видна на экране подключившегося. Строка имеет те же поля, что и строка в Репликации и предсказании. Деталь, которую сервер отделил, вообще не показывается на кузове подключившегося.
Решение проблем
Заголовок раздела «Решение проблем»На седане подключившегося нет вмятин
Заголовок раздела «На седане подключившегося нет вмятин»Причина. Подключившийся засчитывает как неверные чанки, которые не может использовать. Чанк неверен, когда его контрольная сумма не совпадает или его индекс выходит за пределы решётки подключившегося. Это случается, когда два инстанса строят разные решётки, например потому что используют разные ассеты профиля или разные настройки.
Решение. Прочитайте счётчик bad в Crushform.Stats на подключившемся. Дайте обеим сборкам один и тот же ассет профиля и одни и те же настройки, и проверьте счётчик снова.
Трещина на экране подключившегося беззвучна
Заголовок раздела «Трещина на экране подключившегося беззвучна»Причина. Панель, на которой ещё ничего не нарисовано, беззвучна, поэтому первая репликация панели у подключившегося не воспроизводит звук трещины. Панель, которую реплицированные уровни уже разрушили, тоже беззвучна, и вместо этого её разрушение проигрывает Break.
Решение. Читайте трещины панелей, когда подключившийся подключается, как это делает запись о дереве ниже. Плагин не воспроизводит звук для трещины, которую подключившийся не видел.
Дерево, которое упало до подключения игрока, не вызывает OnYielded
Заголовок раздела «Дерево, которое упало до подключения игрока, не вызывает OnYielded»Причина. OnYielded не срабатывает для состояния старше Break Event Max Age Seconds, то есть по умолчанию 2 секунды, и не срабатывает до прихода состояния игры.
Решение. Читайте состояние дерева, когда подключившийся подключается, вместо ожидания события. Большее значение Break Event Max Age Seconds позволяет срабатывать и более старым событиям, но тогда и более старые события разрушения будут проигрывать разлёт.