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

СПРАВОЧНИККОМПОНЕНТЫ

UCFDeformComponent

МОДУЛЬCrushformЗАГОЛОВОКCFDeformComponent.hРОДИТЕЛЬUActorComponent

Вмятины и износ краски одного эктора, корневой компонент которого — его симулируемое тело. Без профиля ничего не делает, кроме того, что OnWheelSurfaceChanged и GetWheelSurface не требуют ни профиля, ни сетки грязи. Решётка натягивается на коллизию тела в пространстве корневого компонента при начале игры.

Сервер держит настоящую решётку и публикует её чанками 4x4x4. Клиент, который симулирует тело, отправляет свои удары на сервер и сразу рисует их как предсказание; все остальные клиенты рисуют полученные чанки.

Функции

AUTHORITY · сервер, на каждом инстансеLOCAL · этот инстансPURE · только чтение
void SetCrushformHost(UObject* NewHost)
C++ ONLY

Кто отвечает за ICFDeformHost для этого компонента; null = host-объект владельца из реестра, иначе сам владелец. Вызывайте до BeginPlay: компонент один раз считывает свои меши и стекло из host-объекта.

UObject* GetCrushformHost() const
PUREC++ ONLY

Явно заданный host-объект, иначе UCFHostRegistry::FindHost(Owner, UCFDeformHost), иначе null.

void AddWheelHostPrerequisite(UActorComponent& Host)
C++ ONLY

Заставляет оба тика этого компонента ждать тика Host: основного и того, что читает поверхности колёс. Для host-объекта, который строит контакты колёс кадра в своём тике, чтобы этот компонент никогда не читал контакты предыдущего кадра.

void Repair()
AUTHORITY

Только для авторити: убирает все вмятины и царапины на каждом инстансе. Грязь остаётся; её убирает Wash.

Категория
Crushform
void Wash()
AUTHORITY

Только для авторити: смывает все каналы загрязнения (пыль, грязь, снег и влагу) с тела на каждом инстансе. Вмятины остаются; их убирает Repair.

Категория
Crushform
bool FillDirt(const FCFDirtValues& Floor)
LOCALC++ ONLY

Поднимает грязь этого тела как минимум до этих значений по каналам (0..1), как её оставляет длинная поездка; измеряется от земли под колёсами так же, как при езде: максимум у линии земли, с истончением вверх по форме каждого канала в профиле; канал брызг снова полон вокруг каждой оси. Тело в воздухе измеряется от своего низа. Только на этом инстансе: грязь никогда не передаётся по сети. Вспомогательное средство для отладки; колёса продолжают добавлять и сбрасывать грязь, как и раньше. Возвращает false там, где грязь не отрисовывается. Собственного OnDirtChanged не отправляет: об изменении сообщит следующее обновление грязи.

void AddDirt(FVector WorldPoint, float Radius, FCFDirtValues Amount)
LOCAL

Добавляет Amount каждого канала вокруг мировой точки: максимум в точке и ноль на расстоянии Radius (см). Только на этом инстансе: вызывайте на каждом инстансе, который должен это видеть. Ничего не делает там, где грязь не отрисовывается.

Категория
Crushform|Dirt
void WashAt(FVector WorldPoint, float Radius)
LOCAL

Смывает грязь всех каналов вокруг мировой точки: максимум в точке и ноль на расстоянии Radius (см); срабатывает OnWashed с bPartial, если что-то смыло. Только на этом инстансе: вызывайте его на каждом, который должен это видеть. Wash — сетевое смывание всего тела.

Категория
Crushform|Dirt
FCFDirtValues GetDirtAt(FVector WorldPoint) const
PURE

Грязь каждого канала в мировой точке тела этого инстанса, 0..1. Все нули там, где грязь не отрисовывается.

Категория
Crushform|Dirt
FCFDirtZones GetDirtZones() const
PURE

Средняя грязь каждого канала по каждой стороне тела, как её сообщает OnDirtChanged. Все нули там, где грязь не отрисовывается.

Категория
Crushform|Dirt
FCFDamageZones GetDamageZones() const
PURE

