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

НАЧАЛО РАБОТЫСВОЙ АВТОМОБИЛЬ

Свой автомобиль

Используйте эту страницу для автомобиля, который не является пешкой Chaos Vehicles. Для пешки Chaos Vehicles Crushform Chaos Vehicle Adapter читает колёса из компонента движения, и Быстрый старт описывает его подключение.

  • Корневой компонент эктора — симулируемый кузов. Вмятины и краска измеряются на нём, а для вмятины нужен профиль деформации.
  • Настройте материалы, как в руководстве Быстрый старт.
  • Колёса — компоненты эктора: меш или scene-компонент, который поворачивается вместе с колесом.
  • Для C++ добавьте в свой Build.cs модули Crushform, которые вы вызываете, как в руководстве Установка.

Адаптер трассирует поверхность под каждым колесом, которое вы перечислили. Он создаёт вмятины и грязь, стекло, шины, звуки, разрушение объектов и отклик на удары, а также отвечает на их вопросы об автомобиле.

  1. Add › Crushform Vehicle Adapter. Добавьте его к эктору.
  2. Задайте UCFVehicleAdapterComponent::Wheels: один FCFAdapterWheel на каждое колесо. В Details раскройте Wheels и добавьте по одному элементу на колесо. В каждом элементе выберите колесо в списке Wheel, который показывает scene-компоненты эктора, и задайте Radius, радиус шины в сантиметрах. Радиус 0 означает половину высоты границ меша колеса. Задавайте радиус для колеса, которое уже вращается.
Панель Details адаптера с четырьмя элементами в Wheels, в каждом выпадающий список Wheel и Radius 0 см.
Wheels: один элемент на каждое колесо, в каждом колесо выбрано из списка.
  1. Задайте GroundChannel, канал, по которому колёса трассируют землю (по умолчанию Visibility), и GroundProbeMargin, по умолчанию 2 см. Трассировка начинается от ступицы, поэтому шина, которая находится на таком расстоянии над землёй, всё ещё касается её. Или вызовите UCFVehicleAdapterComponent::SetWheels во время игры со значениями FCFAdapterWheelState. Это работает и до BeginPlay.
  2. Задайте Authority и RamAllowanceMps. Server — по умолчанию: сервер симулирует автомобиль и оценивает его удары. С OwningClient инстанс, на котором ведут автомобиль, симулирует его и сообщает о своих ударах, а сервер принимает отчёт, только если изменение скорости не превышает недавнюю пиковую скорость автомобиля плюс RamAllowanceMps (по умолчанию 15 м/с), с поправкой в большую сторону для более лёгкого кузова, который уступает. Затем задайте профили и флаги функций. Пустые DeformProfile или TireProfile берут значение проекта по умолчанию. Каждый флаг функции включён по умолчанию; каждый выключает компонент, который он называет.
  3. Привяжите событие OnDamageChanged в Blueprint, если автомобиль должен реагировать на повреждения. Оно срабатывает, когда меняются повреждения кузова, и никогда не срабатывает без Dirt and Dents.

Адаптер не видит ваше управление, поэтому сообщите ему:

  • Вызовите UCFVehicleAdapterComponent::SetBraking со значением от 0 до 1. FX качения выбрасывают больше грязи, пока автомобиль тормозит.
  • Вызовите UCFVehicleAdapterComponent::SetCabinMuffled со значением true, пока слушатель сидит в салоне. Это приглушает звук качения и звук двигателя.
  • Звук двигателя читает пять событий: GetEngineRunState (Off, Cranking или Running), GetEngineRPM, GetEngineIdleRPM, GetEngineMaxRPM и GetEngineLoad. Адаптер отвечает off и нулём. Переопределите их в Blueprint-наследнике адаптера или в C++.

Если ваши колёса симулирует физическая система, отличная от встроенной трассировки, переопределите четыре события колёс адаптера: UCFVehicleAdapterComponent::BuildWheelContacts, CollectWheelMeshes, BuildTireWheels и BuildLoadRatios. Адаптер Chaos делает то же самое для Chaos Vehicles.

