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

МИРОТКЛИК НА УДАРЫ

Отклик на удары

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

Если включена консольная переменная LogHits, плагин сообщает о каждом ударе, который он оценивает. В сеансе игры в редакторе каждый удар оставляет маркер на 5 секунд: сферу в точке удара со стрелкой вдоль нормали поверхности. Маркер зелёный, когда удар проигрывается, жёлтый — для удара внутри устойчивого контакта, и красный — для удара ниже минимума. Каждый оценённый удар также пишет одну строку в лог, в категорию LogCrushformImpact, в таком виде:

<owner>: <component> (bone <bone>) hit by <actor> / <component>, impulse N, support N, mass N kg, other mass N kg, normal Z N, intensity N at <point>: <verdict>

Вердикт — played, below minimum или steady contact, suppressed.

Каждый удар — это gameplay-тег, например Crushform.Impact.Prop.Break.Wood, который проигрывается в точке. Остальное делает UCFImpactFeedbackSubsystem:

  1. Он находит строку для тега в активном наборе ударов. Если в наборе нет строки для этого точного тега, используется строка ближайшего родительского тега, у которого она есть. Если ни одна строка не подходит, ничего не проигрывается.
  2. Он проигрывает один звук из строки, выбранный случайно, и порождает эффект Niagara строки с заданным параметром Intensity.
  3. Он масштабирует громкость между значениями Volume by Intensity строки и выбирает высоту тона из её Pitch Range.
  4. Он применяет фильтры строки: удар ниже Min Intensity ничего не проигрывает, источник, который недавно проигрывал звук, ждёт свой Cooldown Seconds, а пока заняты Max Concurrent Voices строки, новый удар проигрывает эффект, но без звука. На весь плагин в одном кадре стартует не больше Max Sounds Per Frame звуков (по умолчанию 2): остальные ждут следующих кадров, самые сильные первыми, а звук, который всё ещё ждёт после Sound Queue Seconds (0.15 с), отбрасывается. Если запустить в одном кадре звуки аварии, которая даёт их сразу много, получится рывок, поэтому их растягивают на несколько кадров. Эффекты в очередь не ставятся.

Набор ударов — ассет данных UCFImpactFeedbackSet. Набор проекта по умолчанию — /Crushform/Impact/DA_CF_ImpactFeedback, со строкой для каждого тега плагина. Проект может создать свой набор и указать его в Default Set.

Удары исходят от компонентов, которые сидят на теле. Вы добавляете их в меню Add редактора Blueprint, где все три перечислены в разделе Custom, а не в Crushform:

  • UCFImpactFeedbackComponent сообщает об ударах наблюдаемого примитива с Event Tag, который ему задан (по умолчанию Crushform.Impact.Hit). Он ничего не наблюдает, пока вы не передадите ему примитив через SetObservedPrimitive, это только C++. Удар оценивается по импульсу на килограмм тела. Ниже Min Impulse Per Kg (50) он молчит, а в полную силу звучит при Impulse Per Kg for Full Intensity (600). Устойчивый контакт, например тело, опирающееся на землю, не повторяет удар.
  • UCFNetImpactFeedbackComponent сам наблюдает корневой примитив своего владельца и также передаёт удар другим игрокам. Передача обычно ждёт не меньше Min Relay Interval Seconds (0,5 с) и приходит раньше для заметно более сильного удара.
  • UCFPartImpactFeedbackComponent проигрывает удар навесной детали, когда она достигает конца своего хода. Деталь, которая ударяется о закрытый конец, проигрывает Slam Event Tag, по умолчанию Crushform.Impact.Part.Slam. Деталь, отброшенная далеко в открытый конец, проигрывает Open Slam Event Tag, по умолчанию Crushform.Impact.Part.Slam.Open, а набор ударов без строки для этого тега проигрывает строку Part.Slam.

Автомобиль получает эти компоненты от своего адаптера. Определение разрушаемого объекта называет свои теги, а пустой тег проигрывает тег плагина по умолчанию.

Плагин объявляет 19 тегов ударов в CFImpactTags:

