Can You Set a State Tree Dynamically on an Actor Spawn?

Hello! I have been investigating the use of State Trees to control AI in my project, but I am looking for a way to set an actors state tree from a variable when it spawns. After having a look, I’m not too sure how to go about this or if it’s currently possible.

I would have a number of different state trees I can assign for an actor and would really prefer not to have to make a new child of my actor for every different state that could be used in it. Does anyone know of a way to set a state tree from a variable at spawn?

In case anyone else has this issue I found a way to do it by changing the state tree component when spawning an actor.

I created an Enum to define the different state tree options, and added it as a variable to the BP that’ll be spawned. Then I set the Enum variable in the BP to be exposed on spawn.

The actor BP that gets spawned in needs to have a state tree component, but the values can be left as none.

From the Begin Play node in the actor BP, I added a switch node on the Enum I created. Then from each pin I used the “Add state tree component” node to set the state tree for that case. Selecting the node allows you to define the state tree the component should use.

Then set the state tree component that’s already in the BP to the return value from the “Add state Tree component” node.

When spawning the actor you’ll just have to set the enum and it should work.

I couldn’t have figured it out without this person’s post:

Here’s a video tutorial if more explanation is needed:

2 Likes

I encountered a similar scenario in my game where I needed to dynamically set the state tree at runtime. My solution was to create a custom class that inherits from UStateTreeComponent. In this custom class, I implemented a function to replace the current state tree. However, this approach required working in C++, as I couldn’t find a way to inherit StateTreeComponent directly in Blueprints.

Here’s how I implemented it:

By calling SetStartLogicAutomatically(false) in the constructor, the state tree does not start automatically, giving me control over when to initiate it.

Here’s an example of how this can be used in Blueprints:

1 Like

Hey,

thanks for this post! I hope you’ll read this message xD

As I’m new to UE C++, could you further explain which steps I need to actually take for creating this? I’ve set up VS for my 5.5 project. But I don’t know where to start creating my custom C++ class.
(+ Do I need the source version for that?)

Kind regards,
Division Software

Hi,

you’d need to create your own StateTreeAIComponent, you can just open unreal engine, click on your C++ folder, right click, and create new C++ class, in the search you can type StateTreeAIComponent, or if its not for AI, just StateTreeComponent. Click on that, name your Class, like MyProjectStateTreeAiComponent.

Now with the new class created, you’d need some boilerplate code, so it works properly, in this case you’ll need at least the Constructor, BeginPlay and Tick function, from the Parent component we inherited(StateTreeAIComponent).

it would look something like this in your MyProjectStateTreeAiComponent.h file:

#pragma once

#include "CoreMinimal.h"
#include "Components/StateTreeAiComponent.h"
#include "MyProjectStateTreeComponent.generated.h"

/**
 *
 */

UCLASS(ClassGroup = (Custom), meta = (BlueprintSpawnableComponent))
class MYPROJECT_API UMyProjectStateTreeAiComponent: public UStateTreeAIComponent
{
	GENERATED_BODY()

public:
	UMyProjectStateTreeAiComponent();

protected:
	virtual void BeginPlay() override;

	// Called every frame
	virtual void TickComponent(float DeltaTime, ELevelTick TickType,
		FActorComponentTickFunction* ThisTickFunction) override;
	
	UFUNCTION(BlueprintCallable, Category="MyProject")
	void StartLogicWithSelectedStateTree(UStateTree* StateTree);
};

also if you want to include the logic from the previous post to Start Logic with a different StateTree Asset, then also add the last function above StartLogicWithSelectedStateTree

and create the definitions in the .cpp file:

#include "MyProjectStateTreeComponent.h"

UMyProjectStateTreeAiComponent::UMyProjectStateTreeAiComponent()
{
	PrimaryComponentTick.bCanEverTick = true;
	PrimaryComponentTick.bStartWithTickEnabled = true;

	SetStartLogicAutomatically(false);
}

void UMyProjectStateTreeAiComponent::BeginPlay()
{
	Super::BeginPlay();
}

void UMyProjectStateTreeAiComponent::TickComponent(float DeltaTime, ELevelTick TickType,
	FActorComponentTickFunction* ThisTickFunction)
{
	Super::TickComponent(DeltaTime, TickType, ThisTickFunction);
}

void UMyProjectStateTreeAiComponent::StartLogicWithSelectedStateTree(UStateTree* StateTree)
{
	if (StateTree)
	{
		if (IsRunning())
		{
			Cleanup();
		}

		StateTreeRef.SetStateTree(StateTree);
		StartLogic();
	}
}

Then you should add your component to the Ai Controller or whatever actor you want to use it on, and when you then drag the component in and call StartLogicWithSelectedStateTree, it will give you the option to select a StateTree Asset and will execute the logic above!

Just tried implementing it myself and also had to add "StateTreeModule" to my MyProject.Build.cs file:

        PublicDependencyModuleNames.AddRange(
            new string[] {
                "Core",
                "CoreUObject",
                "Engine",
                "GameplayTags",
                "Niagara",
                "NavigationSystem",
                "AIModule",
                // ... all your other modules ...
                "StateTreeModule" // add this
            });

Hey, thanks for your help! I’ve got it already working with some help of C++ experienced people :slight_smile: