Custom tasks, evaluators and conditions can be written both in C++ and BP’s. C++ offers better control, such as not making tasks tick.



This function can be used to load objects from outside the state tree. This works by defining a handle, and linking it:

//In your header
TStateTreeExternalDataHandle<AAIController> ControllerHandle;
virtual bool Link(FStateTreeLinker& Linker) override;
//.cpp file
bool FMySTT::Link(FStateTreeLinker& Linker)
	return true;
EStateTreeRunStatus FMySTT::EnterState(FStateTreeExecutionContext& Context, const FStateTreeTransitionResult& Transition) const
	AAIController& Controller = Context.GetExternalData(ControllerHandle);
	// ....

How it works

The data available via GetExternalData is defined in UStateTreeComponent (if you use Mass state trees there’s probably different place which I’ve not looked at)

UStateTreeComponent has a function SetContextRequirements which is used to fill external data into the tree. Check its implementation for specifics.

Troubleshooting state trees


Visual Logger can be used to see what states/tasks the tree is selecting. A state tree debugger can also be opened from the state tree editor’s menus, which can display what state you are currently in, and some other details.

Common problems

  • Check that global tasks don’t return success immediately which stops tree (should show up in visual logger)
  • Check that tasks/evaluators don’t use external data which is unavailable
    • This will not say anything useful in logs at least in Unreal Engine 5.3.1. The log will simply say the tree is being started, and then no output from the state tree whatsoever.
    • Potential cause: You start your state tree in a controller’s beginplay instead of onpossess, and your external data requires a pawn to exist. A pawn may not be set yet in a controller’s beginplay.
  • Crashing when using GetExternalData may be caused by attempting to access external data that doesn’t exist. For example, if you try to access an AI Controller, and your state tree is in the pawn.
  • Crashing when using GetInstanceData may be caused from a missing GetInstanceDataType.

State tree performance

Measure with Unreal Insights. State Tree total seems to show up as “StateTree”. Blueprint based tasks seem to perform significantly worse than C++ based tasks, so depending on how often the tasks execute, using C++ may give decent performance benefits.

Other issues

Issues valid at least for Unreal Engine 5.3

  • State Trees cannot be changed at runtime if ran through the StateTreeComponent
  • State Trees might be possible to run outside of the component, but no builtin support for it