#unreal

InstanceData is used by both StateTree Tasks and StateTree Evaluators. It’s used to hold instance-specific data which can be changed at runtime, and can be bound to properties on other tasks or evaluators. Compare to properties directly on the instance struct, which are only settable via editor, and cannot be bound to other values.

Example

USTRUCT()
struct FMyInstanceData
{
	GENERATED_BODY()
	
	UPROPERTY(EditAnywhere, Category=Input)
	int32 Foo = 0;
}

Categories

Properties on InstanceData structs should be assigned one of the following categories:

  • Input: Values which are required to be bound to something.
  • Output: Values which are only used for outputting data.
  • Parameter: Optional input values which can be either bound to runtime values or edited in editor.

These categories can also be used in Blueprint-based tasks and evaluators for their properties.

Class-based InstanceData

You can also make your InstanceData an UObject. This is mainly useful if your task or evaluator runs logic which needs to bind dynamic delegates, since you cannot bind them to the task struct itself.

UCLASS()
class UMyInstanceData : public UObject
{
	GENERATED_BODY()
}

For UObject data, you use StaticClass() instead of StaticStruct() in GetInstanceDataType()

virtual const UStruct* GetInstanceDataType() const override { return UInstanceDataType::StaticClass(); }

Instead of using GetInstanceData, you need to use GetInstanceDataPtr:

UInstanceDataType* InstanceData = Context.GetInstanceDataPtr<UInstanceDataType>(*this);

For more examples on how this is used, see FStateTreeTask_PlayContextualAnim in engine code.

Gotchas

When using GetInstanceData for purposes of outputting values to be used elsewhere in your state tree, remember to use a reference:

//This will not work because you're getting a copy
FInstanceDataType Foo = Context.GetInstanceData(*this);
 
//The type should be a reference so writing into it actually updates the data correctly
FInstanceDataType& Foo = Context.GetInstanceData(*this);