Для каждого колеса BuildWheelContacts заполняет один FCFWheelContact за кадр:

  • Point: где шина касается земли, в мировом пространстве, см. Читается только пока bGrounded истинно.
  • Radius: радиус шины, см.
  • bGrounded: ложь, пока колесо в воздухе. Колесо в воздухе не оставляет грязи.
  • PhysicalMaterial: поверхность под колесом. Null берёт стандартные скорости.
  • SurfaceSpeed: скорость поверхности шины, м/с, положительная, когда она катит автомобиль вперёд.
  • GroundSpeed: скорость ступицы над землёй, м/с. Если меньше 0, используется скорость автомобиля.
  • WheelIndex: номер колеса, с 0. Он не меняется за всё время жизни колеса.

CollectWheelMeshes возвращает меши колёс. Они получают грязь и никогда не деформируются. BuildTireWheels возвращает меш каждой шины, физический радиус и HostIndex, а также bAcceptsPush; когда его ставить, сказано в руководстве Host-интерфейсы. BuildLoadRatios возвращает силу контакта, делённую на номинальную нагрузку, по HostIndex; отсутствующий или отрицательный элемент держит коэффициент нагрузки этого колеса равным 1.

Используйте host-интерфейсы, когда у автомобиля свой набор компонентов и вы не хотите адаптер. Вы добавляете компоненты Crushform сами и отвечаете на их вопросы в самом экторе или в одном из его компонентов. Интерфейсы находятся в модуле Crushform, кроме ICFTireHost и ICFTireViewer (CrushformTire) и ICFEngineHost (CrushformEngine).

КомпонентМодульЧто нужно
UCFDeformComponentCrushformПрофиль деформации: без него компонент ничего не делает. Корневой компонент эктора — симулируемый кузов.
UCFGlassUnitsComponentCrushformСтеклянные панели, которые являются дочерними UCFGlassComponent эктора. GetCrushformGlass эктора возвращает этот компонент. Нужен компонент деформации.
UCFTireComponentCrushformTireICFTireHost на экторе. Без него шины остаются круглыми. Профиль шин или значение проекта по умолчанию.
UCFRollingAudioComponentCrushformWheelICFWheelHost на экторе. Звук каждой поверхности берётся из таблицы поверхностей проекта.
UCFRollingFXComponentCrushformWheelICFWheelHost на экторе. Эффект каждой поверхности берётся из таблицы поверхностей проекта.
UCFPropContactComponentCrushformКорневой примитив эктора как кузов. ICFBreakerHost необязателен.
UCFImpactFeedbackComponentCrushformImpactПримитив, удары которого он сообщает, задаётся через SetObservedPrimitive. Его EventTag проигрывает звук; пустое значение означает отсутствие звука.
UCFEngineAudioComponentCrushformEngineICFEngineHost на экторе. Звуковой профиль или значение проекта по умолчанию.

На кузове автомобиля адаптер использует UCFNetImpactFeedbackComponent вместо UCFImpactFeedbackComponent. Он сообщает об ударах кузова только на инстансе, который симулирует кузов, а остальные инстансы проигрывают ретранслированную копию.

В меню Add компоненты отклика на удары — CFImpact Feedback, CFNet Impact Feedback и компонент для деталей — стоят в категории Custom, а не Crushform.

Шесть host-интерфейсов:

ИнтерфейсКого спрашиваетЧто отвечает
ICFDeformHostUCFDeformComponent, сетевой отклик на ударыКакой инстанс симулирует кузов, игнорируемые экторы, правдоподобен ли отчёт, какие меши деформируются, меши колёс, стекло
ICFWheelHostслой грязи, UCFRollingAudioComponent, UCFRollingFXComponentКолёса кадра в виде значений FCFWheelContact
ICFBreakerHostUCFPropContactComponentСимулирует ли этот инстанс кузов, контактное тело, маршрут отчёта, компонент деформации, которым вминается разрушенный элемент
ICFTireHostUCFTireComponentКолёса, смещения и выталкивания, которые записываются обратно, коэффициенты нагрузки, сцепка
ICFTireViewerбюджет шин, на пешкеАвтомобиль, в котором едет пешка, или null, если он пешком
ICFEngineHostUCFEngineAudioComponentСостояние двигателя: режим работы, обороты, холостые и максимальные обороты, нагрузка

