МИРОБЛОМКИ
Обломки
Что это делает
Заголовок раздела «Что это делает»Когда секция забора или окно ломается, её запечённые фрагменты разлетаются. Они приземляются, катятся, лежат какое-то время и уходят в землю. Обломки — косметическая часть поломки. Они не реплицируются: каждый инстанс выбрасывает свои фрагменты, когда видит поломку.
Фрагменты обломков — физические тела. Как с ними встречаются автомобили и пешки, задают определение и профиль коллизии, как описано в разделах ниже.
Как это работает
Заголовок раздела «Как это работает»Обломки берутся из пула. Мировая подсистема UCFDebrisSubsystem держит фиксированный набор компонентов фрагментов и переиспользует их. Когда элемент ломается, подсистема берёт свободные фрагменты из пула и выбрасывает запечённые фрагменты элемента. Фрагменты существуют только на этом локальном инстансе.
- Кто его симулирует. Обломки живут на клиенте. Выделенный сервер никогда не создаёт подсистему, поэтому не создаёт и фрагменты.
- Где появляется. Поломка дальше
DebrisMaxSpawnDistanceCm(10000 см) от локальной камеры не порождает обломков. - Бросок. Фрагменты рядом с точкой удара получают больше скорости ударяющего тела. Фрагменты далеко от неё в основном опрокидываются. Фрагмент в точке удара получает
InheritVelocityFraction(0,6) скорости тела плюсScatterSpeedCmS(300 см/с) наружу и вверх. Толчок ослабевает наImpactFalloffCm(150 см). - Коллизия. Фрагмент сталкивается с миром, с целыми объектами и с другими фрагментами, но не с пешками. Какой тип объекта он использует, задаёт Debris Collision Profile в настройках проекта. Определение с выключенным
bDebrisCollidesWithDebrisзаставляет его фрагменты игнорировать другие фрагменты. - Автомобили. Кузова автомобилей проходят сквозь фрагмент, если только определение не задаёт
bDebrisPushedByVehicles. Тогда автомобиль толкает фрагмент в одну сторону в течениеDebrisVehicleContactSeconds(3,5 с) после поломки. Фрагмент, лежащий на автомобиле, продолжает толкаться, пока не окажется за его пределами. Толкнутый фрагмент никогда не считается ударом по автомобилю. - Время жизни. Фрагмент, который уснул, лежит неподвижно
DebrisRestSeconds(3 с), затем уходит в землю заDebrisSinkSeconds(1 с): он опускается прямо вниз на собственный размер — свою самую длинную сторону с учётом масштаба плюс 10 см, — уменьшаясь до пятой части, и в конце скрывается.DebrisLifetimeSeconds(8 с) — жёсткий предел его жизни, лежит он или нет. - Бюджет. Игра держит не больше
MaxLiveDebrisPieces(96) фрагментов; самый старый переиспользуется сверх этого. Фрагменты определения, обломки которого живут до респауна элемента (bDebrisLastsUntilRespawn), учитываются отдельно, доMaxPersistentDebrisPieces(64).
Фрагменты, которые выбрасывает поломка, — это запечённые фрагменты определения элемента. Как запекается определение, см. на странице Заборы и объекты.
Настройка
Заголовок раздела «Настройка»У обломков нет собственного ассета. Каждое определение разрушаемого объекта задаёт свои обломки, а настройки проекта задают бюджет для всех них.
- В Content Browser откройте определение забора,
DA_CF_FencePicket, из Plugins › Crushform Content › Fences (или своё определение). - В категории Debris задайте Debris Lifetime Seconds, Debris Rest Seconds и Debris Sink Seconds. Включите Debris Pushed by Vehicles, если автомобили должны толкать фрагменты.
- Откройте Project Settings › Plugins › Crushform Breakable. В группе Debris задайте Max Live Debris Pieces и Debris Collision Profile. Подсказка профиля просит выбрать такой, который опирается на мир и игнорирует пешки. По умолчанию стоит
None, и фрагмент становится только физическим: его не находит ни одна трассировка, развёртка или перекрытие.
| Debris | ||
|---|---|---|
| Max Live Debris Pieces | 96 | |
| Max Persistent Debris Pieces | 64 | |
| Debris Max Spawn Distance Cm | 10000.0 | |
| Debris Impact Cooldown Seconds | 0.25 | |
| Debris Min Impulse Per Kg | 50.0 | |
| Debris Impulse Per Kg for Full Intensity | 600.0 | |
| Debris Collision Profile | None | |
Использование
Заголовок раздела «Использование»У подсистемы нет узла Blueprint, поэтому Blueprint не может менять пул или порождать фрагменты. Он может читать значения Debris определения, потому что они BlueprintReadOnly. График ниже хранит определение забора в переменной и выводит его Debris Lifetime Seconds, когда срабатывает пользовательское событие.
Игра, которая хочет прочитать или очистить пул, делает это в C++:
#include "CFDebrisSubsystem.h"
void ReportAndClearDebris(const UObject* WorldContext){ if (UCFDebrisSubsystem* Debris = UCFDebrisSubsystem::Get(WorldContext)) { UE_LOG(LogTemp, Log, TEXT("Live debris pieces: %d"), Debris->GetLivePieceCount()); Debris->ReleaseAllPieces(); }}Сигнатуры: static UCFDebrisSubsystem* Get(const UObject* WorldContext), int32 GetLivePieceCount() const и void ReleaseAllPieces(). ReleaseAllPieces возвращает все живые фрагменты в пул сразу, без ухода в землю.
Игра, которая даёт пулу собственную камеру и отклик, реализует ICFBreakableHost в C++ и регистрирует его через SetHost. У интерфейса два метода: TryGetBreakableViewLocation(FVector&) const, который задаёт точку, от которой отсекаются обломки, и PlayBreakableFeedback(const FCFBreakableFeedback&), который проигрывает звук и эффект поломки. Это только C++: в Blueprint его реализовать нельзя.
#include "CFBreakableHost.h"#include "CFDebrisSubsystem.h"
class FMyBreakableHost : public ICFBreakableHost{public: virtual bool TryGetBreakableViewLocation(FVector& OutLocation) const override; virtual void PlayBreakableFeedback(const FCFBreakableFeedback& Feedback) override;};
// The pool does not own the host: keep it alive while it is registered.void RegisterBreakableHost(const UObject* WorldContext, ICFBreakableHost* Host){ if (UCFDebrisSubsystem* Pool = UCFDebrisSubsystem::Get(WorldContext)) { Pool->SetHost(Host); }}Блоку C++ нужен модуль CrushformBreakable в вашем Build.cs (см. Установка). Если в настройках Crushform Impact Feedback не выключено Use Default Breakable Host, host-объект плагина по умолчанию, UCFImpactBreakableHost, регистрирует себя и сопоставляет поломки с событиями удара. См. Отклик на удары.
Примитив, который представляет один элемент компонента элементов, реализует в C++ ICFBreakableUnitPart через GetBreakableUnits. Так удар по примитиву возвращается к своему элементу. И это тоже только C++.
Основные настройки
Заголовок раздела «Основные настройки»Значения обломков находятся в определении разрушаемого объекта, в категории Debris. Бюджет и профиль коллизии — в настройках проекта. Значения по умолчанию — от плагина.
| Свойство | Что делает | По умолчанию |
|---|---|---|
UCFBreakableDefinition::bDebrisLastsUntilRespawn | Фрагменты лежат, пока элемент не встанет снова, вместо ухода в землю. | false |
UCFBreakableDefinition::bDebrisPushedByVehicles | Кузова автомобилей толкают фрагменты в одну сторону на время контакта. | false |
UCFBreakableDefinition::DebrisVehicleContactSeconds | Как долго после поломки автомобили толкают фрагменты. 0 означает, пока они лежат. | 3.5 |
UCFBreakableDefinition::bDebrisCollidesWithDebris | Сталкивается ли фрагмент с другими фрагментами. | true |
UCFBreakableDefinition::DebrisLifetimeSeconds | Жёсткий предел жизни фрагмента, лежит он или нет. | 8 |
UCFBreakableDefinition::DebrisRestSeconds | Сколько фрагмент лежит неподвижно, прежде чем уйти в землю. | 3 |
UCFBreakableDefinition::DebrisSinkSeconds | Сколько фрагменту нужно, чтобы уйти в землю. | 1 |
UCFBreakableDefinition::InheritVelocityFraction | Доля скорости ударяющего тела, которую получает фрагмент в точке удара. | 0.6 |
UCFBreakableDefinition::ScatterSpeedCmS | Дополнительная скорость наружу и вверх в точке удара, в см/с. | 300 |
UCFBreakableDefinition::ImpactFalloffCm | Фрагменты на таком расстоянии от точки удара получают самый слабый бросок. | 150 |
UCFBreakableSettings::MaxLiveDebrisPieces | Живые фрагменты на мир. Сверх этого переиспользуется самый старый. | 96 |
UCFBreakableSettings::MaxPersistentDebrisPieces | Живые фрагменты определений, обломки которых живут до респауна. | 64 |
UCFBreakableSettings::DebrisMaxSpawnDistanceCm | Поломка дальше этого расстояния от локальной камеры не порождает обломков. | 10000 |
UCFBreakableDefinition::MaxAngularSpeedDegS | Наибольшее вращение, которое получает брошенный фрагмент, в градусах в секунду. | 540 |
UCFBreakableSettings::DebrisCollisionProfile | Профиль коллизии фрагментов. | None |
UCFBreakableSettings::DebrisImpactCooldownSeconds | Наименьшее время между двумя откликами на удар одного фрагмента. | 0.25 |
UCFBreakableSettings::DebrisMinImpulsePerKg | Импульс на килограмм, который нужен удару фрагмента, чтобы проиграть отклик. | 50 |
UCFBreakableSettings::DebrisImpulsePerKgForFullIntensity | Импульс на килограмм, при котором удар фрагмента проигрывается в полную силу. | 600 |
Проверка работы
Заголовок раздела «Проверка работы»В любой сборке, кроме Shipping, откройте консоль клавишей тильда.
stat CrushformDebrisпоказывает циклы обломков. Число живых в пуле — этоGetLivePieceCount, который читает пример на C++ выше.- Сломайте секцию забора на
Lvl_ProvingGround. Фрагменты разлетаются, приземляются, лежат и уходят в землю. - Въедьте автомобилем в штакетину, для которой определение задало
bDebrisPushedByVehicles. Автомобиль толкает фрагмент в течениеDebrisVehicleContactSeconds, а затем проезжает сквозь него. - Откройте панель отладки и нажмите Clear debris в разделе World. Каждый фрагмент сразу возвращается в пул. См. Режим отладки.
Устранение неполадок
Заголовок раздела «Устранение неполадок»Поломка не выбрасывает фрагментов
Заголовок раздела «Поломка не выбрасывает фрагментов»Причина. Определение не запечено, а определение без запечённых фрагментов их не порождает. Либо поломка происходит дальше DebrisMaxSpawnDistanceCm (10000 см) от локальной камеры, либо на выделенном сервере, который обломки не порождает никогда.
Решение. Запеките определение командой Bake Pieces. Чтобы проверить поломку, встаньте ближе к ней. Выделенный сервер по замыслу обломков не показывает: их показывают клиенты.
Фрагменты исчезают слишком рано
Заголовок раздела «Фрагменты исчезают слишком рано»Причина. Пул заполнен. Сверх MaxLiveDebrisPieces (96) переиспользуется самый старый фрагмент, а фрагмент старше DebrisLifetimeSeconds (8 с) удаляется, даже если он всё ещё лежит.
Решение. Увеличьте Max Live Debris Pieces или задайте DebrisLifetimeSeconds больше. Для фрагментов, которые должны оставаться до респауна элемента, включите bDebrisLastsUntilRespawn, а если бюджет для них кончается, увеличьте Max Persistent Debris Pieces.
Автомобиль проезжает сквозь фрагменты
Заголовок раздела «Автомобиль проезжает сквозь фрагменты»Причина. bDebrisPushedByVehicles выключен, а это значение по умолчанию. Или оно включено, но DebrisVehicleContactSeconds уже истекло, после чего автомобили снова проезжают сквозь фрагмент.
Решение. Включите Debris Pushed by Vehicles для фрагментов, которые должны двигаться под автомобилем, и задайте Debris Vehicle Contact Seconds равным тому, сколько должен длиться толчок.
Пешка проходит сквозь фрагменты
Заголовок раздела «Пешка проходит сквозь фрагменты»Причина. Фрагменты сталкиваются с миром, с целыми объектами и друг с другом, но не с пешками. Так задумано, и это задаёт Debris Collision Profile.
Решение. Чтобы фрагменты останавливали пешку, задайте в Debris Collision Profile профиль, который блокирует пешки. Затем проверьте, что фрагменты всё ещё опираются на мир.
Удар по фрагменту проигрывает тег удара, который определение называет как Debris Impact Tag, или Crushform.Impact.Prop.Debris, если поле пусто. Когда он проигрывается, решают ограничения по задержке и импульсу выше. О тегах и их звуках см. Отклик на удары.
