claude-code-arcane 2.3.0 → 2.5.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.
Files changed (141) hide show
  1. package/CHANGELOG.md +23 -0
  2. package/README.md +131 -41
  3. package/agents/game/ue-blueprint-specialist.md +125 -0
  4. package/agents/game/ue-gas-specialist.md +133 -0
  5. package/agents/game/ue-umg-specialist.md +131 -0
  6. package/dist/cli.js +642 -478
  7. package/docs/SKILLS-CATALOG.md +42 -3
  8. package/docs/USER-GUIDE.md +28 -54
  9. package/hooks/detect-unreal.sh +90 -0
  10. package/package.json +2 -1
  11. package/profiles/agile.yaml +1 -1
  12. package/profiles/ai.yaml +1 -1
  13. package/profiles/android-native.yaml +1 -1
  14. package/profiles/audio.yaml +1 -1
  15. package/profiles/backend-dotnet.yaml +1 -1
  16. package/profiles/backend-go.yaml +1 -1
  17. package/profiles/backend-nestjs.yaml +1 -1
  18. package/profiles/backend-nextjs.yaml +1 -1
  19. package/profiles/backend-ts.yaml +1 -1
  20. package/profiles/business.yaml +1 -1
  21. package/profiles/clevel.yaml +1 -1
  22. package/profiles/clickup.yaml +1 -1
  23. package/profiles/core.yaml +1 -1
  24. package/profiles/database.yaml +1 -1
  25. package/profiles/design.yaml +1 -1
  26. package/profiles/docs.yaml +1 -1
  27. package/profiles/ecommerce.yaml +1 -1
  28. package/profiles/finance.yaml +1 -1
  29. package/profiles/flutter.yaml +1 -1
  30. package/profiles/freelance.yaml +1 -1
  31. package/profiles/frontend.yaml +1 -1
  32. package/profiles/infra.yaml +1 -1
  33. package/profiles/integrations.yaml +1 -1
  34. package/profiles/ios-native.yaml +1 -1
  35. package/profiles/jira.yaml +1 -1
  36. package/profiles/job-hunt.yaml +1 -1
  37. package/profiles/marketing.yaml +1 -1
  38. package/profiles/mobile.yaml +1 -1
  39. package/profiles/regulatory.yaml +1 -1
  40. package/profiles/second-brain.yaml +1 -1
  41. package/profiles/security.yaml +1 -1
  42. package/profiles/self-improving.yaml +1 -1
  43. package/profiles/statusline.yaml +1 -1
  44. package/profiles/testing.yaml +1 -1
  45. package/profiles/unity-design.yaml +1 -1
  46. package/profiles/unity-dev.yaml +1 -1
  47. package/profiles/unreal-dev.yaml +97 -0
  48. package/profiles/visual-novel.yaml +1 -1
  49. package/rules/gamedev/unreal-code.md +125 -0
  50. package/skills/arcane-list/SKILL.md +12 -7
  51. package/skills/install-mcp/SKILL.md +135 -46
  52. package/skills/install-mcp/references/unreal-operations.md +55 -0
  53. package/skills/ue-actor-component-architecture/SKILL.md +509 -0
  54. package/skills/ue-actor-component-architecture/references/actor-lifecycle.md +301 -0
  55. package/skills/ue-actor-component-architecture/references/component-types.md +592 -0
  56. package/skills/ue-ai-navigation/SKILL.md +526 -0
  57. package/skills/ue-ai-navigation/references/behavior-tree-patterns.md +392 -0
  58. package/skills/ue-ai-navigation/references/behavior-tree-workflow.md +107 -0
  59. package/skills/ue-ai-navigation/references/custom-bttask.md +104 -0
  60. package/skills/ue-ai-navigation/references/eqs-reference.md +423 -0
  61. package/skills/ue-animation-system/SKILL.md +521 -0
  62. package/skills/ue-animation-system/references/anim-notify-reference.md +486 -0
  63. package/skills/ue-animation-system/references/locomotion-setup.md +550 -0
  64. package/skills/ue-async-threading/SKILL.md +433 -0
  65. package/skills/ue-async-threading/references/thread-safety-guide.md +213 -0
  66. package/skills/ue-async-threading/references/threading-patterns.md +345 -0
  67. package/skills/ue-audio-system/SKILL.md +527 -0
  68. package/skills/ue-audio-system/references/audio-setup-patterns.md +700 -0
  69. package/skills/ue-blueprints/SKILL.md +134 -0
  70. package/skills/ue-blueprints/references/communication.md +82 -0
  71. package/skills/ue-character-movement/SKILL.md +475 -0
  72. package/skills/ue-character-movement/references/cmc-extension-patterns.md +335 -0
  73. package/skills/ue-character-movement/references/movement-pipeline.md +189 -0
  74. package/skills/ue-cpp-foundations/SKILL.md +533 -0
  75. package/skills/ue-cpp-foundations/references/components-and-gc.md +107 -0
  76. package/skills/ue-cpp-foundations/references/container-patterns.md +544 -0
  77. package/skills/ue-cpp-foundations/references/delegate-patterns.md +497 -0
  78. package/skills/ue-cpp-foundations/references/gameplay-classes-cpp.md +136 -0
  79. package/skills/ue-cpp-foundations/references/property-specifiers.md +306 -0
  80. package/skills/ue-data-assets-tables/SKILL.md +527 -0
  81. package/skills/ue-data-assets-tables/references/asset-loading-patterns.md +306 -0
  82. package/skills/ue-data-assets-tables/references/data-driven-design.md +378 -0
  83. package/skills/ue-editor-tools/SKILL.md +523 -0
  84. package/skills/ue-editor-tools/references/detail-customization-patterns.md +395 -0
  85. package/skills/ue-editor-tools/references/editor-module-setup.md +480 -0
  86. package/skills/ue-game-features/SKILL.md +477 -0
  87. package/skills/ue-game-features/references/experience-system.md +222 -0
  88. package/skills/ue-game-features/references/game-feature-patterns.md +308 -0
  89. package/skills/ue-gameplay-abilities/SKILL.md +518 -0
  90. package/skills/ue-gameplay-abilities/references/ability-task-reference.md +391 -0
  91. package/skills/ue-gameplay-abilities/references/gameplay-effect-reference.md +397 -0
  92. package/skills/ue-gameplay-abilities/references/gas-setup-patterns.md +369 -0
  93. package/skills/ue-gameplay-framework/SKILL.md +466 -0
  94. package/skills/ue-gameplay-framework/references/framework-class-map.md +243 -0
  95. package/skills/ue-input-system/SKILL.md +394 -0
  96. package/skills/ue-input-system/references/cpp-setup.md +131 -0
  97. package/skills/ue-input-system/references/enhanced-input-workflow.md +117 -0
  98. package/skills/ue-input-system/references/input-action-reference.md +731 -0
  99. package/skills/ue-mass-entity/SKILL.md +476 -0
  100. package/skills/ue-mass-entity/references/mass-entity-patterns.md +319 -0
  101. package/skills/ue-mass-entity/references/mass-fragment-reference.md +119 -0
  102. package/skills/ue-materials-rendering/SKILL.md +526 -0
  103. package/skills/ue-materials-rendering/references/material-parameter-reference.md +216 -0
  104. package/skills/ue-materials-rendering/references/post-process-settings.md +383 -0
  105. package/skills/ue-module-build-system/SKILL.md +487 -0
  106. package/skills/ue-module-build-system/references/build-cs-reference.md +418 -0
  107. package/skills/ue-module-build-system/references/common-build-errors.md +381 -0
  108. package/skills/ue-naming-conventions/SKILL.md +142 -0
  109. package/skills/ue-naming-conventions/references/asset-name-modifiers.md +233 -0
  110. package/skills/ue-naming-conventions/references/content-structure.md +83 -0
  111. package/skills/ue-networking-replication/SKILL.md +452 -0
  112. package/skills/ue-networking-replication/references/replication-patterns.md +526 -0
  113. package/skills/ue-networking-replication/references/rpc-decision-guide.md +393 -0
  114. package/skills/ue-niagara-effects/SKILL.md +531 -0
  115. package/skills/ue-niagara-effects/references/niagara-data-interfaces.md +491 -0
  116. package/skills/ue-niagara-effects/references/niagara-parameter-types.md +153 -0
  117. package/skills/ue-niagara-effects/references/niagara-workflow.md +115 -0
  118. package/skills/ue-packaging/SKILL.md +116 -0
  119. package/skills/ue-physics-collision/SKILL.md +423 -0
  120. package/skills/ue-physics-collision/references/collision-channel-setup.md +218 -0
  121. package/skills/ue-physics-collision/references/trace-patterns.md +499 -0
  122. package/skills/ue-procedural-generation/SKILL.md +505 -0
  123. package/skills/ue-procedural-generation/references/pcg-node-reference.md +381 -0
  124. package/skills/ue-procedural-generation/references/procedural-mesh-patterns.md +940 -0
  125. package/skills/ue-project-context/SKILL.md +305 -0
  126. package/skills/ue-sequencer-cinematics/SKILL.md +506 -0
  127. package/skills/ue-sequencer-cinematics/references/sequencer-patterns.md +629 -0
  128. package/skills/ue-serialization-savegames/SKILL.md +524 -0
  129. package/skills/ue-serialization-savegames/references/save-system-architecture.md +705 -0
  130. package/skills/ue-state-trees/SKILL.md +489 -0
  131. package/skills/ue-state-trees/references/state-tree-mass-integration.md +184 -0
  132. package/skills/ue-state-trees/references/state-tree-patterns.md +321 -0
  133. package/skills/ue-testing-debugging/SKILL.md +520 -0
  134. package/skills/ue-testing-debugging/references/automation-test-patterns.md +387 -0
  135. package/skills/ue-testing-debugging/references/profiling-commands.md +357 -0
  136. package/skills/ue-ui-umg-slate/SKILL.md +431 -0
  137. package/skills/ue-ui-umg-slate/references/common-ui-setup.md +484 -0
  138. package/skills/ue-ui-umg-slate/references/widget-types.md +487 -0
  139. package/skills/ue-world-level-streaming/SKILL.md +518 -0
  140. package/skills/ue-world-level-streaming/references/streaming-patterns.md +414 -0
  141. package/templates/gamedev/unreal-project-context.md +107 -0
