05 — Фізичні предмети¶
🇬🇧 English | 🇺🇦 Українська
AInteractionPhysicsActor має mesh-root і UInteractionManipulationComponent. Компонент передає єдиний snapshot руху, масштабу, рук і прикріплення; стандартний ReplicateMovement актора вимкнений, щоб два механізми не перезаписували трансформацію. ObjectData посилається на UInteractionPhysicsDataAsset.
MassInKgзадає масу; mesh повинен мати придатну simple collision.bStartWithPhysicsвмикає симуляцію від початку.SleepWhenSettledзалишає природний сон Chaos: удар іншого тіла може розбудити предмет.DisablePhysicsFixedTimeповністю зупиняє симуляцію післяPhysicsDisableDelay; такий предмет не прокинеться від звичайного фізичного удару, але його можна знову захопити.HitSoundвідтворюється через multicast після авторитетного удару.
Сервер повідомляє актору про підбір і відпускання через інтерфейс: OnGrab(Interactor) викликається, коли першу руку прийнято, OnRelease(Interactor, Reason, LinearVelocity, AngularVelocity) — коли відпустила остання. Готовий актор у OnGrab запам'ятовує гравця як Instigator, а в OnRelease запускає таймер DisablePhysicsFixedTime. Перевизначаючи ці функції в нащадку, викликайте батьківську реалізацію.
Конструктор вмикає для mesh-root профіль колізії PhysicsActor, Simulation Generates Hit Events, wake-події та CCD (bUseCCD), щоб швидкий предмет не пролітав крізь тонкі стіни. CCD має свою ціну: для великої кількості дрібних нерухомих предметів у нащадку його можна вимкнути.
Удари: звук і пошкодження¶
Поки предмет вільний (його ніхто не тримає), сервер обробляє кожну hit-подію MeshComponent. Усі пороги задає ObjectData:
| Налаштування | Початково | Що робить |
|---|---|---|
HitSound |
— | Звук удару; відтворюється ненадійним multicast у точці удару на всіх клієнтах |
HitSoundMinimumImpulse |
150 | Слабші удари не звучать: дотики й лежання тихі |
HitSoundCooldown |
0.15 с | Найменший проміжок між двома звуками одного предмета, щоб ковзання не повторювало звук щокадру |
bApplyImpactDamage |
вимкнено | Чи викликати UGameplayStatics::ApplyDamage для актора, у якого влучив предмет |
DamagePerImpulse |
0.005 | Шкода на одиницю нормального імпульсу |
MinimumDamageImpulse |
20 | Слабші удари шкоди не завдають |
DamageTypeClass |
UDamageType |
Тип шкоди, що передається в ApplyDamage |
Простими словами. Імпульс — це «сила» удару: він росте з масою й швидкістю предмета. Кинута цеглина має великий імпульс, покладена на стіл — майже нульовий. Пороги відсікають дрібні дотики, щоб звук і шкода були лише від справжніх ударів.
Шкода вимкнена за замовчуванням: увімкніть bApplyImpactDamage, якщо кинуті предмети мають ранити або ламати. Ініціатором шкоди є контролер pawn, який востаннє брав предмет: OnGrab призначає його Instigator. Для власних правил перевизначте OnComponentHitInternal у C++-нащадку.
При Movement=Direct захоплений предмет зберігає QueryOnly, щоб друга рука могла його вибрати. При Movement=Physics один серверний PhysicsHandle веде тіло зі збереженням фізичних зіткнень. Після відпускання використовується QueryAndPhysics; bSimulateOnRelease і bAllowThrow визначають симуляцію й кидок. Лінійна швидкість — см/с, кутова — градуси/с. Всі фізичні actor callbacks мають authority guard; не керуйте копією клієнтського тіла вручну. Профілі описані в 08 — VR-маніпуляції.
AInteractionSpearActor використовує вісь +X як напрямок вістря. Вістря лежить у (Bounds.Max.X, 0, 0) локального mesh; pivot може бути зміщений уздовж древка. GetSpearTipLocation() повертає його світову позицію. Спис може вирівнюватися за швидкістю і прикріплюватися до поверхні при куті до 60°, швидкості від MinimumEmbedSpeed (200 см/с) та контакті в передній ділянці TipContactLength (40 локальних см). Бічний або повільний удар залишає звичайну фізичну реакцію.
Під час польоту спис тікає лише на сервері. Якщо ObjectData.bAlignToVelocity увімкнено і швидкість перевищує 100 см/с, актор плавно повертається за вектором швидкості (RInterpTo з AlignmentStiffness; у SpearRange — 20), а кутова швидкість обнуляється. Політ завершується, коли тіло засинає, симуляцію вимкнено або спис знову взяли. Launch(Velocity) запускає той самий політ без руки, наприклад зі стріли, яку випустив лук.
PenetrationDepth задає заглиблення вістря у світових сантиметрах від точки контакту. Після влучання IsEmbedded() повертає true, симуляція зупиняється, а спис рухається разом із поверхнею. Його можна знову захопити та метнути. Для мережевого прикріплення до рухомої цілі її актор і компонент мають бути доступні реплікації. Готовий приклад — SpearRange.
UInteractionDestructibleComponent — опціональне руйнування від ударів. Додайте його до replicated актора з primitive-root і hit events (готовий AInteractionPhysicsActor їх уже вмикає). Сервер зменшує здоров'я, а коли воно закінчується, усі машини показують ефект і актор знищується. Це простий gameplay-коефіцієнт, а не фізична модель міцності.
| Властивість, подія або метод | Значення |
|---|---|
Health |
Запас міцності, початково 50; задається в Class Defaults. GetHealth() повертає залишок на сервері |
DamagePerImpulse |
Шкода на одиницю імпульсу удару, початково 0.01 |
MinimumImpactDamage |
Удар має завдати більше цієї шкоди (початково 5), інакше не зараховується |
DestroyEffect |
Необов'язковий ефект у точці руйнування: система Niagara або Cascade |
OnImpactDestroyed(Location) |
Спрацьовує на сервері й на кожному клієнті перед знищенням: звук, уламки, власний ефект |
ApplyImpactDamage(Amount, Location) |
Серверна шкода з вашої логіки: вибух, удар мечем тощо |
Наприклад, ящик із Health = 30 і типовими коефіцієнтами не помічає ударів з імпульсом до 500 (шкода до 5), а удар з імпульсом 1500 забирає 15 здоров'я: двох таких ударів досить. Покрокова вправа — урок 6.
Як вибрати режим¶
| Потрібно | Налаштування |
|---|---|
| Предмет лежить на стійці й не падає до першого підбору | bStartWithPhysics=false у ObjectData |
| Предмет одразу падає й котиться | bStartWithPhysics=true |
| Кинутий предмет має «заснути» й прокидатися від ударів | PostThrowBehavior=SleepWhenSettled |
| Кинутий предмет має гарантовано зупинитися через N секунд | PostThrowBehavior=DisablePhysicsFixedTime, PhysicsDisableDelay=N |
| Предмет у руці не повинен проходити крізь стіни | профіль із Movement=Physics (08) |
| Кинуті предмети мають ранити або ламати | bApplyImpactDamage=true в ObjectData, за потреби UInteractionDestructibleComponent на цілі |
| Модель для огляду, яка лишається в повітрі після відпускання | bSimulateOnRelease=false, bAllowThrow=false |