Насколько вмята каждая сторона тела (стороны из Get Dirt Zones): для каждой стороны самый глубокий узел и среднее по её узлам; смещение узла, делённое на Max Displacement профиля, 0..1. Читается из повреждений, подтверждённых сервером, поэтому каждый инстанс читает одно и то же: собственные неподтверждённые удары этого инстанса не учитываются. Все нули, пока у тела нет решётки.

Категория
Crushform|Damage
FCFDamageValues GetDamageInBox(const FBox& Box) const
PURE

Повреждение по узлам решётки, из которых берётся точка внутри Box: Max — самый глубокий из них, делённый на Max Displacement профиля, Mean — их среднее смещение по нему, каждое ограничено 1. Box задан в пространстве корневого компонента владельца, как Crush Link Box у панели. Все нули, пока у тела нет решётки, Box её не пересекает или Box не задан. Box с перевёрнутыми углами читает бокс, который они задают.

Категория
Crushform|Damage
FCFWheelSurface GetWheelSurface(int32 WheelIndex) const
PURE

На чём сейчас стоит колесо host-объекта с этим WheelIndex, читается у host-объекта при вызове. WheelIndex в результате равен INDEX_NONE, если host-объект не сообщает такого колеса. Работает независимо от того, отрисовывается ли грязь.

Категория
Crushform|Dirt
bool ApplyLatticeHit(const FCFHitInput& Hit)
C++ ONLY

Применяет удар, заданный в пространстве решётки, как если бы физика сообщила его здесь: на авторити — к решётке, на клиенте, который симулирует тело, — как предсказание, которое он сообщает. Возвращает false, если этот инстанс не может применять удары к владельцу, и когда профиль не допускает вмятин.

bool ApplyWorldHit(const FVector& WorldPoint, const FVector& WorldNormal, float DeltaV)
C++ ONLY

Удар, заданный в мировом пространстве геймплеем, а не физикой, например объект, который тело разрушило, не касаясь его. WorldPoint лежит на теле или рядом с ним; WorldNormal может смотреть в любую сторону; DeltaV в м/с. Правила для инстансов те же, что у ApplyLatticeHit; также false, если точка вне решётки или удар слишком слабый для вмятины, и когда профиль не допускает вмятин.

void DentFromBrokenUnit(UPrimitiveComponent& Body, const FVector& UnitPoint, const FVector& VelocityCmS, float SpeedFraction)
C++ ONLY

Разрушаемый элемент поддался под Body, который физически никогда не касается элементов: вмятина на теле в точке, ближайшей к UnitPoint, с силой SpeedFraction от скорости тела в элемент. Ничего не делает на инстансе, который не симулирует тело (IsImpactSourceHere): там вмятину передаёт собственный отчёт симулирующего клиента. Body не const, так как трассировка компонента не const.

bool CrushByPlane(const FVector& WorldPoint, const FVector& WorldDirection, float Softness, float Bulge)
AUTHORITYC++ ONLY

Только для авторити: вдавливает плоскую пластину в тело; её плоскость проходит через WorldPoint и движется вдоль WorldDirection (FCFLattice::ApplyPlaneCrush; Softness в см, Bulge как доля толчка). Не предсказывается: клиенты видят его по мере прихода чанков. Возвращает false на инстансе без авторити над решёткой, когда профиль не допускает вмятин и когда ничего не сдвинулось.

float GetGivingWayMass(const UPrimitiveComponent* OtherComp, FName BoneName)
C++ ONLY

Масса, которая поддаётся при ударе по OtherComp, кг: ударенное тело вместе с тем, что его толкает, его приваренные части, остальной скелет, симулируемое тело эктора, к которому оно прикреплено (сочленённая стрела автомобиля). 0 для тела, которое не двигается: статического, кинематического или не симулируемого.

float GetEnergyScale(float OwnMass, float GivingWayMass)
C++ ONLY

Пересчёт изменения собственной скорости тела при ударе в скорость в неподвижную стену, которая принимает ту же энергию: sqrt(1 + OwnMass / GivingWayMass), отношение ограничено CF::MaxGivingWayMassRatio. 1, когда ничего не поддаётся.

