Перейти к содержимому
CRUSHFORMV1.1.0
ПОЛУЧИТЬ НА FAB

МИРОБЛОМКИ

Обломки

Когда секция забора или окно ломается, её запечённые фрагменты разлетаются. Они приземляются, катятся, лежат какое-то время и уходят в землю. Обломки — косметическая часть поломки. Они не реплицируются: каждый инстанс выбрасывает свои фрагменты, когда видит поломку.

Фрагменты обломков — физические тела. Как с ними встречаются автомобили и пешки, задают определение и профиль коллизии, как описано в разделах ниже.

Седан сзади на Proving Ground, в воздухе летят куски штакетного забора, а вокруг него лежат на земле.
Куски штакетника после поломки: лежат на земле и летят в воздухе вокруг седана.

Обломки берутся из пула. Мировая подсистема 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).

Фрагменты, которые выбрасывает поломка, — это запечённые фрагменты определения элемента. Как запекается определение, см. на странице Заборы и объекты.

У обломков нет собственного ассета. Каждое определение разрушаемого объекта задаёт свои обломки, а настройки проекта задают бюджет для всех них.

  1. В Content Browser откройте определение забора, DA_CF_FencePicket, из Plugins › Crushform Content › Fences (или своё определение).
  2. В категории Debris задайте Debris Lifetime Seconds, Debris Rest Seconds и Debris Sink Seconds. Включите Debris Pushed by Vehicles, если автомобили должны толкать фрагменты.
  3. Откройте Project Settings › Plugins › Crushform Breakable. В группе Debris задайте Max Live Debris Pieces и Debris Collision Profile. Подсказка профиля просит выбрать такой, который опирается на мир и игнорирует пешки. По умолчанию стоит None, и фрагмент становится только физическим: его не находит ни одна трассировка, развёртка или перекрытие.
Debris
Max Live Debris Pieces96
Max Persistent Debris Pieces64
Debris Max Spawn Distance Cm10000.0
Debris Impact Cooldown Seconds0.25
Debris Min Impulse Per Kg50.0
Debris Impulse Per Kg for Full Intensity600.0
Debris Collision ProfileNone
Группа Debris в настройках проекта, в разделе Plugins > Crushform Breakable.

У подсистемы нет узла Blueprint, поэтому Blueprint не может менять пул или порождать фрагменты. Он может читать значения Debris определения, потому что они BlueprintReadOnly. График ниже хранит определение забора в переменной и выводит его Debris Lifetime Seconds, когда срабатывает пользовательское событие.

График хранит определение забора в переменной и выводит его 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, если поле пусто. Когда он проигрывается, решают ограничения по задержке и импульсу выше. О тегах и их звуках см. Отклик на удары.