Компонент находит свой host-объект в таком порядке. Сначала host-объект, заданный через SetCrushformHost до BeginPlay. Затем host-объект, зарегистрированный для эктора в UCFHostRegistry. Затем сам эктор, если он реализует интерфейс. Иначе host-объекта нет. Каждое событие отвечает ECFHostAnswer: Default означает, что компонент решает так, будто host-объекта нет, а Yes или No переопределяют это.

  1. Откройте Blueprint эктора и перейдите в Class Settings. В разделе Implemented Interfaces нажмите Add и выберите интерфейс, например CFDeform Host, затем CFWheel Host.
Список Implemented Interfaces с кнопкой Add и двумя интерфейсами под ней, CFDeform Host и CFWheel Host.
Class Settings › Implemented Interfaces: host-интерфейсы Crushform, добавленные к эктору.
  1. Функции интерфейсов появляются в My Blueprint в разделе Interfaces › Crushform с их C++-именами без пробелов, например GatherCrushformWheelMeshes. Дважды щёлкните по функции, чтобы реализовать её. Значение ECFHostAnswer, которое вы не трогали, возвращает Default. Список, который вы не трогали, ничего не собирает.
Раздел Interfaces в My Blueprint, группа Crushform, со списком ShouldCrushformIgnore, ShouldCrushformDeform, IsCrushformReportPlausible, IsCrushformImpactSourceHere, GetCrushformGlass, GatherCrushformWheelMeshes, GatherCrushformIgnoredActors и GatherCrushformWheelContacts.
My Blueprint показывает функции интерфейсов в разделе Interfaces › Crushform.
  1. У GatherCrushformWheelMeshes есть выходной массив, поэтому это функция. Соберите массив из четырёх мешей колёс и подключите его к выходу узла Return.
Четыре меша колёс в одном массиве, подключённом к узлу Return.

Реализуйте интерфейсы у эктора и переопределите _Implementation каждого события, на которое отвечаете. Этот класс отвечает за меши колёс и контакты колёс четырёхколёсного автомобиля.

YourVehicle.h
#pragma once
#include "CoreMinimal.h"
#include "CFDeformHost.h"
#include "CFWheelHost.h"
#include "GameFramework/Actor.h"
#include "YourVehicle.generated.h"
class UMeshComponent;
class UStaticMeshComponent;
UCLASS()
class AYourVehicle : public AActor, public ICFDeformHost, public ICFWheelHost
{
GENERATED_BODY()
public:
virtual void GatherCrushformWheelMeshes_Implementation(TArray<UMeshComponent*>& OutMeshes) const override;
virtual void GatherCrushformWheelContacts_Implementation(TArray<FCFWheelContact>& OutContacts) const override;
/** The four wheels, in WheelIndex order. Fill it in the constructor with the wheel components you create, or in Blueprint once they exist. */
UPROPERTY(VisibleAnywhere)
TArray<TObjectPtr<UStaticMeshComponent>> Wheels;
/** Tyre radius, cm. */
UPROPERTY(EditAnywhere)
float WheelRadius = 35.f;
/** The speed of each wheel's surface, m/s, from your vehicle model. */
TArray<float> WheelSurfaceSpeeds;
};

Тело GatherCrushformWheelContacts трассирует вниз от ступицы каждого колеса и заполняет один FCFWheelContact на колесо. Колесо в воздухе оставляет bGrounded ложным, а Point и PhysicalMaterial не задаются.