ТегПроигрывается, когда
Crushform.ImpactКорень событий ударов.
Crushform.Impact.HitТело с компонентом отклика на удар во что-то врезается.
Crushform.Impact.Vehicle.CrashКузов автомобиля ударяется о что-то твёрдое.
Crushform.Impact.Prop.BreakРазрушаемый объект, который не является стеклом, ломается.
Crushform.Impact.Prop.Break.WoodДеревянный объект разваливается, например секция деревянного забора.
Crushform.Impact.Prop.Break.MetalМеталлический объект отламывается целиком, например панель забора из сетки-рабицы.
Crushform.Impact.Prop.DebrisФрагмент обломков разрушаемого объекта во что-то попадает.
Crushform.Impact.Prop.Debris.WoodДеревянный фрагмент обломков приземляется.
Crushform.Impact.Prop.Debris.MetalМеталлический фрагмент обломков приземляется.
Crushform.Impact.Glass.CrackСтеклянная панель трескается.
Crushform.Impact.Glass.BreakСтеклянная панель ломается и рассыпается.
Crushform.Impact.Glass.ShardОсколок стекла во что-то попадает.
Crushform.Impact.Tree.HitТело толкает разрушаемое дерево.
Crushform.Impact.Tree.BreakРазрушаемое дерево ломается и начинает падать.
Crushform.Impact.Tree.BendРазрушаемый столб поддаётся и остаётся наклонённым.
Crushform.Impact.Tree.LandУпавший ствол дерева ударяется о землю.
Crushform.Impact.Part.HitДеталь автомобиля, которая качается на шарнире или оторвалась, во что-то попадает.
Crushform.Impact.Part.SlamДеталь автомобиля, качающаяся на шарнире, ударяется о закрытый конец хода.
Crushform.Impact.Part.Slam.OpenДеталь автомобиля, качающаяся на шарнире и отброшенная далеко, ударяется о открытый конец хода.

Строка набора для тега — это FCFImpactFeedbackEntry. Её Sounds — список, один из которого проигрывается случайно, поэтому для вариаций не нужен отдельный звуковой cue. Её Effect — система Niagara, которая получает float-параметр Intensity. Её Attenuation формирует звук на расстоянии.

Здесь используется поставляемый набор, а затем создаётся собственная строка.

  1. В Content Browser набор по умолчанию находится в Plugins › Crushform Content › Impact.
  2. Откройте DA_CF_ImpactFeedback. Его список Entries содержит по одной строке на тег. Найдите строку Crushform.Impact.Prop.Break.Wood, чтобы увидеть, что хранит строка: Sounds, Effect, Attenuation, диапазоны громкости и высоты тона и фильтры.
Impact
Entries18 Array elements
Index [ 0 ]Crushform.Impact.Prop.Break
Index [ 1 ]Crushform.Impact.Prop.Debris
Index [ 2 ]Crushform.Impact.Glass.Crack
Index [ 3 ]Crushform.Impact.Glass.Break
Index [ 4 ]Crushform.Impact.Glass.Shard
Index [ 5 ]Crushform.Impact.Vehicle.Crash
Index [ 6 ]Crushform.Impact.Hit
Index [ 7 ]Crushform.Impact.Tree.Hit
Index [ 8 ]Crushform.Impact.Tree.Break
Index [ 9 ]Crushform.Impact.Tree.Bend
Index [ 10 ]Crushform.Impact.Tree.Land
Index [ 11 ]Crushform.Impact.Prop.Break.Wood
Event TagCrushform.Impact.Prop.Break.Wood
Sounds5 Array elements
EffectNS_CF_ImpactWood_Break
AttenuationSA_CF_CarImpact
Volume by Intensity0.41.0
Pitch Range0.921.08
Min Intensity0.05
Cooldown Seconds0.1
Max Concurrent Voices4
Surface Overrides0 Array element
Index [ 12 ]Crushform.Impact.Prop.Debris.Wood
Index [ 13 ]Crushform.Impact.Prop.Break.Metal
Index [ 14 ]Crushform.Impact.Prop.Debris.Metal
Index [ 15 ]Crushform.Impact.Part.Hit
Index [ 16 ]Crushform.Impact.Part.Slam
Index [ 17 ]Crushform.Impact.Part.Slam.Open
Entries ассета DA_CF_ImpactFeedback с раскрытой строкой Crushform.Impact.Prop.Break.Wood.
  1. Чтобы сделать свой набор, выберите Add › Miscellaneous › Data Asset, укажите класс CFImpact Feedback Set и добавьте строку в Entries. Задайте её Event Tag равным нужному тегу и заполните её звуки и эффект.
  2. Откройте Project Settings › Plugins › Crushform Impact Feedback. Задайте Default Set равным вашему набору. Набору нужны только строки для тегов, которые вы хотите слышать. У тега без строки используется строка его ближайшего родителя, поэтому строка для Crushform.Impact покрывает все теги, у которых своей строки нет.
  3. Чтобы дать автомобилю его удары, оставьте включённым Impact Feedback на адаптере, как это есть по умолчанию. Его CF_ImpactFeedback проигрывает Impact Event Tag адаптера. CF_PartImpactFeedback сохраняет собственные теги, и адаптер создаёт его только при включённом Dirt and Dents. Таблица компонентов описана на странице Основные понятия.