float GetSupportSpeed(const UWorld* World, float NormalZ)
C++ ONLY

Изменение скорости (см/с), которое контакт с нормалью такого Z сообщает телу, лежащему на нём, на каждом шаге физики, лишь чтобы удержать его: часть импульса каждого удара и весь импульс лежащего тела. Удары приходят по одному на шаг солвера, поэтому шагом служит асинхронный фиксированный шаг, когда физика тикает асинхронно, иначе шаг кадра, как его ограничивает движок.

bool ComputeLatticeLayout(const AActor& Owner, const FCFDeformHostCaller& Host, const UCFProfile& Profile, FCFLatticeLayout& OutLayout)
C++ ONLY

Решётка, которую Profile задаёт для Owner: какие меши деформируются, бокс, охватывающий коллизию тела, и сетка по этому боксу. Возвращает false, если у владельца нет корневого компонента или ни один меш не деформируется. Запрашивает Host, который вызывающий код привязывает к политике владельца, поэтому работает до BeginPlay, в том числе на превью-экторе Blueprint.

bool IsDeformEnabled() const
PUREC++ ONLY

Есть ли у тела решётка на этом инстансе, чтобы его можно было вдавливать. Без профиля — false.

const FCFDirtGrid& GetDirtGrid() const
PUREC++ ONLY

Загрязнение этого инстанса (пыль, грязь, снег и влага) на теле; не инициализируется там, где его ничего не рисует.

const FCFBodyCollision& GetBodyCollision() const
PUREC++ ONLY

Коллизия корня, следующая за видимой решёткой; не инициализируется там, где профиль не трогает коллизию.

uint8 GetWashCount() const
PUREC++ ONLY

Сколько раз тело было вымыто; реплицируется, поэтому счётчик клиента следует за счётчиком сервера.

const FVector3f& GetGridOrigin() const
PUREC++ ONLY

Положение узла решётки (0, 0, 0) в пространстве корневого компонента, см.

const FBox& GetMeshBounds() const
PUREC++ ONLY

Бокс вокруг деформируемых мешей в пространстве корня владельца, без отступа решётки; недействителен, пока решётка не построена.

const UCFProfile* GetProfile() const
PUREC++ ONLY

Профиль, который использует этот компонент; null, если он не задан.

const FCFDeformStats& GetStats() const
PUREC++ ONLY

Счётчики, которые выводит Crushform.Stats для этого компонента.

const TArray<FCFDebugHit>& GetDebugHits() const
PUREC++ ONLY

Последние удары, применённые этим инстансом, от старых к новым; записываются только в сборках с отладочным оверлеем.

int32 GetNumPendingReports() const
PUREC++ ONLY

Удары, которые отправил этот клиент и которые сервер ещё не подтвердил или не отклонил.

uint8 GetGeneration() const
PUREC++ ONLY

Сколько ремонтов было у тела; реплицируется. Сообщения и чанки другого поколения не применяются.

const TArray<TObjectPtr<UCFHingeComponent>>& GetHinges() const
PUREC++ ONLY

Шарниры, которыми управляет этот компонент, по индексу части: отсортированы по имени, поэтому каждый инстанс нумерует их одинаково.

UCFGlassUnitsComponent* GetGlass() const
PUREC++ ONLY

Стеклянные элементы владельца (ICFDeformHost::GetCrushformGlass), задаются в BeginPlay; null, если их нет.

float GetPartDamage(int32 PartIndex) const
PUREC++ ONLY

Самая глубокая вмятина вокруг навесной детали, см, в решётке, которую рисует этот инстанс; 0 для индекса вне диапазона.

FCFPartDamage GetPartDamageDetail(int32 PartIndex) const
PUREC++ ONLY

Три показателя вмятин навесной детали в решётке, которую рисует этот инстанс; нули для индекса вне диапазона.

bool IsPartDetached(int32 PartIndex) const
PUREC++ ONLY

Выключена ли эта часть у авторити в текущем поколении.

FBox GetPartCutBox(int32 PartIndex) const
PUREC++ ONLY

