claude-code-arcane 2.3.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +15 -0
- package/README.md +54 -6
- package/agents/game/ue-blueprint-specialist.md +125 -0
- package/agents/game/ue-gas-specialist.md +133 -0
- package/agents/game/ue-umg-specialist.md +131 -0
- package/dist/cli.js +5 -0
- package/docs/SKILLS-CATALOG.md +42 -3
- package/docs/USER-GUIDE.md +2 -2
- package/hooks/detect-unreal.sh +90 -0
- package/package.json +1 -1
- package/profiles/unreal-dev.yaml +97 -0
- package/rules/gamedev/unreal-code.md +125 -0
- package/skills/install-mcp/SKILL.md +135 -46
- package/skills/install-mcp/references/unreal-operations.md +55 -0
- package/skills/ue-actor-component-architecture/SKILL.md +509 -0
- package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
- package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
- package/skills/ue-ai-navigation/SKILL.md +526 -0
- package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
- package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
- package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
- package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
- package/skills/ue-animation-system/SKILL.md +521 -0
- package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
- package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
- package/skills/ue-async-threading/SKILL.md +433 -0
- package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
- package/skills/ue-async-threading/references/threading-patterns.md +345 -0
- package/skills/ue-audio-system/SKILL.md +527 -0
- package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
- package/skills/ue-blueprints/SKILL.md +134 -0
- package/skills/ue-blueprints/references/communication.md +82 -0
- package/skills/ue-character-movement/SKILL.md +475 -0
- package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
- package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
- package/skills/ue-cpp-foundations/SKILL.md +533 -0
- package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
- package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
- package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
- package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
- package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
- package/skills/ue-data-assets-tables/SKILL.md +527 -0
- package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
- package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
- package/skills/ue-editor-tools/SKILL.md +523 -0
- package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
- package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
- package/skills/ue-game-features/SKILL.md +477 -0
- package/skills/ue-game-features/references/experience-system.md +222 -0
- package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
- package/skills/ue-gameplay-abilities/SKILL.md +518 -0
- package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
- package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
- package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
- package/skills/ue-gameplay-framework/SKILL.md +466 -0
- package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
- package/skills/ue-input-system/SKILL.md +394 -0
- package/skills/ue-input-system/references/cpp-setup.md +131 -0
- package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
- package/skills/ue-input-system/references/input-action-reference.md +731 -0
- package/skills/ue-mass-entity/SKILL.md +476 -0
- package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
- package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
- package/skills/ue-materials-rendering/SKILL.md +526 -0
- package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
- package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
- package/skills/ue-module-build-system/SKILL.md +487 -0
- package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
- package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
- package/skills/ue-naming-conventions/SKILL.md +142 -0
- package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
- package/skills/ue-naming-conventions/references/content-structure.md +83 -0
- package/skills/ue-networking-replication/SKILL.md +452 -0
- package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
- package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
- package/skills/ue-niagara-effects/SKILL.md +531 -0
- package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
- package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
- package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
- package/skills/ue-packaging/SKILL.md +116 -0
- package/skills/ue-physics-collision/SKILL.md +423 -0
- package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
- package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
- package/skills/ue-procedural-generation/SKILL.md +505 -0
- package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
- package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
- package/skills/ue-project-context/SKILL.md +305 -0
- package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
- package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
- package/skills/ue-serialization-savegames/SKILL.md +524 -0
- package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
- package/skills/ue-state-trees/SKILL.md +489 -0
- package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
- package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
- package/skills/ue-testing-debugging/SKILL.md +520 -0
- package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
- package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
- package/skills/ue-ui-umg-slate/SKILL.md +431 -0
- package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
- package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
- package/skills/ue-world-level-streaming/SKILL.md +518 -0
- package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
- package/templates/gamedev/unreal-project-context.md +107 -0
|
@@ -0,0 +1,115 @@
|
|
|
1
|
+
# Niagara VFX — Editor-Side Workflow
|
|
2
|
+
|
|
3
|
+
> Adapted from the `unreal-niagara` skill in [awesome-gamedev-agent-skills](https://github.com/gamedev-skills/awesome-gamedev-agent-skills) (Apache-2.0). Cross-skill references were remapped to Arcane slash commands.
|
|
4
|
+
|
|
5
|
+
Build and control real-time visual effects in UE5 with Niagara: understand the
|
|
6
|
+
System/Emitter/Module hierarchy, expose parameters you can drive from gameplay, and spawn
|
|
7
|
+
effects at runtime. Targets **UE 5.8**. (Niagara replaces the legacy Cascade system.)
|
|
8
|
+
|
|
9
|
+
## When to use
|
|
10
|
+
|
|
11
|
+
- Use when creating a Niagara System (`NS_`) and Emitters (`NE_`), wiring modules in the
|
|
12
|
+
spawn/update stages, exposing **User** parameters to gameplay, or spawning/driving an effect
|
|
13
|
+
(impact, muzzle flash, fire, magic) from Blueprint or C++.
|
|
14
|
+
- Use when the project has Niagara `NS_`/`NE_` assets or references `UNiagaraComponent`.
|
|
15
|
+
|
|
16
|
+
**When *not* to use:** material/shader authoring (the look of a surface, not particles) is a
|
|
17
|
+
separate topic; `shader-programming` covers cross-engine shader concepts. Audio for the effect
|
|
18
|
+
→ `audio-design`.
|
|
19
|
+
|
|
20
|
+
## Core workflow
|
|
21
|
+
|
|
22
|
+
1. **Understand the hierarchy.** A **Niagara System** (`NS_`) is the effect you place/spawn; it
|
|
23
|
+
contains one or more **Emitters** (`NE_`, often emitter *templates*). Each emitter runs in
|
|
24
|
+
stages: **Emitter Spawn/Update**, **Particle Spawn/Update**, optional **Event Handler**, and
|
|
25
|
+
**Render**.
|
|
26
|
+
2. **Build behaviour from Modules**, which execute top-to-bottom in each stage (Spawn Rate,
|
|
27
|
+
Add Velocity, Gravity Force, Color over Life, etc.). Order matters — a later module reads the
|
|
28
|
+
values earlier ones wrote.
|
|
29
|
+
3. **Know the parameter namespaces:** `System`, `Emitter`, `Particle`, and **`User`**. Only
|
|
30
|
+
**User-namespace** parameters are exposed to and settable from Blueprint/C++; the others are
|
|
31
|
+
internal to the simulation.
|
|
32
|
+
4. **Spawn at runtime** with `UNiagaraFunctionLibrary::SpawnSystemAtLocation` (world position)
|
|
33
|
+
or `SpawnSystemAttached` (follows a component/socket), which return a `UNiagaraComponent`.
|
|
34
|
+
5. **Drive the effect** by setting its User parameters on the returned component (color, spawn
|
|
35
|
+
rate, a target position) and `Activate`/`Deactivate` it.
|
|
36
|
+
6. **Verify** in the Niagara editor preview and in-level; check bounds (especially GPU
|
|
37
|
+
emitters), and confirm the effect culls/destroys correctly.
|
|
38
|
+
|
|
39
|
+
## Patterns
|
|
40
|
+
|
|
41
|
+
### 1. Spawn a one-shot effect at a world location (C++)
|
|
42
|
+
|
|
43
|
+
```cpp
|
|
44
|
+
#include "NiagaraFunctionLibrary.h"
|
|
45
|
+
#include "NiagaraComponent.h"
|
|
46
|
+
|
|
47
|
+
// ImpactSystem is a UPROPERTY(EditAnywhere) TObjectPtr<UNiagaraSystem>.
|
|
48
|
+
void AProjectile::SpawnImpact(const FVector& Location, const FRotator& Rotation)
|
|
49
|
+
{
|
|
50
|
+
UNiagaraComponent* FX = UNiagaraFunctionLibrary::SpawnSystemAtLocation(
|
|
51
|
+
GetWorld(), ImpactSystem, Location, Rotation);
|
|
52
|
+
// FX auto-destroys when finished for a one-shot (system marked non-looping).
|
|
53
|
+
}
|
|
54
|
+
```
|
|
55
|
+
|
|
56
|
+
### 2. Spawn attached to a socket (muzzle flash that follows the gun)
|
|
57
|
+
|
|
58
|
+
```cpp
|
|
59
|
+
UNiagaraComponent* Muzzle = UNiagaraFunctionLibrary::SpawnSystemAttached(
|
|
60
|
+
MuzzleSystem, WeaponMesh, FName("MuzzleSocket"),
|
|
61
|
+
FVector::ZeroVector, FRotator::ZeroRotator,
|
|
62
|
+
EAttachLocation::SnapToTarget, /*bAutoDestroy*/ true);
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
### 3. Drive an exposed User parameter at runtime
|
|
66
|
+
|
|
67
|
+
```cpp
|
|
68
|
+
// Only User-namespace parameters can be set from gameplay. Names match the User parameter.
|
|
69
|
+
if (UNiagaraComponent* Fire = UNiagaraFunctionLibrary::SpawnSystemAttached(
|
|
70
|
+
FireSystem, RootComponent, NAME_None, FVector::ZeroVector, FRotator::ZeroRotator,
|
|
71
|
+
EAttachLocation::KeepRelativeOffset, /*bAutoDestroy*/ false))
|
|
72
|
+
{
|
|
73
|
+
Fire->SetVariableFloat(FName("SpawnRate"), 250.f); // User.SpawnRate
|
|
74
|
+
Fire->SetVariableLinearColor(FName("FireColor"), FLinearColor::Red);
|
|
75
|
+
}
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
### 4. Blueprint equivalent (node flow)
|
|
79
|
+
|
|
80
|
+
```text
|
|
81
|
+
Spawn System at Location (System = NS_Impact, Location, Rotation) -> returns Niagara Component
|
|
82
|
+
On the returned component:
|
|
83
|
+
Set Niagara Variable (Float) Name="SpawnRate" Value=250
|
|
84
|
+
Set Niagara Variable (LinearColor) Name="FireColor" Value=Red
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
## Pitfalls
|
|
88
|
+
|
|
89
|
+
- **Trying to set a System/Emitter/Particle parameter from gameplay** — it won't take. Expose
|
|
90
|
+
it in the **User** namespace; only User parameters are settable via the component.
|
|
91
|
+
- **Using Cascade tutorials** — Cascade is legacy/deprecated. Niagara is the current system; the
|
|
92
|
+
emitter/module workflow differs.
|
|
93
|
+
- **Effect disappears or doesn't cull right** — fixed/incorrect bounds, especially for **GPU
|
|
94
|
+
Compute** emitters which need explicit Fixed Bounds. Set bounds on the emitter/system.
|
|
95
|
+
- **Looping effect never stops** — spawned with `bAutoDestroy = false` and never
|
|
96
|
+
`Deactivate()`d; manage the returned component's lifetime, or mark the system non-looping for
|
|
97
|
+
one-shots.
|
|
98
|
+
- **GPU sim can't drive gameplay** — GPU particle data isn't readily read back to the CPU;
|
|
99
|
+
collision/events that gameplay must react to should use CPU emitters (or Niagara → gameplay
|
|
100
|
+
via the data interface), not GPU.
|
|
101
|
+
- **Module order bugs** — a Force/Velocity module placed before the one that initializes the
|
|
102
|
+
value reads zero. Mind the top-to-bottom stack order.
|
|
103
|
+
|
|
104
|
+
## References
|
|
105
|
+
|
|
106
|
+
- Primary docs: "Overview of Niagara Effects"
|
|
107
|
+
(`https://dev.epicgames.com/documentation/en-us/unreal-engine/overview-of-niagara-effects-for-unreal-engine`)
|
|
108
|
+
and the `UNiagaraFunctionLibrary` / `UNiagaraComponent` API. Add the `Niagara` module to
|
|
109
|
+
`*.Build.cs` for C++ access.
|
|
110
|
+
|
|
111
|
+
## Related skills
|
|
112
|
+
|
|
113
|
+
- `shader-programming` — material/shader concepts for particle materials.
|
|
114
|
+
- `/ue-cpp-foundations` — spawning effects from gameplay code and module setup.
|
|
115
|
+
- `/ue-blueprints` — triggering effects from visual scripts.
|
|
@@ -0,0 +1,116 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ue-packaging
|
|
3
|
+
description: "Packaging and cooking — build configurations, cook vs package, Game Default Map, RunUAT BuildCookRun, platform SDKs"
|
|
4
|
+
category: "gamedev"
|
|
5
|
+
argument-hint: "[platform o build config]"
|
|
6
|
+
user-invocable: true
|
|
7
|
+
allowed-tools: Read, Glob, Grep, Bash, Write, Edit
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# UE Packaging & Cooking
|
|
11
|
+
|
|
12
|
+
Turn a UE5 project into a runnable, distributable build: choose the right build configuration, cook content, set the launch map, and package — from the editor or the command line.
|
|
13
|
+
|
|
14
|
+
Ask before writing: this skill edits `Config/Default*.ini`, packaging settings and CI build scripts. Propose the change and get approval before using Write or Edit.
|
|
15
|
+
|
|
16
|
+
## Context Check
|
|
17
|
+
|
|
18
|
+
Read `docs/unreal/project-context.md` before proceeding. Confirm:
|
|
19
|
+
|
|
20
|
+
- Engine version and whether the project is Blueprint-only (`DebugGame` is unavailable there)
|
|
21
|
+
- Target platforms and which platform SDKs are actually installed
|
|
22
|
+
- Whether builds run locally, on CI, or both — this decides editor flow vs `RunUAT`
|
|
23
|
+
|
|
24
|
+
## When to Use
|
|
25
|
+
|
|
26
|
+
- Producing a build (test or release), choosing Development vs Shipping, cooking content, configuring Packaging / Maps & Modes settings, or automating builds with `RunUAT BuildCookRun` for CI.
|
|
27
|
+
- The goal is a packaged player rather than running in-editor.
|
|
28
|
+
|
|
29
|
+
**When not to use:** storefront submission and release process → `/release-checklist`. Editor-time gameplay iteration is not packaging.
|
|
30
|
+
|
|
31
|
+
## Core Workflow
|
|
32
|
+
|
|
33
|
+
1. **Set the launch map.** Project Settings → **Maps & Modes** → **Game Default Map** is what a packaged build loads first. Wrong or empty here is the most common "packaged game is black" cause.
|
|
34
|
+
2. **Pick the build configuration.** **Development** (default; optimized but keeps logging/stats/console for testing) vs **Shipping** (all optimizations, debugging tools stripped — for release). `DebugGame`/`Debug` are for debugging engine/game code and aren't for distribution; `DebugGame` isn't available for Blueprint-only projects.
|
|
35
|
+
3. **Understand cook vs package.** **Cooking** converts assets to the target platform's format and packs them into `.pak` files. **Packaging** bundles the compiled executable plus cooked content into a standalone, distributable set of files. Packaging runs a cook as part of it.
|
|
36
|
+
4. **Package from the editor:** the **Platforms** menu → choose the platform → set the Binary Configuration → **Package Project** → pick an output folder.
|
|
37
|
+
5. **Or build from the command line** with the Unreal Automation Tool (`RunUAT BuildCookRun`) for repeatable and CI builds.
|
|
38
|
+
6. **Tune Packaging settings** (Project Settings → **Packaging**): which maps and directories to cook, full-rebuild, compression, and whether to build all maps.
|
|
39
|
+
7. **Verify by running the packaged build**, not just by a successful cook — launch the executable and confirm it loads the right map and runs.
|
|
40
|
+
|
|
41
|
+
## Patterns
|
|
42
|
+
|
|
43
|
+
### 1. Editor packaging (the menu path)
|
|
44
|
+
|
|
45
|
+
```text
|
|
46
|
+
Platforms (toolbar)
|
|
47
|
+
-> Windows
|
|
48
|
+
-> Binary Configuration -> Development | Shipping
|
|
49
|
+
-> Content Management -> Package Project
|
|
50
|
+
-> choose/confirm the staging output folder
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
### 2. Command-line build with UAT (CI-friendly)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Cook + build + stage + pak + archive a Shipping Windows build.
|
|
57
|
+
RunUAT BuildCookRun \
|
|
58
|
+
-project="C:/Path/MyGame.uproject" \
|
|
59
|
+
-noP4 -platform=Win64 -clientconfig=Shipping \
|
|
60
|
+
-cook -allmaps -build -stage -pak -archive \
|
|
61
|
+
-archivedirectory="C:/Builds/MyGame"
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
`RunUAT` lives in `Engine/Build/BatchFiles/` (`RunUAT.bat` on Windows, `RunUAT.sh` on macOS/Linux). Drop `-allmaps` and pass `-map=Map1+Map2` to cook a subset.
|
|
65
|
+
|
|
66
|
+
### 3. Cook only (no packaging), e.g. to refresh content
|
|
67
|
+
|
|
68
|
+
```bash
|
|
69
|
+
RunUAT BuildCookRun -project="C:/Path/MyGame.uproject" -noP4 \
|
|
70
|
+
-platform=Win64 -clientconfig=Development -cook -skipstage
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
## Common Mistakes
|
|
74
|
+
|
|
75
|
+
- **Packaged build loads a black or empty level** — Game Default Map isn't set, or that map wasn't cooked. Set it in Maps & Modes and ensure it's included in the cook.
|
|
76
|
+
- **Shipping a Development build** — Development keeps logging/console/stats and is slower; ship **Shipping**. Conversely, Shipping strips `UE_LOG` and the console, so debugging a Shipping-only issue needs Development or `Test`.
|
|
77
|
+
- **A referenced map or asset is missing at runtime** — it wasn't cooked. Add it to the Packaging settings' maps/directories to cook, or cook all maps.
|
|
78
|
+
- **Build fails on the platform** — the platform SDK or toolchain isn't installed (Windows build tools, Android SDK/NDK, console SDKs). Install the platform's prerequisites.
|
|
79
|
+
- **Expecting Blueprint Nativization** — it was **removed in UE5**. Don't rely on it for performance; profile and move hot logic to C++ instead.
|
|
80
|
+
- **First cook is very slow** — shaders and all assets cook from scratch, and subsequent cooks are incremental. Don't mistake a slow first cook for a hang.
|
|
81
|
+
- **Cooking secrets into the build** — config files staged into a packaged build are readable. Keep credentials out of `Config/`.
|
|
82
|
+
|
|
83
|
+
## Reference Files
|
|
84
|
+
|
|
85
|
+
Primary docs: [Packaging Your Project](https://dev.epicgames.com/documentation/en-us/unreal-engine/packaging-your-project), plus the Build Configurations and `BuildCookRun` references.
|
|
86
|
+
|
|
87
|
+
---
|
|
88
|
+
|
|
89
|
+
## Related Skills
|
|
90
|
+
|
|
91
|
+
- `/ue-module-build-system` — `Build.cs`/`Target.cs` and module wiring that packaging depends on
|
|
92
|
+
- `/ue-cpp-foundations` — moving hot logic to C++ now that BP nativization is gone
|
|
93
|
+
- `/ue-data-assets-tables` — Asset Manager and Primary Asset types that drive what gets cooked
|
|
94
|
+
- `/ue-testing-debugging` — automation tests that should gate a release build
|
|
95
|
+
|
|
96
|
+
---
|
|
97
|
+
|
|
98
|
+
## Checklist
|
|
99
|
+
|
|
100
|
+
Validate before considering the work done:
|
|
101
|
+
|
|
102
|
+
- [ ] Game Default Map is set and included in the cook
|
|
103
|
+
- [ ] Build configuration matches the intent (Shipping for release, Development for testing)
|
|
104
|
+
- [ ] The packaged executable was launched and verified, not just cooked successfully
|
|
105
|
+
- [ ] No credentials or internal config were staged into the build
|
|
106
|
+
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
107
|
+
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
108
|
+
|
|
109
|
+
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that produces a broken or unshippable build; fix it before handing the work over.
|
|
110
|
+
|
|
111
|
+
## Next Steps
|
|
112
|
+
|
|
113
|
+
- `/release-checklist` — full release gate before distribution
|
|
114
|
+
- `/patch-notes` — user-facing notes for the packaged build
|
|
115
|
+
- `/code-review` — architectural and quality review of the change
|
|
116
|
+
- `/commit` — conventional commit once the change is verified
|
|
@@ -0,0 +1,423 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: ue-physics-collision
|
|
3
|
+
description: "Collision detection, traces, physics simulation, physical interactions, Chaos physics"
|
|
4
|
+
category: "gamedev"
|
|
5
|
+
argument-hint: "[interaction o collision setup]"
|
|
6
|
+
user-invocable: true
|
|
7
|
+
allowed-tools: Read, Glob, Grep, Bash, Write, Edit
|
|
8
|
+
---
|
|
9
|
+
|
|
10
|
+
# UE Physics & Collision
|
|
11
|
+
|
|
12
|
+
You are an expert in Unreal Engine's physics and collision systems, including collision channels, trace queries, collision events, physics bodies, and the Chaos physics engine.
|
|
13
|
+
|
|
14
|
+
Ask before writing: this skill edits collision presets, physics assets and trace code. Propose the change and get approval before using Write or Edit.
|
|
15
|
+
|
|
16
|
+
---
|
|
17
|
+
|
|
18
|
+
## Step 1: Read Project Context
|
|
19
|
+
|
|
20
|
+
Read `docs/unreal/project-context.md` to confirm:
|
|
21
|
+
- UE version (Chaos is the default physics backend from UE 5.0; PhysX was deprecated)
|
|
22
|
+
- Which modules need `"PhysicsCore"` and `"Engine"` in their `Build.cs`
|
|
23
|
+
- Whether the project uses skeletal meshes with physics assets, or primarily static mesh collision
|
|
24
|
+
- Dedicated server targets (affects whether physics simulation should run server-side)
|
|
25
|
+
|
|
26
|
+
---
|
|
27
|
+
|
|
28
|
+
## Step 2: Identify the Need
|
|
29
|
+
|
|
30
|
+
Ask which area applies if not stated:
|
|
31
|
+
1. **Collision setup** — channels, profiles, responses on components
|
|
32
|
+
2. **Trace queries** — line traces, sweeps, overlap queries for gameplay logic
|
|
33
|
+
3. **Collision events** — OnComponentHit, OnBeginOverlap, OnEndOverlap delegates
|
|
34
|
+
4. **Physics simulation** — rigid body sim, forces, impulses, damping, constraints
|
|
35
|
+
5. **Physical materials** — friction, restitution, surface type detection
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## Collision Channels & Profiles
|
|
40
|
+
|
|
41
|
+
### ECollisionChannel — built-in channels
|
|
42
|
+
|
|
43
|
+
```cpp
|
|
44
|
+
ECC_WorldStatic, ECC_WorldDynamic, ECC_Pawn, ECC_PhysicsBody,
|
|
45
|
+
ECC_Vehicle, ECC_Destructible // object channels (what an object IS)
|
|
46
|
+
ECC_Visibility, ECC_Camera // trace channels (used for queries)
|
|
47
|
+
// Custom: ECC_GameTraceChannel1..ECC_GameTraceChannel18
|
|
48
|
+
```
|
|
49
|
+
|
|
50
|
+
**Responses**: `ECR_Ignore` / `ECR_Overlap` (events, no block) / `ECR_Block` (physical block + events).
|
|
51
|
+
|
|
52
|
+
**Built-in profiles**: `BlockAll`, `BlockAllDynamic`, `OverlapAll`, `OverlapAllDynamic`, `Pawn`, `PhysicsActor`, `NoCollision`.
|
|
53
|
+
|
|
54
|
+
### Setting Collision in C++
|
|
55
|
+
|
|
56
|
+
```cpp
|
|
57
|
+
MyMesh->SetCollisionProfileName(TEXT("BlockAll")); // preferred — sets all at once
|
|
58
|
+
MyMesh->SetCollisionEnabled(ECollisionEnabled::QueryAndPhysics);
|
|
59
|
+
// ECollisionEnabled: NoCollision | QueryOnly | PhysicsOnly | QueryAndPhysics
|
|
60
|
+
MyMesh->SetCollisionObjectType(ECC_PhysicsBody);
|
|
61
|
+
MyMesh->SetCollisionResponseToAllChannels(ECR_Block);
|
|
62
|
+
MyMesh->SetCollisionResponseToChannel(ECC_Pawn, ECR_Overlap);
|
|
63
|
+
MyMesh->SetCollisionResponseToChannel(ECC_Camera, ECR_Ignore);
|
|
64
|
+
```
|
|
65
|
+
|
|
66
|
+
### Object Type Channels vs Trace Channels
|
|
67
|
+
|
|
68
|
+
**Object type channels** describe what an actor IS (Pawn, WorldDynamic, Vehicle). Every component has exactly one object type. **Trace channels** are used for queries — they define what a trace is LOOKING FOR (Visibility, Camera, Weapon). This distinction determines which query function to use: `ByObjectType` matches the target's object type channel; `ByChannel` uses the querier's trace channel and checks responses. Most gameplay traces use trace channels (`ECC_Visibility`, custom `Weapon`); overlap queries for "find all pawns" use object type (`ECC_Pawn`).
|
|
69
|
+
|
|
70
|
+
### Custom Channels — DefaultEngine.ini
|
|
71
|
+
|
|
72
|
+
```ini
|
|
73
|
+
[/Script/Engine.CollisionProfile]
|
|
74
|
+
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel1,DefaultResponse=ECR_Block,bTraceType=True,bStaticObject=False,Name="Weapon")
|
|
75
|
+
+DefaultChannelResponses=(Channel=ECC_GameTraceChannel2,DefaultResponse=ECR_Block,bTraceType=False,bStaticObject=False,Name="Interactable")
|
|
76
|
+
+Profiles=(Name="Interactable",CollisionEnabled=QueryAndPhysics,ObjectTypeName="Interactable",CustomResponses=((Channel="Weapon",Response=ECR_Ignore),(Channel="Visibility",Response=ECR_Block)))
|
|
77
|
+
```
|
|
78
|
+
|
|
79
|
+
`bTraceType=True` = trace channel; `bTraceType=False` = object type channel. They use separate query functions.
|
|
80
|
+
|
|
81
|
+
See `references/collision-channel-setup.md` for full profile examples.
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
## Trace Queries
|
|
86
|
+
|
|
87
|
+
### FCollisionQueryParams
|
|
88
|
+
|
|
89
|
+
```cpp
|
|
90
|
+
FCollisionQueryParams Params;
|
|
91
|
+
Params.TraceTag = TEXT("WeaponTrace"); // for profiling/debug
|
|
92
|
+
Params.bTraceComplex = false; // false=simple hull (fast); true=per-poly (expensive)
|
|
93
|
+
Params.bReturnPhysicalMaterial = true; // populates Hit.PhysMaterial
|
|
94
|
+
Params.bReturnFaceIndex = false; // expensive, only when needed
|
|
95
|
+
Params.AddIgnoredActor(this);
|
|
96
|
+
Params.AddIgnoredComponent(MyComp);
|
|
97
|
+
```
|
|
98
|
+
|
|
99
|
+
### World-Level Trace Functions (C++) — from `WorldCollision.h` via `UWorld`
|
|
100
|
+
|
|
101
|
+
```cpp
|
|
102
|
+
FHitResult Hit;
|
|
103
|
+
// By trace channel
|
|
104
|
+
GetWorld()->LineTraceSingleByChannel(Hit, Start, End, ECC_Visibility, Params);
|
|
105
|
+
GetWorld()->LineTraceMultiByChannel(Hits, Start, End, ECC_Visibility, Params);
|
|
106
|
+
// By object type
|
|
107
|
+
FCollisionObjectQueryParams ObjParams(ECC_PhysicsBody);
|
|
108
|
+
ObjParams.AddObjectTypesToQuery(ECC_WorldDynamic);
|
|
109
|
+
GetWorld()->LineTraceSingleByObjectType(Hit, Start, End, ObjParams, Params);
|
|
110
|
+
// By profile
|
|
111
|
+
GetWorld()->LineTraceSingleByProfile(Hit, Start, End, TEXT("BlockAll"), Params);
|
|
112
|
+
```
|
|
113
|
+
|
|
114
|
+
### Sweep Queries — FCollisionShape (from `CollisionShape.h`)
|
|
115
|
+
|
|
116
|
+
```cpp
|
|
117
|
+
FCollisionShape Sphere = FCollisionShape::MakeSphere(30.f);
|
|
118
|
+
FCollisionShape Box = FCollisionShape::MakeBox(FVector(50.f, 50.f, 50.f));
|
|
119
|
+
FCollisionShape Capsule = FCollisionShape::MakeCapsule(34.f, 88.f); // radius, half-height
|
|
120
|
+
|
|
121
|
+
GetWorld()->SweepSingleByChannel(Hit, Start, End, FQuat::Identity, ECC_Pawn, Sphere, Params);
|
|
122
|
+
GetWorld()->SweepMultiByChannel(Hits, Start, End, FQuat::Identity, ECC_Pawn, Sphere, Params);
|
|
123
|
+
GetWorld()->SweepSingleByObjectType(Hit, Start, End, FQuat::Identity, ObjParams, Sphere, Params);
|
|
124
|
+
GetWorld()->SweepSingleByProfile(Hit, Start, End, FQuat::Identity, TEXT("Pawn"), Sphere, Params);
|
|
125
|
+
```
|
|
126
|
+
|
|
127
|
+
### Overlap Queries
|
|
128
|
+
|
|
129
|
+
```cpp
|
|
130
|
+
TArray<FOverlapResult> Overlaps;
|
|
131
|
+
GetWorld()->OverlapMultiByObjectType(Overlaps, Center, FQuat::Identity,
|
|
132
|
+
FCollisionObjectQueryParams(ECC_Pawn), FCollisionShape::MakeSphere(500.f), Params);
|
|
133
|
+
for (const FOverlapResult& R : Overlaps) { AActor* A = R.GetActor(); }
|
|
134
|
+
|
|
135
|
+
// By trace channel (uses channel responses, not object type matching):
|
|
136
|
+
GetWorld()->OverlapMultiByChannel(
|
|
137
|
+
Overlaps, Center, FQuat::Identity, ECC_Pawn,
|
|
138
|
+
FCollisionShape::MakeSphere(Radius), QueryParams);
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### FHitResult — Key Fields
|
|
142
|
+
|
|
143
|
+
```cpp
|
|
144
|
+
Hit.bBlockingHit; // true if blocking
|
|
145
|
+
Hit.ImpactPoint; // world space contact point
|
|
146
|
+
Hit.ImpactNormal; // surface normal
|
|
147
|
+
Hit.Distance; // from Start to impact
|
|
148
|
+
Hit.BoneName; // skeletal mesh bone
|
|
149
|
+
Hit.GetActor();
|
|
150
|
+
Hit.GetComponent();
|
|
151
|
+
// Physical material (requires bReturnPhysicalMaterial=true):
|
|
152
|
+
if (UPhysicalMaterial* M = Hit.PhysMaterial.Get())
|
|
153
|
+
EPhysicalSurface S = UPhysicalMaterial::DetermineSurfaceType(M);
|
|
154
|
+
```
|
|
155
|
+
|
|
156
|
+
### Blueprint-Layer Traces (UKismetSystemLibrary)
|
|
157
|
+
|
|
158
|
+
```cpp
|
|
159
|
+
#include "Kismet/KismetSystemLibrary.h"
|
|
160
|
+
TArray<AActor*> Ignore = { this };
|
|
161
|
+
// LineTrace with debug draw (ETraceTypeQuery maps to ECollisionChannel)
|
|
162
|
+
UKismetSystemLibrary::LineTraceSingle(this, Start, End,
|
|
163
|
+
ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForDuration, Hit, true);
|
|
164
|
+
// SphereTrace
|
|
165
|
+
UKismetSystemLibrary::SphereTraceSingle(this, Start, End, 50.f,
|
|
166
|
+
ETraceTypeQuery::TraceTypeQuery1, false, Ignore, EDrawDebugTrace::ForOneFrame, Hit, true);
|
|
167
|
+
// By profile
|
|
168
|
+
UKismetSystemLibrary::LineTraceSingleByProfile(this, Start, End,
|
|
169
|
+
TEXT("BlockAll"), false, Ignore, EDrawDebugTrace::None, Hit, true);
|
|
170
|
+
```
|
|
171
|
+
|
|
172
|
+
### Async Traces
|
|
173
|
+
|
|
174
|
+
```cpp
|
|
175
|
+
FTraceHandle Handle = GetWorld()->AsyncLineTraceByChannel(
|
|
176
|
+
EAsyncTraceType::Single, Start, End, ECC_Visibility, Params);
|
|
177
|
+
// Read next frame:
|
|
178
|
+
FTraceDatum Datum;
|
|
179
|
+
if (GetWorld()->QueryTraceData(Handle, Datum) && Datum.OutHits.Num() > 0)
|
|
180
|
+
FHitResult& Hit = Datum.OutHits[0];
|
|
181
|
+
```
|
|
182
|
+
|
|
183
|
+
### Debug Visualization
|
|
184
|
+
|
|
185
|
+
```cpp
|
|
186
|
+
#if ENABLE_DRAW_DEBUG
|
|
187
|
+
DrawDebugLine(GetWorld(), Start, End, FColor::Red, false, 2.f);
|
|
188
|
+
DrawDebugSphere(GetWorld(), HitResult.ImpactPoint, 10.f, 12, FColor::Green, false, 2.f);
|
|
189
|
+
#endif
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
`DrawDebugLine` / `DrawDebugSphere` are from `DrawDebugHelpers.h`. Wrap in `ENABLE_DRAW_DEBUG` so they compile out in shipping builds. The bool param is `bPersistentLines`; the float param is `LifeTime` in seconds.
|
|
193
|
+
|
|
194
|
+
See `references/trace-patterns.md` for full gameplay patterns (hitscan, melee sweep, AoE, ground detection, async sensors).
|
|
195
|
+
|
|
196
|
+
---
|
|
197
|
+
|
|
198
|
+
## Collision Events
|
|
199
|
+
|
|
200
|
+
Delegate declarations from `PrimitiveComponent.h`:
|
|
201
|
+
- `OnComponentHit` — `(HitComp, OtherActor, OtherComp, NormalImpulse, FHitResult)` — physics collision
|
|
202
|
+
- `OnComponentBeginOverlap` — `(OverlappedComp, OtherActor, OtherComp, OtherBodyIndex, bFromSweep, SweepResult)`
|
|
203
|
+
- `OnComponentEndOverlap` — `(OverlappedComp, OtherActor, OtherComp, OtherBodyIndex)`
|
|
204
|
+
|
|
205
|
+
```cpp
|
|
206
|
+
// Hit events (physics collision)
|
|
207
|
+
MyMesh->SetNotifyRigidBodyCollision(true); // "Simulation Generates Hit Events"
|
|
208
|
+
MyMesh->OnComponentHit.AddDynamic(this, &AMyActor::OnHit);
|
|
209
|
+
|
|
210
|
+
UFUNCTION()
|
|
211
|
+
void AMyActor::OnHit(UPrimitiveComponent* HitComp, AActor* OtherActor,
|
|
212
|
+
UPrimitiveComponent* OtherComp, FVector NormalImpulse, const FHitResult& Hit) {}
|
|
213
|
+
|
|
214
|
+
// Overlap events — SetGenerateOverlapEvents(true) REQUIRED on BOTH components
|
|
215
|
+
MyMesh->SetGenerateOverlapEvents(true);
|
|
216
|
+
MyMesh->OnComponentBeginOverlap.AddDynamic(this, &AMyActor::OnBeginOverlap);
|
|
217
|
+
MyMesh->OnComponentEndOverlap.AddDynamic(this, &AMyActor::OnEndOverlap);
|
|
218
|
+
|
|
219
|
+
UFUNCTION()
|
|
220
|
+
void AMyActor::OnBeginOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
|
|
221
|
+
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex, bool bFromSweep, const FHitResult& SweepResult) {}
|
|
222
|
+
|
|
223
|
+
UFUNCTION()
|
|
224
|
+
void AMyActor::OnEndOverlap(UPrimitiveComponent* OverlappedComp, AActor* OtherActor,
|
|
225
|
+
UPrimitiveComponent* OtherComp, int32 OtherBodyIndex) {}
|
|
226
|
+
```
|
|
227
|
+
|
|
228
|
+
**Requirements:** Hit: `QueryAndPhysics`, `ECR_Block` on both, `SetNotifyRigidBodyCollision(true)`. Overlap: `ECR_Overlap` on both, `SetGenerateOverlapEvents(true)` on both.
|
|
229
|
+
|
|
230
|
+
---
|
|
231
|
+
|
|
232
|
+
## Physics Bodies
|
|
233
|
+
|
|
234
|
+
```cpp
|
|
235
|
+
// Enable simulation (PrimitiveComponent.h / BodyInstanceCore.h)
|
|
236
|
+
MyMesh->SetSimulatePhysics(true);
|
|
237
|
+
MyMesh->SetEnableGravity(true);
|
|
238
|
+
MyMesh->SetMassOverrideInKg(NAME_None, 50.f, true); // 50 kg
|
|
239
|
+
MyMesh->SetLinearDamping(0.1f);
|
|
240
|
+
MyMesh->SetAngularDamping(0.05f);
|
|
241
|
+
float Mass = MyMesh->GetMass();
|
|
242
|
+
|
|
243
|
+
// Forces and impulses
|
|
244
|
+
MyMesh->AddImpulse(FVector(0,0,1000), NAME_None, false); // bVelChange=true ignores mass
|
|
245
|
+
MyMesh->AddImpulseAtLocation(FVector(500,0,0), HitPoint); // adds torque
|
|
246
|
+
MyMesh->AddForce(FVector(0,0,9800), NAME_None, false); // continuous (per tick)
|
|
247
|
+
MyMesh->AddRadialImpulse(Center, 500.f, 2000.f, RIF_Linear, false);
|
|
248
|
+
MyMesh->SetPhysicsLinearVelocity(FVector(0,0,300)); // use sparingly
|
|
249
|
+
```
|
|
250
|
+
|
|
251
|
+
**FBodyInstanceCore key flags** (set via UPROPERTY/editor): `bSimulatePhysics`, `bOverrideMass`, `bEnableGravity`, `bAutoWeld`, `bStartAwake`, `bGenerateWakeEvents`, `bUpdateKinematicFromSimulation`.
|
|
252
|
+
|
|
253
|
+
**Collision complexity** (`BodySetupEnums.h`): `CTF_UseDefault`, `CTF_UseSimpleAndComplex`, `CTF_UseSimpleAsComplex`, `CTF_UseComplexAsSimple` (expensive, static only for physics).
|
|
254
|
+
|
|
255
|
+
### Physics Constraints
|
|
256
|
+
|
|
257
|
+
```cpp
|
|
258
|
+
UPhysicsConstraintComponent* C = NewObject<UPhysicsConstraintComponent>(this);
|
|
259
|
+
C->SetupAttachment(RootComponent);
|
|
260
|
+
C->SetConstrainedComponents(MeshA, NAME_None, MeshB, NAME_None);
|
|
261
|
+
C->SetAngularSwing1Limit(EAngularConstraintMotion::ACM_Limited, 45.f);
|
|
262
|
+
C->SetAngularTwistLimit(EAngularConstraintMotion::ACM_Free, 0.f);
|
|
263
|
+
C->SetLinearXLimit(ELinearConstraintMotion::LCM_Locked, 0.f);
|
|
264
|
+
C->RegisterComponent();
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
**Named constraint presets** (set via `ConstraintProfile` or editor Preset dropdown):
|
|
268
|
+
|
|
269
|
+
| Preset | Angular Limits | Linear Limits |
|
|
270
|
+
|---|---|---|
|
|
271
|
+
| Fixed | All locked | All locked |
|
|
272
|
+
| Hinge | One axis free | All locked |
|
|
273
|
+
| Prismatic | All locked | One axis free |
|
|
274
|
+
| Ball-and-Socket | All free | All locked |
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
278
|
+
## Physical Materials (UPhysicalMaterial)
|
|
279
|
+
|
|
280
|
+
From `PhysicalMaterials/PhysicalMaterial.h`:
|
|
281
|
+
|
|
282
|
+
```cpp
|
|
283
|
+
float Friction; // kinetic (0 = frictionless)
|
|
284
|
+
float StaticFriction; // before sliding starts
|
|
285
|
+
float Restitution; // 0 (no bounce) to 1 (elastic)
|
|
286
|
+
float Density; // g/cm^3 — used to compute mass from shape volume
|
|
287
|
+
EPhysicalSurface SurfaceType; // SurfaceType_Default, SurfaceType1..SurfaceType62
|
|
288
|
+
// FrictionCombineMode / RestitutionCombineMode: Average, Min, Multiply, Max
|
|
289
|
+
|
|
290
|
+
// Runtime override
|
|
291
|
+
MyMesh->SetPhysMaterialOverride(MyPhysMaterial);
|
|
292
|
+
|
|
293
|
+
// Detect surface from trace (requires bReturnPhysicalMaterial=true)
|
|
294
|
+
if (UPhysicalMaterial* M = Hit.PhysMaterial.Get())
|
|
295
|
+
{
|
|
296
|
+
EPhysicalSurface S = UPhysicalMaterial::DetermineSurfaceType(M);
|
|
297
|
+
switch (S) { case SurfaceType1: /* Metal */ break; }
|
|
298
|
+
}
|
|
299
|
+
```
|
|
300
|
+
|
|
301
|
+
---
|
|
302
|
+
|
|
303
|
+
## Chaos Physics (UE5)
|
|
304
|
+
|
|
305
|
+
UE5 uses **Chaos** by default (PhysX removed). Key architecture:
|
|
306
|
+
- `FChaosScene` (`ChaosScene.h`) owns the solver: `StartFrame()`, `SetUpForFrame()`, `EndFrame()`.
|
|
307
|
+
- Physics runs on a dedicated thread; game thread reads results at sync points.
|
|
308
|
+
- **Substepping**: enabled per Project Settings > Physics (`MaxSubsteps`, `MaxSubstepDeltaTime`). Enable when small/fast objects tunnel through thin geometry — substepping divides the physics tick into smaller increments so collisions are not missed.
|
|
309
|
+
- **Async physics**: runs simulation on a separate thread with one-frame latency. Enable via `UPhysicsSettings::bTickPhysicsAsync`. Use `UAsyncPhysicsInputComponent` on components that need physics-thread input callbacks.
|
|
310
|
+
|
|
311
|
+
Key `UPhysicsSettingsCore` fields (`PhysicsSettingsCore.h`):
|
|
312
|
+
```cpp
|
|
313
|
+
float DefaultGravityZ; // -980 cm/s^2 default
|
|
314
|
+
float BounceThresholdVelocity; // min velocity to bounce
|
|
315
|
+
float MaxAngularVelocity; // rad/s cap
|
|
316
|
+
float MaxDepenetrationVelocity;
|
|
317
|
+
float ContactOffsetMultiplier; // contact shell size
|
|
318
|
+
FChaosSolverConfiguration SolverOptions;
|
|
319
|
+
```
|
|
320
|
+
|
|
321
|
+
**EPhysicalSurface**: 62 configurable slots (`SurfaceType1..SurfaceType62`) mapped in Project Settings > Physics > Physical Surface.
|
|
322
|
+
|
|
323
|
+
**Geometry Collections (Chaos Destructibles)**: use `UGeometryCollectionComponent`. Fracture thresholds driven by `FPhysicalMaterialStrength` (TensileStrength, CompressionStrength, ShearStrength) and `FPhysicalMaterialDamageModifier` (DamageThresholdMultiplier) on `UPhysicalMaterial`.
|
|
324
|
+
|
|
325
|
+
---
|
|
326
|
+
|
|
327
|
+
### Cloth Simulation
|
|
328
|
+
|
|
329
|
+
```cpp
|
|
330
|
+
// Cloth uses UClothingAssetBase attached to USkeletalMeshComponent
|
|
331
|
+
// Enable in Mesh asset: Clothing → Add Clothing Data
|
|
332
|
+
// C++ access:
|
|
333
|
+
USkeletalMeshComponent* Mesh = GetMesh();
|
|
334
|
+
if (UClothingSimulationInteractor* Cloth = Mesh->GetClothingSimulationInteractor())
|
|
335
|
+
{
|
|
336
|
+
Cloth->PhysicsAssetUpdated(); // re-sync after physics asset change
|
|
337
|
+
Cloth->SetAnimDriveSpringStiffness(10.f); // blend anim ↔ cloth
|
|
338
|
+
}
|
|
339
|
+
```
|
|
340
|
+
|
|
341
|
+
### Field System
|
|
342
|
+
|
|
343
|
+
Field System actors apply forces, strain, and anchors to Chaos destruction and cloth:
|
|
344
|
+
|
|
345
|
+
```cpp
|
|
346
|
+
// Place AFieldSystemActor in level, add field nodes:
|
|
347
|
+
// URadialFalloff — distance-based falloff
|
|
348
|
+
// URadialVector — directional force from center
|
|
349
|
+
// UUniformVector — constant directional force
|
|
350
|
+
// UBoxFalloff — box-shaped field region
|
|
351
|
+
|
|
352
|
+
// Trigger destruction at runtime:
|
|
353
|
+
AFieldSystemActor* FieldActor = GetWorld()->SpawnActor<AFieldSystemActor>();
|
|
354
|
+
URadialFalloff* Falloff = NewObject<URadialFalloff>(FieldActor);
|
|
355
|
+
Falloff->SetRadialFalloff(1000000.f, 0.8f, 1.f, 0.f, 500.f, FVector::ZeroVector, EFieldFalloffType::Field_Falloff_Linear);
|
|
356
|
+
UFieldSystemMetaDataFilter* Meta = NewObject<UFieldSystemMetaDataFilter>(FieldActor);
|
|
357
|
+
Meta->SetMetaDataFilterType(EFieldFilterType::Field_Filter_All, EFieldObjectType::Field_Object_All, EFieldPositionType::Field_Position_CenterOfMass);
|
|
358
|
+
FieldActor->GetFieldSystemComponent()->ApplyPhysicsField(true, EFieldPhysicsType::Field_ExternalClusterStrain, Meta, Falloff);
|
|
359
|
+
```
|
|
360
|
+
|
|
361
|
+
---
|
|
362
|
+
|
|
363
|
+
## Common Mistakes & Anti-Patterns
|
|
364
|
+
|
|
365
|
+
**Wrong collision responses**: Overlap events require `ECR_Overlap` AND `bGenerateOverlapEvents=true` on BOTH components.
|
|
366
|
+
|
|
367
|
+
**Traces every Tick on many actors**: Use async traces or throttle to 5–10 Hz with a timer.
|
|
368
|
+
|
|
369
|
+
**QueryOnly vs PhysicsOnly confusion**: `QueryOnly` = traces only, no physics forces. `PhysicsOnly` = forces only, traces skip it. Use `QueryAndPhysics` for both.
|
|
370
|
+
|
|
371
|
+
**Complex collision in traces**: `bTraceComplex=true` is 4–10x more expensive. Default `false`; only enable for precise terrain interaction.
|
|
372
|
+
|
|
373
|
+
**Missing `SetNotifyRigidBodyCollision`**: `OnComponentHit` will never fire without it — this flag ("Simulation Generates Hit Events") is separate from collision response.
|
|
374
|
+
|
|
375
|
+
**Sweep vs overlap**: Sweep = shape moving along a path (movement, projectile). Overlap = shape at fixed point (AoE, proximity). Don't substitute one for the other.
|
|
376
|
+
|
|
377
|
+
**Physics on dedicated servers**: Disable skeletal ragdolls with `bSimulateSkeletalMeshOnDedicatedServer=false` unless server accuracy is required.
|
|
378
|
+
|
|
379
|
+
### Multiplayer & Replicated Actor Collision
|
|
380
|
+
|
|
381
|
+
In multiplayer, physics simulation runs on the server. Collision events (`OnComponentHit`, `OnBeginOverlap`) fire on the server only by default — clients do not receive these events unless you replicate them explicitly via RPCs. Clients see physics-simulated actor positions via `FRepMovement` (the replicated transform + velocity struct behind `bReplicateMovement`). Setting `bReplicateMovement = true` on an actor syncs its transform and linear/angular velocity; the underlying physics state itself is not replicated. For client-predicted physics (e.g., projectiles), simulate locally on the client and reconcile with server authority on correction. Cosmetic-only physics — ragdolls, debris, environmental props — can simulate on clients independently without server involvement, since visual fidelity matters more than authority.
|
|
382
|
+
|
|
383
|
+
---
|
|
384
|
+
|
|
385
|
+
## Required Module Dependencies
|
|
386
|
+
|
|
387
|
+
```csharp
|
|
388
|
+
// Build.cs
|
|
389
|
+
PublicDependencyModuleNames.AddRange(new string[] {
|
|
390
|
+
"Core", "CoreUObject",
|
|
391
|
+
"Engine", // UPrimitiveComponent, FHitResult, UWorld trace API
|
|
392
|
+
"PhysicsCore", // UPhysicalMaterial, FCollisionShape, FBodyInstanceCore
|
|
393
|
+
});
|
|
394
|
+
```
|
|
395
|
+
|
|
396
|
+
---
|
|
397
|
+
|
|
398
|
+
## Related Skills
|
|
399
|
+
|
|
400
|
+
- `/ue-actor-component-architecture` — `UPrimitiveComponent` lifecycle, attachment, registration
|
|
401
|
+
- `/ue-ai-navigation` — trace-based sensing and navmesh overlap queries
|
|
402
|
+
- `/ue-gameplay-abilities` — targeting systems built on trace and overlap queries
|
|
403
|
+
- `/ue-cpp-foundations` — delegate binding syntax and UFUNCTION requirements
|
|
404
|
+
|
|
405
|
+
---
|
|
406
|
+
|
|
407
|
+
## Checklist
|
|
408
|
+
|
|
409
|
+
Validate before considering the work done:
|
|
410
|
+
|
|
411
|
+
- [ ] Collision channels and presets are defined in config, not hardcoded per actor
|
|
412
|
+
- [ ] Traces use the narrowest channel and shape that answers the question
|
|
413
|
+
- [ ] Complex collision is avoided on anything queried frequently
|
|
414
|
+
- [ ] Conventions in `docs/unreal/project-context.md` were read and followed
|
|
415
|
+
- [ ] The Common Mistakes section of this skill was reviewed against the change
|
|
416
|
+
|
|
417
|
+
**PASS** — every item holds. **CONCERNS** — the work stands but at least one item is unresolved and worth flagging to the user. **FAIL** — an item is violated in a way that breaks correctness, replication or the frame budget; fix it before handing the work over.
|
|
418
|
+
|
|
419
|
+
## Next Steps
|
|
420
|
+
|
|
421
|
+
- `/perf-profile` — check physics and trace cost in the profiler
|
|
422
|
+
- `/code-review` — architectural and quality review of the change
|
|
423
|
+
- `/commit` — conventional commit once the change is verified
|