Debugging Code
JetBrains/skills
A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…
A skill your agent uses when writing or debugging State Tree logic in Unreal Engine C++ — tasks, conditions, evaluators, considerations, schemas, transitions, events or Mass behaviours.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-state-trees --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .claude/skills && cp -r skills-src/skills/ue-state-trees .claude/skills/ue-state-trees && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "ue-state-trees" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-state-trees into .claude/skills/ue-state-trees/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-state-trees", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-state-treesType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-state-trees --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .agents/skills && cp -r skills-src/skills/ue-state-trees .agents/skills/ue-state-trees && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "ue-state-trees" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-state-trees into .agents/skills/ue-state-trees/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-state-trees", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-state-trees --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/skills/ue-state-trees .cursor/skills/ue-state-trees && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "ue-state-trees" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-state-trees into .cursor/skills/ue-state-trees/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-state-trees", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/quodsoler/unreal-engine-skills.git --path skills/ue-state-trees--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-state-trees --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/skills/ue-state-trees .gemini/skills/ue-state-trees && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "ue-state-trees" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-state-trees into .gemini/skills/ue-state-trees/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-state-trees", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install quodsoler/unreal-engine-skills ue-state-treesInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .github/skills && cp -r skills-src/skills/ue-state-trees .github/skills/ue-state-trees && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "ue-state-trees" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-state-trees into .github/skills/ue-state-trees/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-state-trees", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install quodsoler/unreal-engine-skills ue-state-trees --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/quodsoler/unreal-engine-skills.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/skills/ue-state-trees .opencode/skills/ue-state-trees && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "ue-state-trees" agent skill from https://github.com/quodsoler/unreal-engine-skills/tree/main/skills/ue-state-trees into .opencode/skills/ue-state-trees/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "ue-state-trees", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
ue-state-treesA skill your agent uses when writing or debugging State Tree logic in Unreal Engine C++ — tasks, conditions, evaluators, considerations, schemas, transitions, events or Mass behaviours.
Ue State Trees is an agent skill from quodsoler/unreal-engine-skills. Use when writing or debugging State Tree logic in Unreal Engine C++ — tasks, conditions, evaluators, considerations, schemas, transitions, events or Mass behaviours. Also use when the user mentions 'StateTree', 'state tree', 'FStateTreeTaskBase', 'FStateTreeExecutionContext', 'GetInstanceDataType', 'FInstanceDataType', 'UStateTreeComponent', 'UStateTreeAIComponent', 'FStateTreeReference', 'SendStateTreeEvent', 'EStateTreeRunStatus', 'StateTree schema', 'utility selection', 'scheduled tick', 'FinishTask', or 'Mass…
Its SKILL.md is about 7.4k tokens, which your agent loads only when the skill is triggered. The skill folder holds 3 other files, including reference files (for example `references/state-tree-mass-integration.md` and `references/state-tree-patterns.md`).
It sits in Game Development. It works with C++ and Unreal Engine. The repository describes itself as: Unreal Engine C++ skills for AI coding agents. 27 skills covering gameplay, rendering, networking, animation, and more. Works with Claude Code, Cursor, Windsurf, and any agent… The licence is MIT.
Read from SKILL.md and the folder at commit f3742d7. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are cpp).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Ue State Trees loads about 7.4k tokens when it runs, and up to ~17k if it reads all its reference files. Until then it costs about 179 tokens; SKILL.md has 2,081 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from quodsoler/unreal-engine-skills at commit f3742d7, republished under its MIT licence (© quodsoler). 2,081 words, ~7,362 tokens.
.claude/skills/ue-state-trees/SKILL.md (or your agent's skills folder). This skill also uses 2 other files; get the full folder from GitHub.Target engine: UE 5.8. APIs below are verified against the 5.8 headers; older forms are listed under "Deprecated — do not use".
State Tree is a data-driven hierarchical state machine authored as a UStateTree data asset and executed from C++ through an execution context. Runtime types live in the StateTreeModule (plugin StateTree); actor-facing components and schemas live in GameplayStateTreeModule (plugin GameplayStateTree). Mass-entity behaviours add MassAIBehavior (plugin MassAI, Experimental in 5.8) plus MassEntity, MassCore and MassSignals. Add the modules you use to PublicDependencyModuleNames in your .Build.cs.
Read .agents/ue-project-context.md if it exists (module names, conventions, enabled plugins, GAS/networking setup). Do not stop if it is missing.
Identify the area from the request and the codebase. Ask only when two plausible readings would produce different code.
| Request is about… | Go to |
|---|---|
| What the runtime looks like, instance data, contexts | Architecture, Execution Contexts |
| Writing a task | Tasks |
| Writing a condition or gating a transition | Conditions |
| Utility scoring, "pick the best child state" | Considerations |
| Feeding world data into the tree | Evaluators, External Data |
| When and how states change | Transitions, State Types and Selection |
| Tag-driven signals into the tree | Events |
| Reacting to a C++ callback instead of polling | Delegates |
| Restricting which nodes an asset may use | Schemas |
| Running a tree on an actor or AI controller | Component and AI Setup |
| Reducing tick cost / sleeping trees | Scheduled Tick |
| Thousands of entities | Mass Entity Integration |
| Finishing work from a callback or another thread | Async Completion |
UStateTree (UDataAsset) IsReadyToRun() must be true before execution
├── UStateTreeSchema which nodes and context data are allowed
├── States hierarchy of States/Groups/Linked/Subtree
│ ├── Tasks work performed while the state is active
│ ├── EnterConditions gate on selecting the state
│ ├── Considerations utility score used by selection behaviours
│ └── Transitions rules for leaving the state
├── Evaluators global data providers, tick before transitions
└── Parameters FInstancedPropertyBag global parametersNodes are USTRUCTs, not UObjects, and every node virtual is const. Mutable per-instance state lives in a separate instance-data struct owned by FStateTreeInstanceData, which is what persists across frames. The execution context is a short-lived view constructed over that instance data.
| Type | Role |
|---|---|
UStateTree | The compiled asset. IsReadyToRun() reports link success |
FStateTreeInstanceData | Persistent runtime storage — hold this, not the context |
FStateTreeExecutionContext | Full read/write context; construct per tick |
FStateTreeReference | UStateTree* plus overridden global parameters |
EStateTreeRunStatus | Running, Stopped, Succeeded, Failed, Unset |
// MyTreeRunner.h — persistent storage on the owner
UPROPERTY(Transient)
FStateTreeInstanceData InstanceData;
// .cpp — one context per tick over the same instance data
FStateTreeExecutionContext Context(*this, *StateTreeAsset, InstanceData);
Context.SetCollectExternalDataCallback(
FOnCollectStateTreeExternalData::CreateUObject(this, &UMyTreeRunner::CollectExternalData));
FStateTreeExecutionContext::FStartParameters StartParams;
StartParams.RandomSeed = 1234;
Context.Start(StartParams);
// later frames
Context.Tick(DeltaTime);Tick can be split when transitions must be evaluated after other systems have run: call TickUpdateTasks(DeltaTime) first and TickTriggerTransitions() afterwards.
5.8 splits the context by capability. Pick the narrowest one that compiles.
| Context | Gets you | Typical use |
|---|---|---|
FStateTreeReadOnlyExecutionContext | GetOwner, GetWorld, GetStateTree, HasEventToProcess, IsValid | GetDebugInfo overrides, gameplay debugger |
FStateTreeMinimalExecutionContext | adds SendEvent, ScheduleNextTick, scheduled-tick requests | sending an event from outside the tick |
FStateTreeExecutionContext | adds Start/Stop/Tick, instance data, external data, FinishTask, BindDelegate | everything inside a node |
FStateTreeWeakExecutionContext | weak handles captured for later | lambdas, latent actions, timers |
FStateTreeStrongExecutionContext | resolved access from a weak context | inside the callback, via MakeStrongExecutionContext() |
FStateTreeMinimalExecutionContext derives from FStateTreeReadOnlyExecutionContext, and FStateTreeExecutionContext from FStateTreeMinimalExecutionContext, so a node method taking the full context can call anything above it.
Capture FStateTreeWeakExecutionContext (constructed from the live context) and finish the task when the async work returns. See state-tree-patterns.md for the full latent-task template.
const FStateTreeWeakExecutionContext WeakContext = Context.MakeWeakExecutionContext();
OnRequestFinished.AddLambda([WeakContext]()
{
WeakContext.FinishTask(EStateTreeFinishTaskType::Succeeded);
});Inside a tick, a task finishes itself with Context.FinishTask(*this, EStateTreeFinishTaskType::Succeeded) or by returning a completion status from Tick.
A schema declares which node structs, which classes and which context data an asset may use. IsStructAllowed is what makes your nodes appear in the editor, so derive custom nodes from the *CommonBase structs the stock schemas accept: FStateTreeTaskCommonBase, FStateTreeConditionCommonBase, FStateTreeEvaluatorCommonBase, FStateTreeConsiderationCommonBase, FStateTreePropertyFunctionCommonBase.
| Schema | Context data it publishes |
|---|---|
UStateTreeComponentSchema | Actor (class from ContextActorClass) |
UStateTreeAIComponentSchema | Actor (defaults to APawn) plus AIController |
UMassStateTreeSchema | Mass entity data, via FMassStateTreeExecutionContext |
// MyGameStateTreeSchema.h
#pragma once
#include "StateTreeSchema.h"
#include "StateTreeExecutionTypes.h"
#include "MyGameStateTreeSchema.generated.h"
UCLASS(BlueprintType, EditInlineNew, CollapseCategories, meta = (DisplayName = "My Game Schema"))
class MYGAME_API UMyGameStateTreeSchema : public UStateTreeSchema
{
GENERATED_BODY()
protected:
virtual bool IsStructAllowed(const UScriptStruct* InScriptStruct) const override;
virtual bool IsClassAllowed(const UClass* InScriptStruct) const override;
virtual bool IsExternalItemAllowed(const UStruct& InStruct) const override;
virtual TConstArrayView<FStateTreeExternalDataDesc> GetContextDataDescs() const override;
#if WITH_EDITOR
virtual bool AllowEvaluators() const override { return true; }
virtual bool AllowMultipleTasks() const override { return true; }
virtual bool AllowGlobalParameters() const override { return true; }
virtual bool AllowUtilityConsiderations() const override { return true; }
#endif
UPROPERTY()
TArray<FStateTreeExternalDataDesc> ContextDataDescs;
};AllowEnterConditions, AllowUtilityConsiderations, AllowEvaluators, AllowMultipleTasks, AllowGlobalParameters, AllowTasksCompletion and AllowQueuedCompilation are declared inside #if WITH_EDITOR (StateTreeSchema.h:96-138) — they only drive the editor/compiler, so your overrides must be guarded the same way or game builds fail with "does not override". IsStructAllowed, IsClassAllowed, IsExternalItemAllowed, IsScheduledTickAllowed, IsStateSelectionAllowed, IsStateTypeAllowed and GetContextDataDescs are runtime virtuals (StateTreeSchema.h:36-79).
Every task overrides the virtuals it needs and GetInstanceDataType(). The using FInstanceDataType = …; alias alone allocates nothing; FStateTreeNodeBase::GetInstanceDataType() returns nullptr by default (StateTreeNodeBase.h:94) and the compiler reserves no storage, so Context.GetInstanceData(*this) then hits check(Memory != nullptr) (PropertyBindingDataView.h:116).
| Virtual (verbatim signature) | Returns |
|---|---|
EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const | EStateTreeRunStatus |
ExitState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const | void |
StateCompleted(FStateTreeExecutionContext& Context, const EStateTreeRunStatus CompletionStatus, const FStateTreeActiveStates& CompletedActiveStates) const | void |
Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const | EStateTreeRunStatus |
TriggerTransitions(FStateTreeExecutionContext& Context) const | void |
GetDebugInfo(const FStateTreeReadOnlyExecutionContext& Context) const | FString |
// MyTimedTask.h
#pragma once
#include "StateTreeTaskBase.h"
#include "StateTreeExecutionContext.h"
#include "MyTimedTask.generated.h"
USTRUCT()
struct FMyTimedTaskInstanceData
{
GENERATED_BODY()
UPROPERTY(EditAnywhere, Category = "Parameter")
float Duration = 2.0f;
UPROPERTY()
float ElapsedTime = 0.f;
};
USTRUCT(meta = (DisplayName = "My Timed Task"))
struct FMyTimedTask : public FStateTreeTaskCommonBase
{
GENERATED_BODY()
using FInstanceDataType = FMyTimedTaskInstanceData;
virtual const UStruct* GetInstanceDataType() const override { return FInstanceDataType::StaticStruct(); }
virtual EStateTreeRunStatus EnterState(FStateTreeExecutionContext& Context,
const FStateTreeTransitionResult& Transition) const override
{
FInstanceDataType& Data = Context.GetInstanceData(*this);
Data.ElapsedTime = 0.f;
return EStateTreeRunStatus::Running;
}
virtual EStateTreeRunStatus Tick(FStateTreeExecutionContext& Context,
const float DeltaTime) const override
{
FInstanceDataType& Data = Context.GetInstanceData(*this);
Data.ElapsedTime += DeltaTime;
return Data.ElapsedTime >= Data.Duration
? EStateTreeRunStatus::Succeeded
: EStateTreeRunStatus::Running;
}
};Editable parameters usually live on the instance data so they can be bound in the editor; properties placed on the node struct itself are shared by every instance and cannot be bound.
Set these in the task constructor.
| Flag | Default | Effect |
|---|---|---|
bShouldStateChangeOnReselect | true | Re-run Exit/Enter when the same state is selected again |
bShouldCallTick | true | Call Tick(); false also disables property copying |
bShouldCallTickOnlyOnEvents | false | Tick only on frames with events (needs bShouldCallTick false) |
bShouldCopyBoundPropertiesOnTick | true | Refresh bound properties before Tick() |
bShouldCopyBoundPropertiesOnExitState | true | Refresh bound properties before ExitState() |
bShouldAffectTransitions | false | Call TriggerTransitions() during transition handling |
bConsideredForScheduling | true | Include this task when computing the scheduled tick rate |
bTaskEnabled | true | Node not disabled in the asset |
TransitionHandlingPriority (EStateTreeTransitionPriority) orders TriggerTransitions across tasks of one state.
FStateTreeConditionBase::TestCondition(FStateTreeExecutionContext& Context) const returns bool and defaults to false. It must be pure: the selection pass may call it several times per frame.
| Member | Purpose |
|---|---|
EStateTreeExpressionOperand Operand | Copy, And, Or, Multiply (Multiply is considerations only) |
int8 DeltaIndent | Parenthesis level, gives (A AND B) OR (C AND D) without nesting |
EStateTreeConditionEvaluationMode EvaluationMode | Evaluated, ForcedTrue, ForcedFalse |
Conditions also receive EnterState, ExitState and StateCompleted (all no-ops by default) so they can cache work across the state's lifetime.
Stock conditions: FStateTreeCompareIntCondition, FStateTreeCompareFloatCondition, FStateTreeCompareBoolCondition, FStateTreeCompareEnumCondition, FStateTreeCompareNameCondition, FStateTreeCompareDistanceCondition, FStateTreeRandomCondition (Conditions/StateTreeCommonConditions.h), FStateTreeObjectIsValidCondition (Conditions/StateTreeObjectConditions.h) and the gameplay-tag family in Conditions/StateTreeGameplayTagConditions.h. The comparison ones take UE::StateTree::EComparisonOperator.
Considerations score a state so a parent can choose between children. The API is marked experimental in the header, so keep custom considerations small.
USTRUCT(meta = (DisplayName = "My Threat Score"))
struct FMyThreatConsideration : public FStateTreeConsiderationCommonBase
{
GENERATED_BODY()
using FInstanceDataType = FMyThreatConsiderationInstanceData;
virtual const UStruct* GetInstanceDataType() const override { return FInstanceDataType::StaticStruct(); }
protected:
virtual float GetScore(FStateTreeExecutionContext& Context) const override
{
const FInstanceDataType& Data = Context.GetInstanceData(*this);
return FMath::Clamp(Data.ThreatLevel / 100.f, 0.f, 1.f);
}
};GetScore is protected; the framework calls the public GetNormalizedScore. Operand and DeltaIndent combine sibling considerations (And = min, Or = max, Multiply = product). Scores only matter for the two utility selection behaviours, and the schema must return true from AllowUtilityConsiderations().
Evaluators are global (not per-state) and tick before transitions and task ticks. Use them for data many nodes read; use external data for stable references.
virtual void TreeStart(FStateTreeExecutionContext& Context) const;
virtual void TreeStop(FStateTreeExecutionContext& Context) const;
virtual void Tick(FStateTreeExecutionContext& Context, const float DeltaTime) const;
virtual FString GetDebugInfo(const FStateTreeReadOnlyExecutionContext& Context) const;DeltaTime is 0 when the evaluator is ticked during state pre-selection. Evaluators need GetInstanceDataType() exactly like tasks — the full template is in state-tree-patterns.md.
EStateTreeTransitionTrigger is a bitmask (ENUM_CLASS_FLAGS).
| Trigger | Value | Fires when |
|---|---|---|
OnStateSucceeded | 0x1 | The state completed with Succeeded |
OnStateFailed | 0x2 | The state completed with Failed |
OnStateCompleted | 0x1|0x2 | Either of the above |
OnTick | 0x4 | Every tick — always gate with conditions |
OnEvent | 0x8 | A queued event matches the tag |
OnDelegate | 0x10 | A bound delegate was broadcast |
EStateTreeTransitionPriority: Low, Normal, Medium, High, Critical. The first triggered transition of the highest priority wins. Transition types (EStateTreeTransitionType): None, Succeeded, Failed, GotoState, Parent, NextState, NextSelectableState, NextParent, NextSelectableParent (StateTreeTypes.h:76). Per-transition flags bTransitionEnabled and bConsumeEventOnSelect both default to true.
From C++, request a transition with Context.RequestTransition(TargetState, Priority, Fallback) where Fallback is an EStateTreeSelectionFallback.
Delegates replace polling when an external system can tell the tree exactly when to react. One node publishes an FStateTreeDelegateDispatcher on its instance data, another publishes an FStateTreeDelegateListener, and the editor connects the two.
// On the listening node's instance data
UPROPERTY(EditAnywhere, Category = "Input")
FStateTreeDelegateListener ArrivedListener;
// EnterState — bind
Context.BindDelegate(Data.ArrivedListener, FSimpleDelegate::CreateLambda([]()
{
UE_LOG(LogMyGame, Verbose, TEXT("Arrived"));
}));
// ExitState — always unbind
Context.UnbindDelegate(Data.ArrivedListener);
// On the dispatching node
Context.BroadcastDelegate(Data.ArrivedDispatcher);A transition with the OnDelegate trigger fires when the bound dispatcher is broadcast, evaluated with the rest of the transitions.
EStateTreeStateType: State, Group, Linked, LinkedAsset, Subtree. LinkedAsset states are the sharing mechanism — override them per instance with FStateTreeReferenceOverrides.
EStateTreeStateSelectionBehavior:
| Behaviour | Effect |
|---|---|
None | State cannot be selected directly |
TryEnterState | Enter this state even if it has children |
TrySelectChildrenInOrder | First child whose enter conditions pass |
TrySelectChildrenAtRandom | Shuffle children, take the first that passes |
TrySelectChildrenWithHighestUtility | Highest consideration score, ties broken in order |
TrySelectChildrenAtRandomWeightedByUtility | Random weighted by normalised score |
TryFollowTransitions | Evaluate the state's transitions instead of entering |
FStateTreeActiveStates::MaxStates = 8 caps the depth of the active state path. Flatten deeper designs with subtrees or linked assets.
Events are gameplay-tag messages with an optional payload: FStateTreeEvent { FGameplayTag Tag; FInstancedStruct Payload; FName Origin; }.
// From outside the tree
StateTreeComp->SendStateTreeEvent(MyTag_AiAlert, FConstStructView::Make(AlertData), TEXT("Perception"));
// From inside a node (available on the minimal context and above)
Context.SendEvent(MyTag_AiAlert, FConstStructView::Make(ResultData), TEXT("MyTask"));FStateTreeEventQueue::MaxActiveEvents = 64 per instance. Iterate with Context.ForEachEvent(Lambda), whose lambda returns EStateTreeLoopEvents (Next, Break, Consume — StateTreeEvents.h:35) and remove one with Context.ConsumeEvent(SharedEvent) (returns void). Context.HasEventToProcess(Tag) is a cheap existence check. For where gameplay tags are declared, see ue-gameplay-tags-messaging.
External data gives a node a typed reference to an object or struct supplied by the schema's owner — subsystems, the owning actor, components.
TStateTreeExternalDataHandle<UMyWorldSubsystem> SubsystemHandle;
TStateTreeExternalDataHandle<AActor, EStateTreeExternalDataRequirement::Optional> ActorHandle;
virtual bool Link(FStateTreeLinker& Linker) override
{
Linker.LinkExternalData(SubsystemHandle);
Linker.LinkExternalData(ActorHandle);
return true;
}
// Required handles return a reference, Optional handles a pointer
UMyWorldSubsystem& Subsystem = Context.GetExternalData(SubsystemHandle);
AActor* Actor = Context.GetExternalDataPtr(ActorHandle);Link returns bool ([[nodiscard]] on the base, StateTreeNodeBase.h:116); return true on success, false fails linking.
UStateTreeComponentSchema::IsExternalItemAllowed accepts AActor, UActorComponent and UWorldSubsystem subclasses only. The owning actor is published separately as context data named Actor (and AIController for the AI schema); the idiomatic way to reach it is an instance-data property the editor binds automatically:
UPROPERTY(EditAnywhere, Category = "Context")
TObjectPtr<AActor> Actor = nullptr;There is no FStateTreeActorContext type in the engine — use the above.
UStateTreeComponent : UBrainComponent, IGameplayTaskOwnerInterface, IStateTreeSchemaProvider runs one tree on an actor. UStateTreeAIComponent derives from it and returns UStateTreeAIComponentSchema, which guarantees an AAIController context value — use it on AI controllers.
// MyAIController.h — inside the AMyAIController class body
UPROPERTY(VisibleAnywhere, Category = "AI")
TObjectPtr<UStateTreeAIComponent> StateTreeComp;
// MyAIController.cpp
AMyAIController::AMyAIController()
{
StateTreeComp = CreateDefaultSubobject<UStateTreeAIComponent>(TEXT("StateTree"));
StateTreeComp->SetStartLogicAutomatically(true);
}bStartLogicAutomatically is protected; write it through SetStartLogicAutomatically(const bool). Public surface: SetStateTree, SetStateTreeReference, AddLinkedStateTreeOverrides(FGameplayTag, FStateTreeReference), RemoveLinkedStateTreeOverrides(FGameplayTag), SendStateTreeEvent, GetStateTreeRunStatus, and the BlueprintAssignable OnStateTreeRunStatusChanged. StartLogic, StopLogic, PauseLogic and ResumeLogic come from UBrainComponent.
Subclass and override the protected SetContextRequirements(FStateTreeExecutionContext& Context, bool bLogErrors) / CollectExternalData(const FStateTreeExecutionContext& Context, const UStateTree* StateTree, TArrayView<const FStateTreeExternalDataDesc> Descs, TArrayView<FStateTreeDataView> OutDataViews) const to publish extra context or external data.
FStateTreeReference TreeRef;
TreeRef.SetStateTree(MyStateTreeAsset); // also calls SyncParameters()
TreeRef.GetMutableParameters().SetValueFloat(TEXT("AggroRange"), 1500.f);
StateTreeComp->SetStateTreeReference(TreeRef);GetParameters() returns const FInstancedPropertyBag& — mutating needs GetMutableParameters().
A tree whose active tasks all opt out of ticking can sleep instead of running every frame. FStateTreeScheduledTick::MakeSleep(), MakeNextFrame(), MakeEveryFrames() and MakeCustomTickRate(DeltaTime) describe the desired cadence; FStateTreeMinimalExecutionContext::AddScheduledTickRequest / UpdateScheduledTickRequest / RemoveScheduledTickRequest manage a request, and ScheduleNextTick() wakes the tree. UStateTreeComponent implements this through FStateTreeComponentExecutionExtension, gated by UStateTreeComponentSchema::IsScheduledTickAllowed() and the StateTree.Component.DefaultScheduledTickAllowed console variable. A task that must not be counted sets bConsideredForScheduling = false.
For per-instance descriptions and custom tick scheduling on your own runner, implement FStateTreeExecutionExtension (GetInstanceDescription, ScheduleNextTick, OnLinkedStateTreeOverridesSet, OnBeginApplyTransition) and pass it in FStartParameters::ExecutionExtension.
Mass behaviours use UMassStateTreeSchema and the FMassStateTreeTaskBase, FMassStateTreeConditionBase and FMassStateTreeEvaluatorBase node types, which add GetDependencies(UE::MassBehavior::FStateTreeDependencyBuilder&) const so the dynamically created UMassStateTreeProcessor (a UMassSignalProcessorBase) can build the right fragment query. Full setup, fragment table, signal names and processor flow are in state-tree-mass-integration.md. For Mass architecture itself, see ue-mass-entity.
| Do not emit | Use in 5.8 | Source |
|---|---|---|
Start(const FInstancedPropertyBag*, int32 RandomSeed) | Start(FStartParameters) | UE_DEPRECATED(5.8) in StateTreeExecutionContext.h:492 |
AppendDebugInfoString(FString&, const FStateTreeExecutionContext&) | GetDebugInfo(const FStateTreeReadOnlyExecutionContext&) | UE_DEPRECATED(5.8) in StateTreeEvaluatorBase.h:44 |
EGenericAICheck operator on the compare conditions | UE::StateTree::EComparisonOperator | UE_DEPRECATED(5.8) in Conditions/StateTreeCommonConditions.h:47 |
STATETREE_POD_INSTANCEDATA(Type) | UE_STATETREE_ZEROED_TRIVIALLY_COPIED_NO_DESTRUCTOR_INSTANCEDATA(Type) (or the _CONSTRUCTED_ variant) | UE_DEPRECATED_MACRO(5.8) in StateTreeTypes.h:1388 |
FStateTreePropertyRefExternalHandle | FStateTreePropertyRef read through the execution context | UE_DEPRECATED(5.8) in StateTreePropertyRef.h:295 |
AddDelegateListener(Listener, Delegate) | BindDelegate(Listener, Delegate) | UE_DEPRECATED(5.6) in StateTreeExecutionContext.h:530 |
RemoveDelegateListener(Listener) | UnbindDelegate(Listener) | UE_DEPRECATED(5.6) in StateTreeExecutionContext.h:541 |
FinishTask(const UE::StateTree::FFinishedTask&, EStateTreeFinishTaskType) | FinishTask(const FStateTreeTaskBase&, EStateTreeFinishTaskType) | UE_DEPRECATED(5.6) in StateTreeExecutionContext.h:790 |
FStateTreeWeakTaskRef / FStateTreeStrongTaskRef | FStateTreeWeakExecutionContext | UE_DEPRECATED(5.6) in StateTreeNodeRef.h:15,51 |
OnBindingChanged(…, const FStateTreePropertyPath&, …) | the FPropertyBindingPath overload | UE_DEPRECATED(5.6) in StateTreeNodeBase.h:186 |
TrySelectChildrenAtUniformRandom | TrySelectChildrenAtRandom | UE_DEPRECATED(all) in StateTreeTypes.h:196 |
TrySelectChildrenBasedOnRelativeUtility | TrySelectChildrenAtRandomWeightedByUtility | UE_DEPRECATED(all) in StateTreeTypes.h:197 |
Compile(FStateTreeDataView, TArray<FText>&) | Compile(UE::StateTree::ICompileNodeContext&) | UE_DEPRECATED(5.6) final stub in StateTreeNodeBase.h:141 |
StateTreeComp->bStartLogicAutomatically = true; | StateTreeComp->SetStartLogicAutomatically(true); | protected in Components/StateTreeComponent.h:187 |
TreeRef.GetParameters().SetValueFloat(…) | TreeRef.GetMutableParameters().SetValueFloat(…) | const accessor in StateTreeReference.h:61 |
FStateTreeActorContext | TStateTreeExternalDataHandle<AActor> or a Category = "Context" instance-data property | no such type in the engine |
Omitting GetInstanceDataType(): the single most common State Tree bug. using FInstanceDataType = …; documents the type; only the override registers storage.
using FInstanceDataType = FMyTaskInstanceData;
virtual const UStruct* GetInstanceDataType() const override { return FInstanceDataType::StaticStruct(); }Storing the execution context: it is a per-tick view over FStateTreeInstanceData. Keep the instance data as a UPROPERTY(Transient) on the owner and rebuild the context each tick, or capture FStateTreeWeakExecutionContext if you need it later.
Mutating the node struct: every node virtual is const, so Timer += DeltaTime; on a member will not compile. Write to Context.GetInstanceData(*this).
Deriving from FStateTreeTaskBase directly: stock schemas only allow FStateTreeTaskCommonBase and siblings, so the node never appears in the editor picker. Derive from the *CommonBase struct (or the Mass/AI base) that your schema accepts.
Not guarding schema Allow* overrides with #if WITH_EDITOR: the base declares them editor-only (StateTreeSchema.h:96), so an unguarded override compiles in the editor and fails in Game/Shipping targets.
Side effects in TestCondition: selection may test the same condition several times in a frame. Keep it pure; cache in the condition's EnterState instead.
Leaving delegates bound: BindDelegate in EnterState requires UnbindDelegate in ExitState, otherwise the listener fires against a state that is no longer active.
Exceeding MaxStates: the active state path is capped at 8. Deeper hierarchies fail selection rather than warning loudly.
Assuming Tick runs: with bShouldCallTick = false, or when a scheduled tick puts the tree to sleep, tasks do not tick and bound properties are not copied. Drive those tasks from events or delegates.
ue-ai-navigation — behaviour trees, perception, EQS, navigation and Smart Objectsue-mass-entity — Mass processors, fragments, traits, entity queriesue-gameplay-abilities — abilities and effects that drive or react to state changesue-gameplay-framework — controllers, pawns and game-mode lifecycle around the treeue-actor-component-architecture — component ownership, ticking and replication setupue-cpp-foundations — USTRUCT rules, delegates, subsystem accessue-gameplay-tags-messaging — declaring gameplay tags used by State Tree events and transitionsue-gameplay-cameras — spring arms, view targets, camera modifiers, shakes and the Gameplay Camera System© quodsoler, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
SKILL.md and 2 other files (references) in skills/ue-state-trees of quodsoler/unreal-engine-skills.
Open the folder on GitHubat commit f3742d7
Ue State Trees next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Ue State Trees this skillquodsoler/unreal-engine-skills | 360 | — | ~7.4k | Automated safety check: Pass | MIT | |
| Debugging CodeJetBrains/skills | 366 | 1 repos | ~3.8k | Automated safety check: Pass | None | |
| Ue Specifiersfjz13/UnrealSpecifiers | 1.1k | — | ~1.4k | Automated safety check: Pass | Custom licence | |
| Unreal Engine MCPEpicGames/unreal-engine-skills-for-claude-code-plugin | 332 | — | ~1.8k | Automated safety check: Pass | MIT | |
| Unreal Live CodingItalink/UnrealClientProtocol | 127 | — | ~1k | Automated safety check: Pass | MIT | |
| Unreal Cpp Gameplayukanwat/overtime | 387 | 1 repos | ~1.5k | Automated safety check: Pass | Apache-2.0 |
JetBrains/skills
A skill your agent uses for debugger-driven runtime root-cause analysis in Rider-supported solutions and projects, including .NET/C, F, VB, C++, Unity, Unreal Engine, and other GameDev or…
fjz13/UnrealSpecifiers
A skill your agent uses when writing, editing, reviewing, validating, or explaining Unreal Engine C++ reflected declarations: UCLASS, USTRUCT, UENUM, UINTERFACE, UPROPERTY, UFUNCTION, UPARAM, UMETA…
EpicGames/unreal-engine-skills-for-claude-code-plugin
Drives a live Unreal Editor through the unreal-mcp server: spawn actors, edit Blueprints, materials and sequences, change properties and trigger Live Coding.
Italink/UnrealClientProtocol
Trigger Live Coding compilation via UCP. An agent skill from Italink/UnrealClientProtocol.
ukanwat/overtime
Write Unreal Engine 5 C++ gameplay code: the UCLASS/UPROPERTY/UFUNCTION reflection macros, the Gameplay Framework (GameMode, Pawn, Character, PlayerController, Actor components), and the module…
ukanwat/overtime
Set up player input in Unreal Engine 5 with Enhanced Input: Input Actions, Input Mapping Contexts, modifiers and triggers, adding the mapping context, and binding actions by ETriggerEvent.
quodsoler/unreal-engine-skills
Unreal Engine C++ guidance for AActor and UActorComponent: lifecycle hooks, spawning, component creation and attachment, ticking, interfaces and composition.
quodsoler/unreal-engine-skills
Guides Unreal Engine C++ AI work across AI controllers, behavior trees, blackboards, perception, navmesh pathfinding, EQS and Smart Objects.
quodsoler/unreal-engine-skills
Reference for writing and debugging Unreal Engine 5.8 animation C++: AnimInstance and proxy, montages, notifies, curves, blend spaces, state machines, linked layers and root motion.
quodsoler/unreal-engine-skills
Picks and applies the right Unreal Engine C++ concurrency API, from UE::Tasks and FPipe to ParallelFor, FRunnable, locks and timers, with game-thread safety rules.
quodsoler/unreal-engine-skills
A skill your agent uses when playing, mixing or debugging sound in Unreal Engine — one-shot SFX, looping ambience, music, dialogue or procedural audio.
quodsoler/unreal-engine-skills
Reference for exposing Unreal Engine C++ to Blueprint and calling Blueprint from C++, covering UFUNCTION and UPROPERTY specifiers, latent and async nodes, and interfaces.
Works with
Categories
A skill your agent uses when writing or debugging State Tree logic in Unreal Engine C++ — tasks, conditions, evaluators, considerations, schemas, transitions, events or Mass behaviours. Ue State Trees is an agent skill from quodsoler/unreal-engine-skills. Use when writing or debugging State Tree logic in Unreal Engine C++ — tasks, conditions, evaluators, considerations, schemas, transitions, events or Mass behaviours.
Ue State Trees fits situations like: debugging State Tree logic in Unreal Engine C++ — tasks; mass behaviours; the user mentions StateTree; FStateTreeTaskBase.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a claude-code`. Or copy the skill folder (skills/ue-state-trees in quodsoler/unreal-engine-skills) into .claude/skills/ue-state-trees in your project. Claude Code loads it when a task matches its description.
Run `npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a codex`. Or copy the skill folder (skills/ue-state-trees in quodsoler/unreal-engine-skills) into .agents/skills/ue-state-trees in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add quodsoler/unreal-engine-skills --skill ue-state-trees -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/ue-state-trees, .gemini/skills/ue-state-trees, .github/skills/ue-state-trees and .opencode/skills/ue-state-trees in your project.
SKILL.md names no scripts, command-line tools or credentials: Ue State Trees is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Ue State Trees is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 7.4k tokens (SKILL.md is roughly 29k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full. Its references folder adds about 9.3k tokens, read only when the agent opens those files.
Skills that share tags, products or a category with Ue State Trees: Debugging Code (JetBrains/skills, 366 stars), Ue Specifiers (fjz13/UnrealSpecifiers, 1.1k stars), Unreal Engine MCP (EpicGames/unreal-engine-skills-for-claude-code-plugin, 332 stars) and Unreal Live Coding (Italink/UnrealClientProtocol, 127 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
quodsoler (a GitHub user) maintains it in quodsoler/unreal-engine-skills, which has 360 GitHub stars. The repository holds 31 skills in this directory. The repository was last updated on September 28, 2026.
Source: quodsoler/unreal-engine-skills on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.