В своём проекте Blueprint проигрывает удар узлом Play Impact. Он принимает тег, точку, нормаль (по умолчанию вверх), интенсивность от 0 до 1, поверхность и необязательный источник. Удары от одного источника делят общую задержку. График ниже проигрывает удар поломки дерева в точке эктора, когда срабатывает пользовательское событие.

График проигрывает удар поломки дерева в точке эктора, когда срабатывает пользовательское событие.

Play Impact проигрывается только на инстансе, который его вызывает, а на выделенном сервере не проигрывается вовсе. Игра, в которой каждый игрок должен его слышать, вызывает его на каждом инстансе, например из multicast-события.

То же в C++ использует функцию библиотеки, с тегами из CFImpactTags. Блоку нужен модуль CrushformImpact в вашем Build.cs; список модулей есть на странице Установка.

#include "CFImpactFeedbackLibrary.h"
#include "CFImpactTags.h"
void PlayTreeBreakHere(const UObject* WorldContext, const FVector& Location)
{
UCFImpactFeedbackLibrary::PlayImpact(WorldContext, CFImpactTags::Impact_Tree_Break, Location);
}

Сигнатура: static void PlayImpact(const UObject* WorldContextObject, FGameplayTag Tag, FVector Location, FVector Normal = FVector::UpVector, float Intensity = 1.f, EPhysicalSurface Surface = SurfaceType_Default, const UObject* Source = nullptr). UCFImpactFeedbackSubsystem::Get(WorldContext)->PlayImpact(FCFImpactEvent) — тот же вызов уровнем ниже, для кода, который строит событие сам.

Настройки проекта находятся в UCFImpactFeedbackSettings. У строки и компонентов есть собственные значения, которые перечислены ниже. Значения по умолчанию — от плагина.

СвойствоЧто делаетПо умолчанию
UCFImpactFeedbackSettings::DefaultSetНабор ударов, который проигрывается./Crushform/Impact/DA_CF_ImpactFeedback
UCFImpactFeedbackSettings::MaxAudibleDistanceCmДальше этого расстояния в см звук не проигрывается.6000
UCFImpactFeedbackSettings::MaxEffectDistanceCmДальше этого расстояния в см эффект не порождается.8000
UCFImpactFeedbackSettings::MinVoiceSecondsНаименьшее время, которое проигранный звук занимает слот голоса.0.25
UCFImpactFeedbackSettings::MaxVoiceSecondsНаибольшее время, которое проигранный звук занимает слот голоса.3
UCFImpactFeedbackSettings::MaxSoundsPerFrameНаибольшее число звуков, которые стартуют в одном кадре. Остальные ждут следующих кадров, самые сильные первыми. 0 выключает ограничение.2
UCFImpactFeedbackSettings::SoundQueueSecondsСколько звук сверх лимита кадра может ждать; после этого он отбрасывается.0.15
UCFImpactFeedbackSettings::IgnoredHitActorClassesУдар от эктора одного из этих классов не является ударом.пусто
UCFImpactFeedbackSettings::bUseDefaultBreakableHostСопоставляет ли плагин отклик разрушаемых объектов с событиями ударов.true
FCFImpactFeedbackEntry::VolumeByIntensityМножитель громкости при интенсивности 0 и при интенсивности 1.(0.4, 1.0)
FCFImpactFeedbackEntry::PitchRangeДиапазон случайного множителя высоты тона.(0.92, 1.08)
FCFImpactFeedbackEntry::MinIntensityИнтенсивность ниже этого значения ничего не проигрывает. 0 выключает фильтр.0
FCFImpactFeedbackEntry::CooldownSecondsВремя между двумя ударами одного источника.0.1
FCFImpactFeedbackEntry::MaxConcurrentVoicesНаибольшее число звуков строки, которые проигрываются одновременно.4
UCFImpactFeedbackComponent::ImpulsePerKgForFullIntensityИмпульс на килограмм, который проигрывается в полную силу.600
UCFImpactFeedbackComponent::MinImpulsePerKgИмпульс на килограмм, ниже которого удар молчит.50
UCFImpactFeedbackComponent::ContactGapSecondsТишина, после которой следующий удар компонента считается новым контактом.0.1
UCFImpactFeedbackComponent::ContactSpikeRatioВнутри контакта удар проигрывается, только если его импульс в это число раз больше текущего импульса.2
UCFNetImpactFeedbackComponent::MinRelayIntervalSecondsНаименьший промежуток между двумя ударами этого тела, которые отправляются другим игрокам, кроме заметно более сильного удара, который отправляется раньше.0.5
UCFPartImpactFeedbackComponent::OpenSlamEventTagСобытие удара при ударе о открытый конец хода детали. Пусто: там звука нет.Crushform.Impact.Part.Slam.Open
UCFPartImpactFeedbackComponent::SlamSpeedForFullIntensityСкорость удара детали в см/с, при которой он проигрывается в полную силу.500
UCFPartImpactFeedbackComponent::MinSlamSpeedСкорость в см/с, ниже которой удар детали молчит.40