YourVehicle.cpp
#include "YourVehicle.h"
#include "Components/StaticMeshComponent.h"
#include "Engine/World.h"
#include "PhysicalMaterials/PhysicalMaterial.h"
void AYourVehicle::GatherCrushformWheelMeshes_Implementation(TArray<UMeshComponent*>& OutMeshes) const
{
for (UStaticMeshComponent* Wheel : Wheels)
{
OutMeshes.Add(Wheel);
}
}
void AYourVehicle::GatherCrushformWheelContacts_Implementation(TArray<FCFWheelContact>& OutContacts) const
{
UWorld* World = GetWorld();
if (!World)
{
return;
}
// The physical material comes back only when the query asks for it.
FCollisionQueryParams Params(SCENE_QUERY_STAT(YourVehicleWheel), false, this);
Params.bReturnPhysicalMaterial = true;
for (int32 Index = 0; Index < Wheels.Num(); ++Index)
{
const UStaticMeshComponent* Wheel = Wheels[Index];
if (!IsValid(Wheel))
{
continue;
}
// Trace down from the hub, past the tyre radius.
const FVector Hub = Wheel->GetComponentLocation();
const FVector TraceEnd = Hub - FVector(0.f, 0.f, WheelRadius + 20.f);
FHitResult Hit;
FCFWheelContact Contact;
Contact.WheelIndex = Index;
Contact.Radius = WheelRadius;
Contact.SurfaceSpeed = WheelSurfaceSpeeds.IsValidIndex(Index) ? WheelSurfaceSpeeds[Index] : 0.f;
Contact.bGrounded = World->LineTraceSingleByChannel(Hit, Hub, TraceEnd, ECC_Visibility, Params);
if (Contact.bGrounded)
{
Contact.Point = Hit.ImpactPoint;
Contact.PhysicalMaterial = Hit.PhysMaterial.Get();
}
OutContacts.Add(Contact);
}
}

Код, которому нужны колёса эктора, спрашивает его host-объект через Execute_, а не вызывает событие по имени через указатель:

#include "CFHostRegistry.h"
#include "CFWheelHost.h"
TArray<FCFWheelContact> Contacts;
if (UObject* Host = UCFHostRegistry::FindHost(this, *UCFWheelHost::StaticClass()))
{
ICFWheelHost::Execute_GatherCrushformWheelContacts(Host, Contacts);
}
  • Второй host-объект для того же эктора и интерфейса заменяет первый, с предупреждением.
  • Blueprint-host-объект не отвечает в превью редактора. Превью не запускает его скрипт, поэтому раскладка решётки в Details и редактор зон не видят его ответов. Проверяйте результат в Play.
  • Не вызывайте событие интерфейса по имени через указатель на интерфейс. Используйте функцию Execute_ или аксессор компонента.

Это свойства адаптера. Собственные настройки адаптера находятся в Details компонента адаптера.

СвойствоПо умолчаниюЧто делает
UCFVehicleAdapterComponent::WheelsпустоКолёса, которые трассирует адаптер: компонент и Radius для каждого.
GroundChannelVisibilityКанал, по которому колёса трассируют землю.
GroundProbeMargin2 смНа каком расстоянии над землёй шина ещё касается её.
AuthorityServerКакой инстанс симулирует автомобиль и оценивает его удары.
RamAllowanceMps15 м/сПри OwningClient: насколько сообщённый удар может превышать недавнюю пиковую скорость.
DeformProfileпроект по умолчаниюВмятины и грязь кузова.
TireProfileпроект по умолчаниюШины.
EngineSoundProfileпроект по умолчаниюЗвук двигателя.
bDirtAndDents, bGlass, bTires, bRollingSound, bRollingFX, bEngineSound, bImpactFeedback, bBreaksPropsвсе включеныКаждый выключает компонент, который он называет.
ImpactImpulsePerKgForFullIntensity600 см/сИзменение скорости при ударе, который проигрывается в полную силу.
ImpactMinImpulsePerKg50 см/сИзменение скорости, ниже которого удар ничего не проигрывает.
PropContactMinSpeedCmS50 см/сНиже этой скорости автомобиль не ломает объекты.
  1. Откройте уровень с вашим автомобилем и нажмите Play.
  2. Откройте консоль клавишей тильда и выполните Crushform.Stats. Команда выводит занятые слоты атласа и счётчики ударов каждого повреждаемого эктора.
  3. Выполните Crushform.Debug 1. Команда рисует повреждённые узлы решётки кузова. Crushform.Debug 2 рисует все узлы.
  4. Выполните Crushform.DebugImpact 10 <name>, чтобы ударить эктор, чьё имя содержит <name>, со скоростью 10 м/с, на расстоянии до 100 м. Без имени удар приходится на эктора под прицелом. Команда никогда не бьёт по пешке, которой вы управляете, поэтому проверяйте свой автомобиль, въезжая в стену, как в шаге 5 руководства Быстрый старт. Это чит: он есть в каждой сборке, кроме Shipping, включая редактор.
  5. Проедьте по поверхности из PM_CF_Mud. Колёса должны реагировать на грязь так, как это задано в таблице поверхностей проекта.