@@ -0,0 +1,489 @@
1
+ ---
2
+ name: ue-state-trees
3
+ description: "State Tree, state machines, StateTreeTask, StateTreeCondition, StateTreeEvaluator"
4
+ category: "gamedev"
5
+ argument-hint: "[state tree o behavior]"
6
+ user-invocable: true
7
+ allowed-tools: Read, Glob, Grep, Bash, Write, Edit
8
+ ---
9
+
10
+ # UE State Trees
11
+
12
+ You are an expert in Unreal Engine's State Tree system for building flexible, data-driven state machines.
13
+
14
+ Ask before writing: this skill edits StateTree assets, tasks, conditions and evaluators. Propose the change and get approval before using Write or Edit.
15
+
16
+ ## Context Check
17
+
18
+ Read `docs/unreal/project-context.md` to determine:
19
+ - Whether `StateTreeModule` and `GameplayStateTreeModule` plugins are enabled
20
+ - If Mass Entity integration is needed (`MassEntity`, `MassAIBehavior` plugins)
21
+ - Existing AI frameworks — behavior trees, custom FSMs to migrate from
22
+ - Schema types in use and any custom schemas
23
+
24
+ ## Information Gathering
25
+
26
+ Before implementing, clarify:
27
+ 1. What is the use case? (AI behavior, game logic, UI state, entity processing)
28
+ 2. What scale? (single actor with `UStateTreeComponent` vs thousands of Mass entities)
29
+ 3. How complex? (simple linear FSM vs hierarchical states with linked subtrees)
30
+ 4. Are there existing behavior trees to migrate from?
31
+ 5. What external data do tasks need? (actor references, subsystems, world state)
32
+
33
+ ---
34
+
35
+ ## StateTree Architecture
36
+
37
+ A State Tree is a hierarchical finite state machine authored as a `UStateTree` data asset:
38
+
39
+ ```
40
+ UStateTree (UDataAsset)
41
+ ├── UStateTreeSchema ← defines allowed context/external data
42
+ ├── States[] ← hierarchical state tree
43
+ │ ├── Tasks[] ← work performed while state is active
44
+ │ ├── Transitions[] ← rules for leaving this state
45
+ │ └── Conditions[] ← gates on transitions
46
+ ├── Evaluators[] ← global data providers (tick before transitions)
47
+ └── Parameters ← FInstancedPropertyBag default inputs
48
+ ```
49
+
50
+ **Runtime flow per tick:** 1) Evaluators tick, 2) Transitions checked from active leaf up to root, 3) If transition fires: ExitState on old tasks then EnterState on new, 4) Active tasks tick.
51
+
52
+ **Key classes:**
53
+
54
+ | Class | Role |
55
+ |-------|------|
56
+ | `UStateTree` | Data asset — call `IsReadyToRun()` before execution |
57
+ | `FStateTreeExecutionContext` | Per-tick context — constructed each frame, NOT persisted |
58
+ | `FStateTreeInstanceData` | Persistent runtime state — survives across ticks |
59
+ | `UStateTreeComponent` | Actor component that manages tree lifecycle |
60
+ | `EStateTreeRunStatus` | `Running`, `Stopped`, `Succeeded`, `Failed`, `Unset` |
61
+
62
+ **Build.cs modules**: `StateTreeModule`, `GameplayStateTreeModule`
63
+
64
+ The execution context is constructed per-tick from persistent instance data:
65
+ ```cpp
66
+ FStateTreeInstanceData InstanceData; // persists across frames
67
+ // Each tick:
68
+ FStateTreeExecutionContext Context(Owner, *StateTree, InstanceData);
69
+ Context.Tick(DeltaTime);
70
+ ```
71
+
72
+ This separates mutable state (`FStateTreeInstanceData`) from stateless execution logic, making State Trees safe for parallel evaluation in Mass Entity scenarios.
73
+
74
+ ---
75
+
76
+ ## Schema System
77
+
78
+ Schemas define what context data a State Tree can access, constraining valid tasks and conditions. This prevents authoring errors at edit time rather than runtime.
79
+
80
+ | Schema | Context Provided | Use Case |
81
+ |--------|-----------------|----------|
82
+ | `UStateTreeComponentSchema` | Actor + BrainComponent | General actor logic |
83
+ | `UStateTreeAIComponentSchema` | Above + `AIControllerClass` | AI behavior |
84
+ | `UMassStateTreeSchema` | Mass entity context | Mass Entity processing |
85
+
86
+ `UStateTreeComponentSchema` exposes `ContextActorClass` (`TSubclassOf<AActor>`) so the editor knows which components are available for property binding. `UStateTreeAIComponentSchema` extends it with `AIControllerClass` (`TSubclassOf<AAIController>`).
87
+
88
+ ### Custom Schemas
89
+
90
+ Subclass `UStateTreeSchema` for project-specific trees:
91
+
92
+ ```cpp
93
+ UCLASS()
94
+ class UMyGameSchema : public UStateTreeSchema
95
+ {
96
+ GENERATED_BODY()
97
+ public:
98
+ virtual bool IsStructAllowed(const UScriptStruct* InStruct) const override;
99
+ virtual bool IsExternalItemAllowed(const UStruct& InStruct) const override;
100
+ virtual TConstArrayView<FStateTreeExternalDataDesc> GetContextDataDescs() const override;
101
+
102
+ #if WITH_EDITOR
103
+ virtual bool AllowEvaluators() const override { return true; }
104
+ virtual bool AllowMultipleTasks() const override { return true; }
105
+ virtual bool AllowGlobalParameters() const override { return true; }
106
+ #endif // WITH_EDITOR
107
+ };
108
+ ```
109
+
110
+ Override `GetContextDataDescs()` to declare context objects (actor refs, subsystems). The editor uses this to validate property bindings.
111
+
112
+ ---
113
+
114
+ ## Tasks
115
+
116
+ Tasks are the primary work units in a state. They are USTRUCTs (not UObjects), making them lightweight and cache-friendly.
117
+
118
+ ### FStateTreeTaskBase API
119
+
120
+ Key virtuals (all `const` — tasks are immutable at runtime):
121
+
122
+ | Virtual | Returns | Called When |
123
+ |---------|---------|-------------|
124
+ | `EnterState(Context, Transition)` | `EStateTreeRunStatus` (default: Running) | State becomes active |
125
+ | `ExitState(Context, Transition)` | `void` | State is exited |
126
+ | `Tick(Context, DeltaTime)` | `EStateTreeRunStatus` (default: Running) | Each frame (if `bShouldCallTick`) |
127
+ | `StateCompleted(Context, Status, CompletedStates)` | `void` | Child state completes (REVERSE order) |
128
+ | `TriggerTransitions(Context)` | `void` | Only if `bShouldAffectTransitions` |
129
+
130
+ ### Behavioral Flags
131
+
132
+ | Flag | Default | Purpose |
133
+ |------|---------|---------|
134
+ | `bShouldStateChangeOnReselect` | `true` | Exit+Enter when transitioning to same state |
135
+ | `bShouldCallTick` | `true` | Enable per-frame Tick calls |
136
+ | `bShouldCallTickOnlyOnEvents` | `false` | Tick only when events are pending |
137
+ | `bShouldCopyBoundPropertiesOnTick` | `true` | Refresh property bindings each tick |
138
+ | `bShouldAffectTransitions` | `false` | Enable `TriggerTransitions` calls |
139
+
140
+ Set `bShouldCallTick = false` for fire-and-forget tasks that only need `EnterState`/`ExitState`.
141
+
142
+ ### Instance Data Pattern
143
+
144
+ Tasks are `const` at runtime — mutable per-instance state lives in a separate struct via the `typedef FInstanceDataType` pattern:
145
+
146
+ ```cpp
147
+ USTRUCT()
148
+ struct FMyTaskInstanceData
149
+ {
150
+ GENERATED_BODY()
151
+ float ElapsedTime = 0.f;
152
+ };
153
+
154
+ USTRUCT(meta=(DisplayName="My Custom Task"))
155
+ struct FMyTask : public FStateTreeTaskBase
156
+ {
157
+ GENERATED_BODY()
158
+ typedef FMyTaskInstanceData FInstanceDataType; // required — framework allocates storage
159
+
160
+ virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context,
161
+ const FStateTreeTransitionResult& Transition) const override
162
+ {
163
+ FInstanceDataType& Data = Context.GetInstanceData(*this);
164
+ Data.ElapsedTime = 0.f;
165
+ return EStateTreeRunStatus::Running;
166
+ }
167
+
168
+ virtual EStateTreeRunStatus Tick(FStateTreeExecutionContext& Context,
169
+ float DeltaTime) const override
170
+ {
171
+ FInstanceDataType& Data = Context.GetInstanceData(*this);
172
+ Data.ElapsedTime += DeltaTime;
173
+ return Data.ElapsedTime >= Duration
174
+ ? EStateTreeRunStatus::Succeeded : EStateTreeRunStatus::Running;
175
+ }
176
+
177
+ UPROPERTY(EditAnywhere, Category = "Parameter")
178
+ float Duration = 2.0f;
179
+ };
180
+ ```
181
+
182
+ See `references/state-tree-patterns.md` for complete task, condition, and evaluator templates.
183
+
184
+ ### Multiple Tasks Per State
185
+
186
+ When `AllowMultipleTasks()` is true, a state runs several tasks simultaneously. Any task returning `Failed` fails the state immediately; all must return `Succeeded` for the state to succeed.
187
+
188
+ ---
189
+
190
+ ## Conditions
191
+
192
+ Conditions gate transitions — evaluated to determine whether a transition should fire.
193
+
194
+ ```cpp
195
+ USTRUCT(meta=(Hidden))
196
+ struct FStateTreeConditionBase : public FStateTreeNodeBase
197
+ {
198
+ virtual bool TestCondition(FStateTreeExecutionContext& Context) const; // default: false
199
+ EStateTreeExpressionOperand Operand = EStateTreeExpressionOperand::And;
200
+ int8 DeltaIndent = 0; // indent level for logical grouping
201
+ EStateTreeConditionEvaluationMode EvaluationMode = EStateTreeConditionEvaluationMode::Evaluated;
202
+ };
203
+ ```
204
+
205
+ **Operands:** `And` (both must be true), `Or` (either), `Copy` (hidden/internal). `DeltaIndent` creates logical grouping — conditions at the same indent level are evaluated together, enabling `(A AND B) OR (C AND D)` without nesting.
206
+
207
+ **Built-in conditions:** `FStateTreeCompareIntCondition`, `FStateTreeCompareFloatCondition`, `FStateTreeCompareEnumCondition`, `FGameplayTagMatchCondition`, `FStateTreeObjectIsValidCondition`, `FStateTreeCompareDistanceCondition`. Bind inputs via property bindings.
208
+
209
+ ---
210
+
211
+ ## Evaluators
212
+
213
+ Evaluators run globally (not per-state) and execute **before** transitions and task ticks each frame. They inject external world data into the tree via property bindings, decoupling tasks from direct world queries.
214
+
215
+ ```cpp
216
+ USTRUCT(meta=(Hidden))
217
+ struct FStateTreeEvaluatorBase : public FStateTreeNodeBase
218
+ {
219
+ virtual void TreeStart(FStateTreeExecutionContext& Context) const;
220
+ virtual void TreeStop(FStateTreeExecutionContext& Context) const;
221
+ virtual void Tick(FStateTreeExecutionContext& Context, float DeltaTime) const;
222
+ // Note: DeltaTime is 0 during preselection
223
+ };
224
+ ```
225
+
226
+ Evaluators use the same `FInstanceDataType` typedef pattern as tasks. Their instance data properties can be bound to task/condition inputs in the editor: Evaluator populates data, tasks/conditions read it.
227
+
228
+ **When to use evaluators vs external data:** Evaluators for data that changes every frame (nearest enemy, world time). External data handles for stable references (owning actor, subsystem).
229
+
230
+ ---
231
+
232
+ ## Transitions
233
+
234
+ Transitions define how and when states change. Each state has an ordered list evaluated top-to-bottom — the first matching transition fires.
235
+
236
+ ### Trigger Types
237
+
238
+ `EStateTreeTransitionTrigger` is a bitmask (`ENUM_CLASS_FLAGS`, supports bitwise OR):
239
+
240
+ | Trigger | Value | Fires When |
241
+ |---------|-------|------------|
242
+ | `OnStateSucceeded` | 1 | Active state returns Succeeded |
243
+ | `OnStateFailed` | 2 | Active state returns Failed |
244
+ | `OnStateCompleted` | 3 | Either Succeeded or Failed (1\|2) |
245
+ | `OnTick` | 4 | Every frame (gate with conditions) |
246
+ | `OnEvent` | 8 | Matching event in the queue |
247
+ | `OnDelegate` | 16 | Bound delegate fires |
248
+
249
+ ### Priorities and Properties
250
+
251
+ `EStateTreeTransitionPriority`: `Low`, `Normal`, `Medium`, `High`, `Critical`. Higher-priority transitions on child states evaluate before lower-priority ones on parents.
252
+
253
+ | Property | Default | Purpose |
254
+ |----------|---------|---------|
255
+ | `bConsumeEventOnSelect` | `true` | Remove event from queue when transition fires |
256
+ | `bTransitionEnabled` | `true` | Disable without removing |
257
+ | `bReactivateTargetState` | `false` | Force Exit+Enter even if target is current state |
258
+
259
+ **Targets:** GotoState (specific named state), NextState (next sibling), Succeeded/Failed (complete parent with that status), or tree-root Succeeded/Failed to complete the entire tree.
260
+
261
+ ---
262
+
263
+ ## State Types and Selection
264
+
265
+ ### State Types
266
+
267
+ | Type | Purpose |
268
+ |------|---------|
269
+ | `State` | Normal state with tasks, conditions, transitions |
270
+ | `Group` | Container for child states — no tasks of its own |
271
+ | `Linked` | References another state within the same tree |
272
+ | `LinkedAsset` | References a state in a different `UStateTree` asset |
273
+ | `Subtree` | Embeds another `UStateTree` as a child |
274
+
275
+ `LinkedAsset` is useful for sharing common behavior patterns (patrol, investigate, flee) across AI archetypes.
276
+
277
+ ### Selection Behavior
278
+
279
+ `EStateTreeStateSelectionBehavior` controls how child states are chosen on entry:
280
+
281
+ | Behavior | Effect |
282
+ |----------|--------|
283
+ | `TryEnterState` | Enter this state directly |
284
+ | `TrySelectChildrenInOrder` | Try children top-to-bottom, first valid wins |
285
+ | `TrySelectChildrenAtRandom` | Random child selection |
286
+ | `TrySelectChildrenWithHighestUtility` | Utility-based selection (highest score) |
287
+ | `TrySelectChildrenAtRandomWeightedByUtility` | Weighted random by utility score |
288
+ | `TryFollowTransitions` | Follow transition chain |
289
+
290
+ `FStateTreeActiveStates::MaxStates = 8` — maximum depth of active state hierarchy. Stay within this limit.
291
+
292
+ ---
293
+
294
+ ## Events
295
+
296
+ State Trees use a GameplayTag-based event system for decoupled communication.
297
+
298
+ `FStateTreeEvent` contains: `FGameplayTag Tag`, `FInstancedStruct Payload` (optional typed data), `FName Origin` (optional sender name for debugging).
299
+
300
+ ```cpp
301
+ // From outside via UStateTreeComponent
302
+ TreeComp->SendStateTreeEvent(FGameplayTag::RequestGameplayTag("AI.Alert"));
303
+
304
+ // With payload
305
+ FMyAlertData AlertData;
306
+ AlertData.ThreatLevel = 5;
307
+ TreeComp->SendStateTreeEvent(
308
+ FGameplayTag::RequestGameplayTag("AI.Alert"),
309
+ FConstStructView::Make(AlertData), TEXT("PerceptionSystem"));
310
+
311
+ // From inside a task via execution context
312
+ Context.SendEvent(Tag, FConstStructView::Make(ResultData), TEXT("MyTask"));
313
+ ```
314
+
315
+ `FStateTreeEventQueue` holds up to `MaxActiveEvents = 64` events per tick. Events are processed during transition evaluation. Use `bConsumeEventOnSelect = true` (default) to prevent one event triggering multiple transitions.
316
+
317
+ ---
318
+
319
+ ## External Data
320
+
321
+ External data provides typed references to objects outside the tree (actors, components, subsystems) without going through evaluators.
322
+
323
+ ```cpp
324
+ // Declare handles in your task/condition/evaluator struct
325
+ TStateTreeExternalDataHandle<FMyActorContext, EStateTreeExternalDataRequirement::Required> ActorHandle;
326
+ TStateTreeExternalDataHandle<FMySubsystemContext, EStateTreeExternalDataRequirement::Optional> SubsystemHandle;
327
+
328
+ // Link in the Link override
329
+ virtual bool Link(FStateTreeLinker& Linker) override
330
+ {
331
+ Linker.LinkExternalData(ActorHandle);
332
+ Linker.LinkExternalData(SubsystemHandle);
333
+ return true;
334
+ }
335
+
336
+ // Access at runtime
337
+ auto& ActorCtx = Context.GetExternalData(ActorHandle); // Required — reference
338
+ auto* SubsystemCtx = Context.GetExternalDataPtr(SubsystemHandle); // Optional — pointer
339
+ ```
340
+
341
+ The schema's `CollectExternalData` populates these handles at tree start, validating at link time rather than runtime.
342
+
343
+ ---
344
+
345
+ ## UStateTreeComponent
346
+
347
+ `UStateTreeComponent` extends `UBrainComponent` and manages the full tree lifecycle on an actor.
348
+
349
+ ```cpp
350
+ void SetStateTree(UStateTree* NewStateTree);
351
+ void SetStateTreeReference(FStateTreeReference NewStateTreeRef);
352
+ void SendStateTreeEvent(const FStateTreeEvent& Event);
353
+ void SendStateTreeEvent(FGameplayTag Tag, FConstStructView Payload, FName Origin);
354
+ EStateTreeRunStatus GetStateTreeRunStatus() const;
355
+ // Delegate — fires when run status changes
356
+ FStateTreeRunStatusChanged OnStateTreeRunStatusChanged; // BlueprintAssignable
357
+ bool bStartLogicAutomatically = true; // EditAnywhere
358
+ ```
359
+
360
+ ### FStateTreeReference
361
+
362
+ `FStateTreeReference` wraps a `UStateTree*` with parameter overrides:
363
+ ```cpp
364
+ FStateTreeReference TreeRef;
365
+ TreeRef.SetStateTree(MyStateTreeAsset);
366
+ TreeRef.SyncParameters();
367
+ TreeRef.GetParameters().SetValueFloat(TEXT("AggroRange"), 1500.f);
368
+ ```
369
+
370
+ `FStateTreeReferenceOverrides` swaps tree references at runtime by tag:
371
+ ```cpp
372
+ Overrides.AddOverride(Tag_CombatVariant, CombatTreeRef);
373
+ Overrides.RemoveOverride(Tag_CombatVariant);
374
+ ```
375
+
376
+ Subclass `UStateTreeComponent` to customize context via `SetContextRequirements(FStateTreeExecutionContext&, bool bLogErrors)` and `CollectExternalData(...)`.
377
+
378
+ ---
379
+
380
+ ## AI Integration
381
+
382
+ `UStateTreeAIComponentSchema` adds `AIControllerClass` to the component schema, making the AI controller available as context data for property bindings.
383
+
384
+ ```cpp
385
+ AMyAIController::AMyAIController()
386
+ {
387
+ StateTreeComp = CreateDefaultSubobject<UStateTreeComponent>(TEXT("StateTree"));
388
+ StateTreeComp->bStartLogicAutomatically = true;
389
+ }
390
+ ```
391
+
392
+ Assign the `UStateTree` asset in the controller defaults. Set the schema's `ContextActorClass` to your Pawn class so the editor can bind to its components.
393
+
394
+ ### State Tree vs Behavior Tree
395
+
396
+ | Aspect | State Tree | Behavior Tree |
397
+ |--------|-----------|---------------|
398
+ | Structure | Hierarchical FSM with transitions | Tree of composites, decorators, tasks |
399
+ | Data flow | Evaluators + property bindings (typed) | Blackboard (string-keyed, loosely typed) |
400
+ | Conditions | First-class on transitions | Decorators on tree nodes |
401
+ | Mass Entity | Native via `UMassStateTreeSchema` | No Mass support |
402
+ | Best for | Data-driven FSMs, Mass entities, flat logic | Deep decision hierarchies, complex aborts |
403
+
404
+ Prefer State Trees for new AI needing Mass Entity scaling or data-driven transitions. Keep Behavior Trees for deeply nested decision logic with complex abort/decorator patterns.
405
+
406
+ ---
407
+
408
+ ## Mass Entity Integration
409
+
410
+ State Trees integrate natively with Mass Entity for processing thousands of entities. See `references/state-tree-mass-integration.md` for complete setup.
411
+
412
+ Key concepts:
413
+ - `UMassStateTreeSchema` constrains trees to Mass-compatible node types (`FMassStateTreeTaskBase`, etc.)
414
+ - `UMassStateTreeSubsystem` manages pooled instance data (`AllocateInstanceData`/`FreeInstanceData`)
415
+ - `UMassStateTreeProcessor` evaluates trees per entity each frame
416
+ - `FMassStateTreeExecutionContext` wraps execution context with `SetEntity`/`GetEntity`
417
+ - Mass-specific tasks override `GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder&)` to declare fragment read/write requirements
418
+
419
+ For Mass Entity architecture details, see `/ue-mass-entity`.
420
+
421
+ ---
422
+
423
+ ## Common Mistakes
424
+
425
+ **Persisting FStateTreeExecutionContext across frames:**
426
+ ```cpp
427
+ // WRONG — context is per-tick, NOT persistent
428
+ FStateTreeExecutionContext* SavedContext; // dangling after tick
429
+
430
+ // RIGHT — reconstruct each tick from persistent instance data
431
+ FStateTreeExecutionContext Context(Owner, *StateTree, InstanceData);
432
+ Context.Tick(DeltaTime);
433
+ ```
434
+
435
+ **Mutating task struct directly instead of using instance data:**
436
+ ```cpp
437
+ // WRONG — task structs are const at runtime
438
+ virtual EStateTreeRunStatus Tick(...) const override {
439
+ Timer += DeltaTime; // compile error — 'this' is const
440
+ }
441
+
442
+ // RIGHT — use FInstanceDataType typedef
443
+ typedef FMyInstanceData FInstanceDataType;
444
+ virtual EStateTreeRunStatus Tick(...) const override {
445
+ auto& Data = Context.GetInstanceData(*this);
446
+ Data.Timer += DeltaTime;
447
+ }
448
+ ```
449
+
450
+ **Conditions with side effects:** `TestCondition` may be called multiple times per frame during transition evaluation. Never modify state in conditions — they must be pure functions.
451
+
452
+ **Evaluators doing heavy work every tick:** Evaluators run every frame before transitions. Cache results in instance data and only refresh when inputs change.
453
+
454
+ **Exceeding MaxStates depth:** `FStateTreeActiveStates::MaxStates = 8`. Deeply nested hierarchies silently fail. Flatten with linked states or subtrees.
455
+
456
+ **Forgetting to link external data:** Unlinked Required handles assert at runtime; Optional handles silently return nullptr. Always link all declared handles in `Link()`.
457
+
458
+ **Not consuming events:** With `bConsumeEventOnSelect = false`, the same event can trigger multiple transitions in one frame. Leave default `true` unless broadcast behavior is intended.
459
+
460
+ ---
461
+
462
+ ## Related Skills
463
+
464
+ - `/ue-ai-navigation` — Behavior tree patterns, AI controller setup, perception system
465
+ - `/ue-mass-entity` — Mass Entity architecture, processors, fragments, traits
466
+ - `/ue-gameplay-abilities` — Ability-driven state transitions, GAS integration
467
+ - `/ue-gameplay-framework` — Game state machines, controller/pawn lifecycle
468
+ - `/ue-actor-component-architecture` — Component setup for `UStateTreeComponent`
469
+ - `/ue-cpp-foundations` — USTRUCT patterns, delegates, subsystem access
470
+
471
+ ---
472
+
473
+ ## Checklist
474
+
475
+ Validate before considering the work done:
476
+
477
+ - [ ] Tasks are single-purpose and reusable across states
478
+ - [ ] Transitions are driven by conditions and events, not by side effects in tasks
479
+ - [ ] The schema chosen matches the owner type of the tree
480
+ - [ ] Conventions in `docs/unreal/project-context.md` were read and followed
481
+ - [ ] The Common Mistakes section of this skill was reviewed against the change
482
+
483
+ **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.
484
+
485
+ ## Next Steps
486
+
487
+ - `/ue-mass-entity` — evaluate Mass if the same behavior runs at scale
488
+ - `/code-review` — architectural and quality review of the change
489
+ - `/commit` — conventional commit once the change is verified
@@ -0,0 +1,184 @@
1
+ # State Tree Mass Entity Integration
2
+
3
+ How State Trees integrate with Mass Entity for processing thousands of entities efficiently. For core Mass Entity architecture, see `/ue-mass-entity`.
4
+
5
+ **Build.cs modules**: `StateTreeModule`, `GameplayStateTreeModule`, `MassEntity`, `MassAIBehavior`
6
+
7
+ ---
8
+
9
+ ## UMassStateTreeSchema
10
+
11
+ `UMassStateTreeSchema` constrains a `UStateTree` asset to only allow Mass-compatible node types:
12
+ - `FMassStateTreeTaskBase` (not `FStateTreeTaskBase`)
13
+ - `FMassStateTreeConditionBase` (not `FStateTreeConditionBase`)
14
+ - `FMassStateTreeEvaluatorBase` (not `FStateTreeEvaluatorBase`)
15
+
16
+ Select this schema when creating a `UStateTree` intended for Mass Entity processing. Regular State Tree nodes will not appear in the editor dropdown.
17
+
18
+ ---
19
+
20
+ ## Mass-Specific Node Base Classes
21
+
22
+ ### FMassStateTreeTaskBase
23
+
24
+ Extends `FStateTreeTaskBase` with Mass fragment dependency declarations:
25
+
26
+ ```cpp
27
+ USTRUCT(meta=(DisplayName="My Mass Task"))
28
+ struct FMyMassTask : public FMassStateTreeTaskBase
29
+ {
30
+ GENERATED_BODY()
31
+ typedef FMyMassTaskInstanceData FInstanceDataType;
32
+
33
+ // Declare which fragments this task reads/writes
34
+ // The processor uses these to build its execution requirements
35
+ virtual void GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder& Builder) const override
36
+ {
37
+ Builder.AddReadWrite<FTransformFragment>();
38
+ Builder.AddReadOnly<FMassVelocityFragment>();
39
+ }
40
+
41
+ virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context,
42
+ const FStateTreeTransitionResult& Transition) const override
43
+ {
44
+ // Access entity via FMassStateTreeExecutionContext
45
+ const FMassStateTreeExecutionContext& MassContext =
46
+ static_cast<const FMassStateTreeExecutionContext&>(Context);
47
+ FMassEntityHandle Entity = MassContext.GetEntity();
48
+ // Use entity with Mass subsystem APIs...
49
+ return EStateTreeRunStatus::Running;
50
+ }
51
+ };
52
+ ```
53
+
54
+ ### FMassStateTreeConditionBase
55
+
56
+ Same pattern — extends `FStateTreeConditionBase`, adds `GetDependencies()`:
57
+
58
+ ```cpp
59
+ USTRUCT(meta=(DisplayName="My Mass Condition"))
60
+ struct FMyMassCondition : public FMassStateTreeConditionBase
61
+ {
62
+ GENERATED_BODY()
63
+
64
+ virtual void GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder& Builder) const override
65
+ {
66
+ Builder.AddReadOnly<FMassHealthFragment>();
67
+ }
68
+
69
+ virtual bool TestCondition(FStateTreeExecutionContext& Context) const override
70
+ {
71
+ const auto& MassCtx = static_cast<const FMassStateTreeExecutionContext&>(Context);
72
+ // Check fragment data on the entity...
73
+ return true;
74
+ }
75
+ };
76
+ ```
77
+
78
+ ### FMassStateTreeEvaluatorBase
79
+
80
+ Extends `FStateTreeEvaluatorBase` with the same `GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder& Builder) const` override for fragment access.
81
+
82
+ ---
83
+
84
+ ## Entity Configuration
85
+
86
+ ### UMassStateTreeTrait
87
+
88
+ Add `UMassStateTreeTrait` to a `UMassEntityConfigAsset` to assign a State Tree to entities of that archetype:
89
+
90
+ ```cpp
91
+ // In Mass Entity Config asset (data-driven):
92
+ // Add StateTree Trait → assign UStateTree asset with UMassStateTreeSchema
93
+ ```
94
+
95
+ The trait adds required fragments to the archetype:
96
+ - `FMassStateTreeInstanceFragment` — per-entity instance data handle
97
+ - `FMassStateTreeSharedFragment` — shared tree reference (one per archetype)
98
+
99
+ ### Fragments
100
+
101
+ | Fragment | Scope | Contains |
102
+ |----------|-------|----------|
103
+ | `FMassStateTreeInstanceFragment` | Per-entity | Handle to pooled `FStateTreeInstanceData` |
104
+ | `FMassStateTreeSharedFragment` | Per-archetype (shared) | `FStateTreeReference` to the `UStateTree` asset |
105
+
106
+ ---
107
+
108
+ ## UMassStateTreeSubsystem
109
+
110
+ Manages pooled State Tree instance data for Mass entities. Pooling avoids per-entity allocation overhead.
111
+
112
+ ```cpp
113
+ // Allocate instance data for an entity
114
+ FMassStateTreeInstanceHandle Handle =
115
+ MassStateTreeSubsystem->AllocateInstanceData(StateTree);
116
+
117
+ // Access instance data for execution
118
+ FStateTreeInstanceData* Data = MassStateTreeSubsystem->GetInstanceData(Handle);
119
+
120
+ // Free when entity is destroyed
121
+ MassStateTreeSubsystem->FreeInstanceData(Handle);
122
+ ```
123
+
124
+ The subsystem handles allocation/deallocation automatically through the trait lifecycle. Manual calls are only needed for custom processors.
125
+
126
+ ---
127
+
128
+ ## FMassStateTreeExecutionContext
129
+
130
+ Wraps `FStateTreeExecutionContext` with entity access:
131
+
132
+ ```cpp
133
+ // 4-param constructor (UE 5.5+): Owner, StateTree, InstanceData, MassExecutionContext
134
+ FMassStateTreeExecutionContext MassContext(
135
+ Owner, *StateTree, InstanceData, MassExecContext);
136
+
137
+ MassContext.SetEntity(EntityHandle); // set current entity before Tick
138
+ FMassEntityHandle Entity = MassContext.GetEntity(); // access in tasks
139
+ ```
140
+
141
+ `MassExecContext` is the `FMassExecutionContext&` available inside a Mass processor's `Execute()` method. The old 6-param form `(Owner, *StateTree, InstanceData, EntityManager, SignalSubsystem, MassExecContext)` is deprecated since UE 5.6.
142
+
143
+ The processor calls `SetEntity()` before ticking each entity's tree, making the entity handle available to all tasks and conditions via the context.
144
+
145
+ ---
146
+
147
+ ## UMassStateTreeProcessor
148
+
149
+ Evaluates State Trees for all entities with `FMassStateTreeInstanceFragment`. Created dynamically — one processor per unique set of fragment requirements (hashed from all tasks' `GetDependencies()`).
150
+
151
+ The processor:
152
+ 1. Queries entities with matching fragments
153
+ 2. For each entity: constructs `FMassStateTreeExecutionContext`, calls `SetEntity()`, ticks the tree
154
+ 3. Handles transition signals and state changes
155
+
156
+ Fragment requirements declared in `GetDependencies()` from all tasks in the tree are merged into the processor's query, so a tree with tasks reading `FTransformFragment` and `FMassVelocityFragment` will produce a processor that requires both.
157
+
158
+ ---
159
+
160
+ ## Mass Signals
161
+
162
+ Mass signals coordinate State Tree execution with other Mass processors:
163
+
164
+ | Signal | Purpose |
165
+ |--------|---------|
166
+ | `StateTreeActivate` | Activates a dormant State Tree on an entity |
167
+ | `NewStateTreeTaskRequired` | Signals that the current task needs re-evaluation |
168
+ | `DelayedTransitionWakeup` | Wakes an entity for a delayed transition check |
169
+
170
+ Send signals via `UMassSignalSubsystem`:
171
+ ```cpp
172
+ SignalSubsystem.SignalEntity(Entity, UE::Mass::Signals::StateTreeActivate);
173
+ ```
174
+
175
+ ---
176
+
177
+ ## Performance Notes
178
+
179
+ - **Keep tasks minimal:** Each entity ticks its tree every frame. Expensive operations (pathfinding, overlap queries) should be throttled with intervals or event-driven rather than per-tick.
180
+ - **Fragment access matters:** `GetDependencies()` determines processor parallelism. Minimize `ReadWrite` fragments; prefer `ReadOnly` to allow concurrent execution with other processors.
181
+ - **Pool instance data:** Always use `UMassStateTreeSubsystem` for allocation. Direct `FStateTreeInstanceData` construction per entity defeats the pooling optimization.
182
+ - **Shallow trees:** `FStateTreeActiveStates::MaxStates = 8` is the depth limit. Mass trees should be especially shallow (2-3 levels) since depth adds per-entity overhead.
183
+ - **Profile early:** Use `stat MassEntity` and Unreal Insights to identify expensive State Tree tasks. A single heavy task across 10,000 entities multiplies its cost dramatically.
184
+ - **Batch signals:** Prefer `SignalEntities()` (plural) over individual `SignalEntity()` calls when signaling multiple entities to reduce subsystem overhead.