В любой сборке, кроме Shipping, откройте консоль клавишей тильда.

  • crushform.Impact.LogHits 1 включает маркеры. Въедьте седаном в стену, забор или дерево. Каждый оценённый удар оставляет маркер примерно на 5 секунд: зелёный для удара при контакте, который проигрывается, жёлтый для удара внутри устойчивого контакта и красный для удара ниже минимума. Чтобы их выключить, используйте crushform.Impact.LogHits 0. По умолчанию значение 0.
  • stat CFImpactFeedback показывает циклы ударов.
  • Ударьте автомобилем о стену. Вы слышите звук и видите эффект в месте контакта.

На выделенном сервере ничего не проигрывается, или другие игроки ничего не слышат

Заголовок раздела «На выделенном сервере ничего не проигрывается, или другие игроки ничего не слышат»

Причина. Выделенный сервер вообще не проигрывает ударов. Вызов Play Impact проигрывается только на инстансе, который его делает. Удары от компонента доходят до других игроков только через UCFNetImpactFeedbackComponent, который их передаёт.

Решение. Вызывайте Play Impact на каждом инстансе, который должен это слышать. Для ударов тела, которые должны слышать другие игроки, используйте на нём UCFNetImpactFeedbackComponent.

Причина. В активном наборе нет строки для этого тега или для любого из его родителей, поэтому UCFImpactFeedbackSet::FindEntry ничего не находит. Компонент или адаптер, у которого тег очищен вручную, тоже ничего не проигрывает.

Решение. Добавьте в набор строку для тега или строку для его ближайшего родителя. Верните тег на компонент или адаптер либо оставьте поле пустым, чтобы проигрывался тег плагина по умолчанию.

Тело, к которому я добавил компонент, молчит

Заголовок раздела «Тело, к которому я добавил компонент, молчит»

Причина. Здесь два случая. UCFImpactFeedbackComponent не наблюдает ни одного примитива, пока в C++ не вызван SetObservedPrimitive, поэтому компонент, добавленный только в Blueprint, молчит. UCFNetImpactFeedbackComponent наблюдает корневой примитив своего владельца, и если корень не является примитивом, он пишет эту строку и молчит:

%s: owner %s has no primitive root; its impacts stay silent

Решение. Для базового компонента передайте ему примитив из C++ через SetObservedPrimitive. Для тела, которое должны слышать другие игроки, используйте UCFNetImpactFeedbackComponent и убедитесь, что корневой компонент владельца является примитивом, например мешем тела.

Удар молчит или проигрывает только эффект

Заголовок раздела «Удар молчит или проигрывает только эффект»

Причина. Удар ниже Min Impulse Per Kg (50) или ниже Min Intensity строки, поэтому он молчит. Либо все Max Concurrent Voices строки заняты, и тогда удар проигрывает эффект без звука.

Решение. Уменьшите Min Impulse Per Kg или Min Intensity для строки либо увеличьте Max Concurrent Voices. Включите crushform.Impact.LogHits 1, чтобы увидеть, краснеет ли удар (ниже минимума) или вообще был оценён.

Устойчивый контакт снова и снова проигрывает удар

Заголовок раздела «Устойчивый контакт снова и снова проигрывает удар»

Причина. Компонент проигрывает новый удар, только когда удар — это всплеск внутри его контакта: его импульс не меньше Contact Spike Ratio (2) текущего импульса. Контакт, который сохраняет свой импульс, не повторяется. Контакт, который прерывается дольше Contact Gap Seconds (0,1 с), считается новым.

Решение. Увеличьте Contact Gap Seconds выше нескольких шагов физики, если один удар распадается на несколько. Оставьте коэффициент всплеска по умолчанию, если устойчивый контакт всё же повторяется.

О поломках, из которых возникают эти удары, см. Заборы и объекты и Разрушаемые деревья и столбы. Собственные звуки удара автомобиля задаются на его адаптере, описанном в Основных понятиях.