Место в пространстве корня владельца, см, которое освобождает коллизия кузова после отрыва этой детали: бокс простой коллизии детали в закрытом положении (границы её меша, если простой коллизии нет), объединённый с боксами её стеклянных панелей и увеличенный на Collision Block Tolerance. Одинаково на каждом инстансе, оторвана деталь сейчас или нет; коллизия кузова вырезается там, только пока включён Deform Collision. Недействительный бокс для индекса детали вне диапазона.

bool IsPartLetSwing(int32 PartIndex) const
PUREC++ ONLY

Отпустил ли источник удара эту деталь качаться в текущем поколении: его сигнал пришёл по репликации или его отправил этот инстанс.

bool IsPartOffOrReportedOff(int32 PartIndex) const
PUREC++ ONLY

Выключена ли часть для того, что по ней судится: маска на авторити содержит эту часть или этот инстанс как источник удара сообщил, что она выключена. Сервер задаёт маску до чтения всего, что пришло после отчёта, поэтому удары после него судятся одинаково на обоих инстансах.

bool IsPartHullBuilt(int32 PartIndex) const
PUREC++ ONLY

Держит ли тело свободной части оболочку своей вмятой коллизии вместо собственных форм (UpdatePartCollision); false для индекса вне диапазона.

void CarryLooseParts(const FTransform& FromRoot)
C++ ONLY

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

FTransform GetLatticeToWorld() const
PUREC++ ONLY

Преобразует из пространства решётки в мировое пространство, для отладочной отрисовки.

Свойства

TObjectPtr<UCFProfile> Profile

Задайте до начала игры: в значениях по умолчанию класса или между SpawnActorDeferred и FinishSpawning.

Категория
Crushform

События

FCFOnDirtChangedDynamicDelegate OnDirtChanged
(const FCFDirtZones& Zones)

Грязь на этом инстансе сместилась: среднее значение по каждой стороне тела, не чаще одного раза за Dirt Event Interval и только если какая-либо сторона изменилась больше чем на Dirt Event Threshold. Никогда не срабатывает на инстансе, который грязь не отрисовывает. Изменения, внесённые AddDirt, WashAt, Wash и FillDirt, сообщает следующее обновление грязи.

Категория
Crushform|Dirt
FCFOnWashedDynamicDelegate OnWashed
(bool bPartial)

Грязь на этом инстансе смыта: bPartial для WashAt, не для мойки всего тела. Никогда не срабатывает на инстансе, который грязь не отрисовывает.

Категория
Crushform|Dirt
FCFOnWheelSurfaceChangedDynamicDelegate OnWheelSurfaceChanged
(const FCFWheelSurface& Surface)

PhysicalMaterial или состояние касания земли у колеса изменилось с момента последнего сообщения, а также при первом появлении колеса: проверяется каждый кадр на инстансе, который не является выделенным сервером, независимо от того, рисуется ли грязь. Изменение только SurfaceSpeed срабатывания не вызывает: событие несёт текущее значение. Колесо в воздухе сообщает PhysicalMaterial, равный null, поэтому смена материала, пока колесо в воздухе, ничего не вызывает. Только для колёс, указанных host-объектом (FCFWheelContact::WheelIndex).

Категория
Crushform|Dirt
FCFOnDamageChangedDynamicDelegate OnDamageChanged
(const FCFDamageZones& Zones)

Повреждение на этом инстансе изменилось: Get Damage Zones отличается от того, что несло последнее событие. Читается не чаще одного раза за кадр, после изменения решётки, на каждом инстансе (в том числе на выделенном сервере), по повреждению, которое подтвердил сервер: удар, который этот инстанс предсказывает, не срабатывает, пока сервер его не подтвердит. Ремонт срабатывает с нулями; игрок, подключившийся позже, получит событие, когда реплицированные чанки построят решётку. Пока мир на паузе, ожидается первый кадр без паузы. Состояние до первого события читайте через Get Damage Zones.

Категория
Crushform|Damage
FCFOnDamageChangedDelegate OnDamageChangedNative
C++ ONLY
(const FCFDamageZones&)

OnDamageChanged для C++: рассылается сразу перед ним, с теми же зонами.