When using State Trees, the AI Debugger can be accessed during play to show information about their current execution state. If a behavior tree is currently in a state that references a linked tree, the AI debugger attempts to show all levels of execution, in this case both the main tree state and the linked tree state. However, when building the output for the linked state tree, it incorrectly attempts to access state info from the root tree. This results in wrong info being displayed, and can lead to an array-access-out-of-bounds crash if the linked tree has more states than the root tree.
The issue repros as of CL 41680477 in ue5-main from 2025-04-16. It was introduced by CL 29884503 on 2023-11-22.
The problem has been tracked down to file [Engine/Plugins/Runtime/StateTree/Source/StateTreeModule/Private/StateTreeExecutionContext.cpp], function FStateTreeExecutionContext::GetDebugInfoString(). Inside a loop of "CurrentFrame.ActiveStates", it tries to access infor from "RootStateTree" instead of "CurrentStateTree".
This is a regression in the sense that viewing the AI Debugger did not crash up to UE 5.3 and does crash on UE 5.5, but not a regression in that it is related to a new implementation feature of the AI Debugger. In any case, the breaking CL has already been found.
Setup:
1. Enable plugins "StateTree" and "GameplayStateTree"
2. Create assets on the Content Browser:
2.1. StateTree "ST_Linked" with schema "StateTree AI Component"
2.2. StateTree "ST_Main" with schema "StateTree AI Component"
2.3. Blueprint "BP_Pawn" with parent "Pawn"
2.4. Blueprint "BP_AI" with parent "AIController"
3. Edit ST_Linked
3.1. Add a state "LinkedState1"
3.2. Add a state "LinkedState2"
3.3. On the details panel for "LinkedState2":
3.3.1. Add a new Task "Delay Task" and check "Run Forever"
3.3.2. Add a new Transition "On State Completed" to "Root"
3.4. Compile, save and close
4. Edit ST_Main
4.1. Add a state "MainState1"
4.2. On the details panel for "MainState1":
4.2.1. Change "Type" to "Linked Asset"
4.2.2. Change "Linked Asset" to point to "ST_Linked"
4.3. Compile, save and close
5. Edit BP_AI
5.1. Add a "StateTreeAI" component
5.2. On the details panel for StateTreeAI:
5.2.1. Change "AI – State Tree" to point to "ST_Main"
5.3. Compile, save and close
6. Edit BP_Pawn
6.1. On the details panel for the actor:
6.1.1. Change "Pawn – AI Controller Class" to "BP_AI"
6.2. Compile, save and close
7. Place an instance of BP_Pawn on any level
8. Save the level
Test A:
A.1. Edit ST_Linked, right-click "LinkedState2" and uncheck "State Enabled". Compile and save.
A.2. Start PIE and press ' (apostrophe) to view the AI Debugger
--> Note that, under category "BehaviorTree", section "Global Tasks" appears twice (first for ST_Main, then for ST_Linked). Note how the second task list shows "MainState1" instead of the expected "LinkedState1".
A.3. Stop PIE
Test B:
B.1. Edit ST_Linked, re-enable "LinkedState2" and disable "LinkedState1". Compile and save.
A.2. Start PIE and press ' (apostrophe) to view the AI Debugger
--> Crash! (the engine tried to show the name of a non-existing second state of ST_Main, instead of the expected ST_Linked)
UnrealEditor-StateTreeModule.dll!FStateTreeExecutionContext::GetDebugInfoString() Line 4543 C++
UnrealEditor-GameplayStateTreeModule.dll!UStateTreeComponent::GetDebugInfoString() Line 346 C++
UnrealEditor-AIModule.dll!FGameplayDebuggerCategory_BehaviorTree::CollectData(APlayerController * OwnerPC, AActor * DebugActor) Line 38 C++
UnrealEditor-GameplayDebugger.dll!AGameplayDebuggerCategoryReplicator::CollectCategoryData(bool bForce) Line 897 C++
UnrealEditor-GameplayDebugger.dll!UGameplayDebuggerLocalController::OnSelectedObject(UObject * Object) Line 924 C++
[Inline Frame] UnrealEditor-GameplayDebugger.dll!Invoke(void(UGameplayDebuggerLocalController::*)(UObject *) PtrMemFun, UGameplayDebuggerLocalController * &) Line 66 C++
[Inline Frame] UnrealEditor-GameplayDebugger.dll!UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(void(UGameplayDebuggerLocalController::*)(UObject *) &) Line 317 C++
UnrealEditor-GameplayDebugger.dll!TBaseUObjectMethodDelegateInstance<0,UGameplayDebuggerLocalController,void __cdecl(UObject *),FDefaultDelegateUserPolicy>::ExecuteIfSafe(UObject * <Params_0>) Line 667 C++
[Inline Frame] UnrealEditor-UnrealEd.dll!TMulticastDelegateBase<FDefaultDelegateUserPolicy>::Broadcast(UObject *) Line 257 C++
UnrealEditor-UnrealEd.dll!TMulticastDelegate<void __cdecl(UObject *),FDefaultDelegateUserPolicy>::Broadcast(UObject * <Params_0>) Line 1079 C++
UnrealEditor-UnrealEd.dll!USelection::OnElementListSyncEvent(const TTypedElementList<FTypedElementHandle> & InElementList, TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType InSyncType, const FTypedElementHandle & InElementHandle, bool bIsWithinBatchOperation) Line 235 C++
[Inline Frame] UnrealEditor-UnrealEd.dll!Invoke(void(USelection::*)(const TTypedElementList<FTypedElementHandle> &, TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType, const FTypedElementHandle &, bool) PtrMemFun, USelection * &) Line 66 C++
[Inline Frame] UnrealEditor-UnrealEd.dll!UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(void(USelection::*)(const TTypedElementList<FTypedElementHandle> &, TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType, const FTypedElementHandle &, bool) &) Line 317 C++
UnrealEditor-UnrealEd.dll!TBaseUObjectMethodDelegateInstance<0,USelection,void __cdecl(TTypedElementList<FTypedElementHandle> const &,enum TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType,FTypedElementHandle const &,bool),FDefaultDelegateUserPolicy>::ExecuteIfSafe(const TTypedElementList<FTypedElementHandle> & <Params_0>, TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType <Params_1>, const FTypedElementHandle & <Params_2>, bool <Params_3>) Line 667 C++
[Inline Frame] UnrealEditor-TypedElementFramework.dll!TMulticastDelegateBase<FDefaultDelegateUserPolicy>::Broadcast(const TTypedElementList<FTypedElementHandle> &) Line 257 C++
[Inline Frame] UnrealEditor-TypedElementFramework.dll!TMulticastDelegate<void __cdecl(TTypedElementList<FTypedElementHandle> const &,enum TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType,FTypedElementHandle const &,bool),FDefaultDelegateUserPolicy>::Broadcast(const TTypedElementList<FTypedElementHandle> & <Params_0>, TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType) Line 1079 C++
UnrealEditor-TypedElementFramework.dll!TTypedElementList<FTypedElementHandle>::FLegacySync::Private_EmitSyncEvent(const TTypedElementList<FTypedElementHandle>::FLegacySync::ESyncType InSyncType, const FTypedElementHandle & InElementHandle) Line 53 C++
[Inline Frame] UnrealEditor-TypedElementFramework.dll!TTypedElementList<FTypedElementHandle>::NoteListChanged(const TTypedElementList<FTypedElementHandle>::EChangeType) Line 512 C++
UnrealEditor-TypedElementFramework.dll!TTypedElementList<FTypedElementHandle>::AddElementImpl(FTypedElementHandle && InElementHandle) Line 316 C++
[Inline Frame] UnrealEditor-TypedElementRuntime.dll!TTypedElementList<FTypedElementHandle>::Add(const FTypedElementHandle &) Line 399 C++
UnrealEditor-TypedElementRuntime.dll!ITypedElementSelectionInterface::SelectElement(const FTypedElementHandle & InElementHandle, const TSharedPtr<TTypedElementList<FTypedElementHandle>,1> & InSelectionSet, const FTypedElementSelectionOptions & InSelectionOptions) Line 20 C++
UnrealEditor-LevelEditor.dll!TTypedElement<ITypedElementSelectionInterface>::SelectElement(TSharedRef<TTypedElementList<FTypedElementHandle>,1> InSelectionSet, const FTypedElementSelectionOptions & InSelectionOptions) Line 305 C++
UnrealEditor-LevelEditor.dll!FActorElementLevelEditorSelectionCustomization::SelectActorElement(const TTypedElement<ITypedElementSelectionInterface> & InActorSelectionHandle, TSharedRef<TTypedElementList<FTypedElementHandle>,1> InSelectionSet, const FTypedElementSelectionOptions & InSelectionOptions) Line 233 C++
UnrealEditor-LevelEditor.dll!FActorElementLevelEditorSelectionCustomization::SelectElement(const TTypedElement<ITypedElementSelectionInterface> & InElementSelectionHandle, TSharedRef<TTypedElementList<FTypedElementHandle>,1> InSelectionSet, const FTypedElementSelectionOptions & InSelectionOptions) Line 35 C++
UnrealEditor-TypedElementRuntime.dll!FTypedElementSelectionSetElement::SelectElement(const FTypedElementSelectionOptions & InSelectionOptions) Line 118 C++
UnrealEditor-TypedElementRuntime.dll!UTypedElementSelectionSet::SelectElement(const FTypedElementHandle & InElementHandle, const FTypedElementSelectionOptions InSelectionOptions) Line 199 C++
UnrealEditor-UnrealEd.dll!USelection::Select(UObject * InObject) Line 244 C++
UnrealEditor-GameplayDebugger.dll!AGameplayDebuggerCategoryReplicator::SetDebugActor(AActor * Actor, bool bSelectInEditor) Line 1069 C++
UnrealEditor-GameplayDebugger.dll!UGameplayDebuggerLocalController::OnSelectActorTick() Line 850 C++
UnrealEditor-GameplayDebugger.dll!UGameplayDebuggerLocalController::ToggleActivation(UGameplayDebuggerLocalController::ESelectionMode SelectionMode) Line 647 C++
[Inline Frame] UnrealEditor-GameplayDebugger.dll!Invoke(void(UGameplayDebuggerLocalController::*)()) Line 66 C++
[Inline Frame] UnrealEditor-GameplayDebugger.dll!UE::Core::Private::Tuple::TTupleBase<TIntegerSequence<unsigned int>>::ApplyAfter(void(UGameplayDebuggerLocalController::*)() &) Line 317 C++
UnrealEditor-GameplayDebugger.dll!TBaseUObjectMethodDelegateInstance<0,UGameplayDebuggerLocalController,void __cdecl(void),FDefaultDelegateUserPolicy>::Execute() Line 651 C++
[Inline Frame] UnrealEditor-Engine.dll!TDelegate<void __cdecl(void),FDefaultDelegateUserPolicy>::Execute() Line 613 C++
UnrealEditor-Engine.dll!FInputActionUnifiedDelegate::Execute(const FKey Key) Line 288 C++
UnrealEditor-Engine.dll!UPlayerInput::EvaluateInputDelegates(const TArray<UInputComponent *,TSizedDefaultAllocator<32>> & InputComponentStack, const float DeltaTime, const bool bGamePaused, const TArray<TTuple<FKey,FKeyState *>,TSizedDefaultAllocator<32>> & KeysWithEvents) Line 1549 C++
UnrealEditor-EnhancedInput.dll!UEnhancedPlayerInput::EvaluateInputDelegates(const TArray<UInputComponent *,TSizedDefaultAllocator<32>> & InputComponentStack, const float DeltaTime, const bool bGamePaused, const TArray<TTuple<FKey,FKeyState *>,TSizedDefaultAllocator<32>> & KeysWithEvents) Line 776 C++
UnrealEditor-Engine.dll!UPlayerInput::ProcessInputStack(const TArray<UInputComponent *,TSizedDefaultAllocator<32>> & InputComponentStack, const float DeltaTime, const bool bGamePaused) Line 1174 C++
UnrealEditor-Engine.dll!APlayerController::ProcessPlayerInput(const float DeltaTime, const bool bGamePaused) Line 2776 C++
There's no existing public thread on this issue, so head over to Questions & Answers just mention UE-273333 in the post.
0 |
Component | UE - AI - Debugging |
---|---|
Affects Versions | 5.4, 5.5.4 |
Created | Apr 17, 2025 |
---|---|
Updated | May 2, 2025 |