UE 5.8 StateTree: A State with Tasks all marked as not affecting completion may incorrectly complete as Succeeded

Summary

In UE 5.8 StateTree, if a State:

  1. has at least one Task;
  2. all Tasks are configured as not affecting State completion, i.e. Considered for Completion = false;
  3. the State’s completion type is Any;
  4. the Task keeps returning Running after EnterState and never calls FinishTask;

then under some runtime conditions the State may still be evaluated as Succeeded shortly after entering. This triggers completion transition evaluation. If the State has no completion transition, StateTree falls back to Root and interrupts a still-running child State.

This does not necessarily reproduce on every Play. The compiled StateTree asset only defines the completion mask / bit layout; it does not store the current completion status. The current status is stored in a reusable runtime ActiveTasksStatus bit buffer. If the synthetic bit is currently 0, the State may temporarily behave as Running. If that bit has been polluted by previous state or previous runtime logic as Succeeded, and ResetStatus() fails to clear it, the State appears completed immediately after entering.

Local debugging indicates the issue is caused by a mismatch between the UE 5.8 MakeCompletionTasksMask() synthetic completion bit and runtime ResetStatus(State.TasksNum):

  • MakeCompletionTasksMask() inserts an extra synthetic completion bit when there are no considered tasks;
  • FStateTreeTasksCompletionStatus::Push() still calls ResetStatus(State.TasksNum);
  • when TasksNum > 0 and all tasks are not considered, the synthetic bit is placed after the real task bit(s);
  • ResetStatus(State.TasksNum) clears only the real task bit(s), not the synthetic bit;
  • if the synthetic bit remains Succeeded, the whole State is incorrectly evaluated as completed.

What Type of Bug are you experiencing?

AI

Steps to Reproduce

  1. Create or open a UE 5.8 project.

  2. Create a StateTree.

  3. Create a structure like this:

    Root
     └─ ParentState
        └─ ChildState
    
  4. Add a StateTree Task to ParentState, for example a Blueprint Task:

    • EnterState only prints a log message;
    • it does not call FinishTask;
    • it does not return Succeeded from Tick;
    • it remains Running.
  5. Set the Task’s Considered for Completion / Toggle Completion to disabled, so it does not affect State completion.

  6. Set ParentState completion type to Any.

  7. Do not configure a completion transition on ParentState.

  8. Let the StateTree enter ParentState.ChildState.

  9. Observe the StateTree runtime behavior.

Expected Result

When a State has Tasks but all of them have Considered for Completion = false:

  • those Tasks should not drive the State to completed;
  • if there is no other explicit State-level completion source, the State should remain Running;
  • while a child State is still Running, the parent State should not become Succeeded due to a stale synthetic completion bit;
  • StateTree should not fall back to Root via completion fallback.

Observed Result

The parent State may be evaluated as Succeeded even though:

  • its only Task returns Running;
  • that Task is explicitly configured as not affecting State completion;
  • the child State is still Running.

When this happens, StateTree tries to find a completion transition for the parent State. If no completion transition exists, StateTree triggers the internal fallback:
“Could not trigger completion transition, jump back to root state.”
Internal → Root

This interrupts the still-running child State.

The symptom may be intermittent. If the reused ActiveTasksStatus runtime bit buffer does not currently have the synthetic completion bit polluted, the State may behave normally. If the synthetic bit remains Succeeded, the State is incorrectly treated as completed immediately after entering.

Affects Versions

5.8

Platform(s)

Android
iOS
Linux
Mac
OpenXR
visionOS
Windows

Upload an image