ИНТЕГРАЦИЯПРОИЗВОДИТЕЛЬНОСТЬ
Производительность
Стоимость Crushform складывается из нескольких параметров: атласа и его слотов, разрешения каждой решётки, частоты перестроения коллизии и грязи, а также того, сколько шин, обломков и звуков может работать одновременно. На этой странице назван каждый параметр с его значением по умолчанию. Значения времени кадра здесь не приводятся, потому что они зависят от вашего проекта. Измеряйте свой проект командами из последнего раздела этой страницы.
Атлас и его слоты
Заголовок раздела «Атлас и его слоты»Каждый повреждённый кузов занимает один слот атласа, а слот хранит его решётку. Атлас — это Render Target в UCFSettings::Atlas. Его поверхность ограничена 4096 текселями с каждой стороны (MaxAtlasSize в CFTypes.h), а число слотов равно поверхности, делённой на один слот, то есть UCFSettings::SlotWidth на UCFSettings::SlotHeight.
- Решётка помещается в слот, когда её ResX, умноженный на ResZ, не больше
SlotWidth, а её ResY не большеSlotHeight.UCFProfile::Resolutionпрофиля по умолчанию равно 16 на 8 на 8, что помещается в слот по умолчанию 256 на 8. - Слот должен вмещать самую маленькую решётку, 4 на 4 узла. Слот шириной меньше 16 текселей или высотой меньше 4 текселей делает вмятины невидимыми, и об этом пишется в лог.
- Атлас должен быть linear B8G8R8A8: Render Target RTF_RGBA8 или текстура BGRA8 без sRGB. Любой другой формат тоже делает вмятины невидимыми.
Когда все слоты заняты, новый повреждённый кузов занимает слот самого дальнего повреждённого кузова, но только если тот находится дальше от камеры, чем новый. Самый дальний кузов тогда ждёт и рисуется неповреждённым, пока слот снова не освободится. Кузов на том же расстоянии, что и самый дальний, тоже ждёт.
Решётка и профиль
Заголовок раздела «Решётка и профиль»Профиль задаёт для каждого кузова стоимость решётки.
UCFProfile::Resolution(по умолчанию 16 на 8 на 8) — число узлов решётки. Большей решётке нужен больший слот, см. выше.UCFProfile::bDents(включено): когда он выключен, удары и сдавливания никогда не оставляют вмятин или царапин на кузове. Грязь при этом продолжает работать.UCFProfile::DirtScale(1): каждое отложение грязи на кузове умножается на это значение. При 0 у кузова нет сетки грязи вообще.UCFProfile::MaxPlausibleDeltaV(40 м/с): более сильный удар сообщается как равный этому пределу, а сервер отклоняет всё, что выше.
Отчёты и коллизия
Заголовок раздела «Отчёты и коллизия»UCFSettings::MaxReportsPerSecond(60) — сколько отчётов в секунду сервер принимает от одного компонента. Ведро токенов (token bucket) отправляющего клиента вмещает столько отчётов; ведро сервера в 1.5 раза вместительнее.UCFSettings::MaxReportsPerBatch(8) — максимум отчётов, которые клиент, управляющий автомобилем, отправляет за один кадр.UCFSettings::ScrapeReportInterval(0.1 с) — время между двумя отчётами о потёртостях одного компонента.UCFSettings::CollisionRebuildThreshold(2 см) иUCFSettings::CollisionRebuildInterval(0.5 с) управляют тем, когда коллизия кузова с вмятинами строится заново. Перестройка происходит, только когда узел сместился на это расстояние, и не раньше интервала.UCFSettings::bDeformCollision(вкл.): выключение снимает всю стоимость следования за вмятинами: ни блоков, ни выреза для оторванной детали, ни оболочки для расшатанной. Автомобили тогда сталкиваются так, как задумано в ассете, поэтому машина, вдавленная аварией, для того, что в неё врезается, не вдавлена, а оторванная деталь начинает внутри коллизии кузова, и решатель выталкивает её наружу. Профиль устройства может задатьCrushform.Collision.Deform 0для слабых устройств.UCFSettings::CollisionDeferFrames(1) принимает 0 или 1. При 1 тяжёлая сборка коллизии идёт в рабочем потоке: вырез для оторванной детали, перестройка кузова после вмятины и оболочка оторванной детали. Перестройка и вырез кузова оказываются на кузове до физики следующего кадра, а если рабочий поток к тому времени не закончил, игровой поток ждёт его там. Поэтому кадр удара остаётся коротким, а следующий кадр на медленной машине может оказаться длиннее. 0 строит всё в кадре удара. Профиль устройства может задать консольную переменнуюCrushform.Collision.DeferFrames, которая переопределяет значение проекта.UCFSettings::CollisionBlockTolerance(1.5 см) иUCFSettings::MaxCollisionBlocks(96) управляют тем, на сколько блоков разрезаются боксы и выпуклые формы кузова с вмятинами.MaxCollisionBlocks— это максимум блоков, на которые вместе разрезаются все боксы и выпуклые формы одного кузова. Значение, не превышающее число таких форм, ничего не режет: каждая остаётся одной оболочкой.
UCFSettings::DirtUpdateInterval(0.2 с) — время между двумя обновлениями грязи одного кузова.UCFSettings::DirtReferenceSpeed(8 м/с) — скорость шины, при которой значения скоростей поверхности действуют без изменений.UCFSettings::MaxDirtSpeedScale(2) ограничивает множитель, на который более быстрые шины увеличивают эти значения.UCFSettings::DirtEventInterval(0.5 с) иUCFSettings::DirtEventThreshold(0.02) ограничивают события изменения грязи одного кузова.
Бюджет шин решает, какие колёса деформируются. UCFTireSettings::Scope выбирает режим, а значения бюджета задаются настройками проекта Crushform Tire; см. Настройки проекта. Каждое значение также является переменной консоли: команда консоли или аргумент командной строки, задающие его, переопределяют значение проекта. Все переменные описаны в справочнике консольных команд:
Crushform.Tire.MaxWheels(30): шин, которые могут деформироваться одновременно. Собственный автомобиль зрителя деформируется всегда, даже сверх этого предела.Crushform.Tire.Radius(4000 см): расстояние от камеры, в пределах которого могут деформироваться шины других автомобилей.Crushform.Tire.LodDistance1(1500 см) иCrushform.Tire.LodDistance2(3000 см): расстояния, на которых шина трассирует более редкий веер лучей, а затем самый редкий веер по простой коллизии.Crushform.Tire.UpdateInterval(0.25 с): время между двумя проходами бюджета.Crushform.Tire.Hysteresis(0.15): насколько расширяются границы выделенной шины, чтобы шина на границе не мерцала.Crushform.Tire.OnScreenTolerance(0.5 с): сколько времени после последней отрисовки колесо ещё считается находящимся на экране.Crushform.Tire.Enable(1): при значении 0 каждая шина возвращается в круглую форму.
У сна покоящихся колёс нет переменной консоли: UCFTireSettings::SleepDistance (1 см) и UCFTireSettings::SleepAngleDeg (0.5 градуса): успокоившееся колесо, которое остаётся в этих пределах, может заснуть, и тогда оно перестаёт трассировать, пока его поза не изменится. Отрицательное SleepDistance выключает сон.
Обломки и разрушаемые объекты
Заголовок раздела «Обломки и разрушаемые объекты»UCFBreakableSettings::MaxLiveDebrisPieces(96) — число живых фрагментов обломков на мир. Самый старый фрагмент переиспользуется сверх этого предела.UCFBreakableSettings::MaxPersistentDebrisPieces(64) считает отдельно фрагменты определений, обломки которых существуют до респауна.UCFBreakableSettings::DebrisMaxSpawnDistanceCm(10000 см) — расстояние от локальной камеры, дальше которого разрушение не создаёт обломков, а разбитая стеклянная панель не бросает осколков.UCFBreakableSettings::AnyBodyCheckIntervalSeconds(0.1 с) — как часто забор с элементами, которые ломаются от любого тела, ищет тела рядом с ними.
Осколки стекла
Заголовок раздела «Осколки стекла»Crushform.Glass.ShardScale(1) — доля осколков каждого разрушения, которые разлетаются, от 0 до 1. Каждый осколок — частица Niagara-системы панели, поэтому их число и есть стоимость разрушения. Разрушение бросает доUCFGlassDefinition::MaxShardTilesраз по числу осколков определения: до 60 для ламинированного пресета (12 × 5) и до 64 для закалённого (16 × 4). 0.5 бросает примерно половину, а 0 не бросает ни одного: панель всё равно разбивается, но без частиц.Crushform.Glass.MaxLiveShards(512) — наибольшее число осколков разбитых панелей, живых одновременно, а 0 снимает предел. Он ограничивает стоимость завала, когда несколько панелей разбиваются вместе: 512 — это около восьми ламинированных разрушений, и этого хватает на все панели одной машины. Сверх предела первыми освобождаются осколки самых старых разбитых панелей, а осколки одного разрушения сверх предела отрезаются.Crushform.Glass.ShardSystemsPerFrame(1) — сколько систем осколков стартует в одном кадре, а 0 снимает ограничение. Остальные стартуют в следующих кадрах по порядку, сдвинутые вдоль своей скорости на время ожидания, но не больше чем на 0.25 с. Это не даёт разбитым панелям завала попасть в один кадр; увеличьте значение, если ваша игра может позволить себе кадр и хочет получить все осколки в момент аварии.- Каждая разбитая панель берёт из пула один компонент Niagara для своих осколков и возвращает его, когда осколки закончились, когда панель отремонтирована или в конце игры. Поэтому пул держит один компонент на разбитую панель, а не на осколок.
Отклик на удары и FX качения
Заголовок раздела «Отклик на удары и FX качения»UCFImpactFeedbackSettings::MaxAudibleDistanceCm(6000 см) иUCFImpactFeedbackSettings::MaxEffectDistanceCm(8000 см): удары, которые находятся дальше этих расстояний от локальной камеры, не воспроизводят звук и не создают эффект.UCFImpactFeedbackSettings::MaxVoiceSeconds(3 с) — самое долгое время, в течение которого воспроизводимый звук занимает слот голоса. У каждой строки набора ударов свойFCFImpactFeedbackEntry::MaxConcurrentVoices(по умолчанию 4) — число её звуков, которые могут играть одновременно.UCFImpactFeedbackSettings::MaxSoundsPerFrame(2) — наибольшее число звуков, которые стартуют в одном кадре, а 0 снимает предел. Остальные ждут следующих кадров, самые сильные первыми.UCFImpactFeedbackSettings::SoundQueueSeconds(0.15 с) — сколько звук сверх предела может ждать, прежде чем его отбросят. Профиль устройства может задатьCrushform.Impact.MaxSoundsPerFrameиCrushform.Impact.SoundQueueSeconds.UCFWheelSettings::FXTuningостанавливает FX качения автомобиля, пока он медленный.FCFRollingFXTuning::SleepSpeedKPHпо умолчанию равен 1 км/ч.
Профилирование аварии
Заголовок раздела «Профилирование аварии»Авария проходит свой путь удара в основном в игровом потоке, в несколько этапов, и у каждого этапа есть свой именованный scope. Чтобы увидеть, куда уходит время, введите stat namedevents, затем Trace.Start cpu,frame,bookmark перед аварией и Trace.Stop после неё и откройте трассу в Unreal Insights: каждый scope ниже виден под своим именем. Если UCFSettings::CollisionDeferFrames больше 0, вырез и оболочки идут в рабочем потоке, включая scope выреза ниже; Body collision block convex в любом случае идёт в рабочих потоках. Scope по этапам:
- Вход удара:
Deform Hit gate,Deform Ignored actors,Deform Hit mass,Deform Hit giving way,Deform Hit contacts,Deform Hit distance,Deform Hit velocitiesиDeform Hit root pose. - Решётка и отчёты:
Deform Mark chunks,Deform Debug hit,Deform Predict,Deform Damage schedule,Deform Render mark,Deform Part damage,Deform Shake offиDeform PartCollision wait. - Коллизия кузова:
Body collision cut subtract,Body collision cut prepare,Body collision cut watch,Body collision block convex,Collision blocks clip convex,Deform Collision poll,Body collision job start,Body collision job waitиBody collision job apply. - Навесные детали:
Hinge crowded,Hinge blocked,Hinge detach,Hinge start swing,Hinge loosen,Hinge joint createиHinge joint destroy. - Расстояние до тел:
Body distance,Body distance poseиBody distance shapes. - Осколки стекла:
Glass Shards,Glass Shard data,Glass Shard spawn,Glass Shard hitsиGlass Apply verdict. - Отклик на удары:
Play Impact sound,Play Impact effectиImpact sound queue.
Сборка коллизии кузова идёт в рабочем потоке: в кадре аварии виден старт задания, который копирует решётку, читаемую рабочим потоком, и его применение в кадре, в котором задание завершилось. Ожидание появляется, когда срок наступил раньше, чем рабочий поток закончил, или когда сборку, которая ещё шла, отбросили (ремонт, повторное прикрепление, пересобранный или потерянный кузов, конец игры).
Проверка работы
Заголовок раздела «Проверка работы»Нажмите Play In Editor на уровне с повреждённым кузовом, затем откройте консоль.
Crushform.Statsсначала выводит атлас в таком виде. Растущее число ждущих кузовов или вытеснений означает, что атлас заполнен.
Crushform atlas: <used> of <total> slots used, <waiting> waiting, <evictions> evictions, <uploads> uploads.Затем он выводит по одной строке для каждого повреждаемого эктора в мире: server lattice, где этот инстанс хранит повреждение, и client view, где он рисует повреждение сервера. Строка продолжается поколением эктора, его ожидающими отчётами и чанками, а также счётчиками: числом ударов, а также отправленных, принятых и отклонённых отчётов, построениями коллизии с самым долгим в миллисекундах, ожиданиями коллизии (сборками, которых игровой поток дожидался в срок), удержанными деталями (деталями, которые ждали своего выреза, прежде чем упасть), и оболочками деталей. Процесс выделенного сервера, который ничего не рисует, вместо первой строки выводит Crushform atlas: none in this process (a dedicated server draws nothing).
stat Crushformвыводит на экран временные шаги модуля core, такие как тик деформации, обновление грязи и перестройка коллизии кузова, каждый в миллисекундах. Остальные группы stat:CrushformTire,CrushformBreakable,CFBreakableInstances,CrushformDebris,CFPropContact,CFImpactFeedback,CrushformVehicle,CrushformChaos,CrushformWheel,CrushformEngine,CrushformPlaygroundиCrushformDebug.
Решение проблем
Заголовок раздела «Решение проблем»Вмятины пропадают на части повреждённых автомобилей.
Причина: атлас заполнен. Самые дальние повреждённые кузова ждут слота и рисуются неповреждёнными, пока один из слотов не освободится. Crushform.Stats показывает число ждущих и вытеснений.
Решение: увеличьте UCFSettings::Atlas. Число слотов — это размер атласа, делённый на размер слота, до предела 4096 текселей, поэтому больший атлас вмещает больше повреждённых кузовов одновременно.
Вмятин не появляется, и в логе сказано, что слот слишком мал.
Причина: UCFSettings::SlotWidth меньше 16 текселей или UCFSettings::SlotHeight меньше 4.
Решение: увеличьте размер слота минимум до 16 на 4 тексела. По умолчанию 256 на 8.
Вмятин не появляется, и в логе назван формат пикселей атласа. Причина: атлас не linear B8G8R8A8. Текстура sRGB или любой другой формат отклоняются. Решение: используйте Render Target RTF_RGBA8 или текстуру BGRA8 с выключенным sRGB.