Unexpected Could not trigger completion transition behavior in state tree

Hello,

We have encountered rather inconsistent behavior regarding transitions in state trees. The behavior can be illustrated using a small example state tree in the following picture.

[Image Removed]

I would expect that the tree goes through states in the following order

  • Root, Level_1_1
  • Root, Level_1_2
  • Root, Level_1_3, Level_2_1
  • Root, Level_1_3, Level_2_2
  • Root, Level_1_3, Level_2_3

And then the execution would loop inside the substrates of Level_1_3. However, the actual behavior is that after the Level_2_1 state finishes, the execution goes back to the Root state. In the Rewind debugger the reason is stated as “Could not trigger completion transition, jump back to root state”.

[Image Removed]

Is there a reason for this? It comes as a surprise to me.

If I remove the task from the State Level_1_3, so it wouldn’t have any tasks, the execution runs as expected.

Also if i change the order of the 1st level states and set Level_1_3 to be a first child of the Root state

[Image Removed]

the execution loops through Level_2_1, Level_2_2, Level_2_3 as I would expect. That makes the described behavior even more confusing.

I would appreciate a tip or comment regarding this behavior.

Cheers,

Matej

[Attachment Removed]

Steps to Reproduce
Create a state tree pictured in the description and execute it

[Attachment Removed]

Hello,

I have probably discovered the reason for behavior described earlier. It seems that when the State_2_1 state finishes also the State_1_3 also gets into succeeded status. The execution of the state tree then looks for transitions to execute. It searches for a first state that hasn’t the ETaskCompletionStatus::Running status.

The search starts from root and ends with the first state that is found. The code in StateTreeExecutionStatus.cpp is

for (int32 StateIndex = 0; StateIndex < CurrentFrame.ActiveStates.Num(); ++StateIndex)
{
	const FStateTreeStateHandle CurrentHandle = CurrentFrame.ActiveStates[StateIndex];
	const FCompactStateTreeState& State = CurrentStateTree->States[CurrentHandle.Index];
	const ETaskCompletionStatus StateTasksStatus = CurrentFrame.ActiveTasksStatus.GetStatus(State).GetCompletionStatus();
	if (StateTasksStatus != ETaskCompletionStatus::Running)
	{
		CurrentStatus = CastToRunStatus(StateTasksStatus);
		FrameIndexToStart = FrameIndex;
		StateIndexToStart = StateIndex;
		break;
	}
}

Naturally it finds the State_1_3 state which has no transitions defined and thus there is nothing to execute. Is there a way to circumvent this behavior? In our actual use case the State_1_3 state is important since it contains tasks that should be active during the duration of all substates.

Cheers,

Matej

[Attachment Removed]

Hello again,

I am sorry about adding new pieces of information bit by bit instead of writing it all together. I am still looking into this problem and I suspect that the issue is the fact that the code getting the StateTasksStatus returns Succeeded for the Level_1_3 state. It contains only a DebugText task which never finishes and is never considered for state completion.

Moreover, it really seems to be depending on the actual form of the state tree. I have added a dummy state that is the parent state for the Level_1_3 state. Like this

[Image Removed]Now the StateTaskStatus is Running for both Dummy and even Level_1_3. Is there any reason why adding Dummy state makes the execution work differently?

Matej

[Attachment Removed]

Most certainly a bug! It is just not one we had stumbled onto ourselves. Our primary dev for StateTree is looking into it right now. I have created a JIRA bug report for it as well. It is live here on our public issue tracker: https://issues.unrealengine.com/issue/UE-384337.

-James

[Attachment Removed]