FAnimNode_BlendStack_Standalone will never blend in an asset that is requested each frame

Our animation system is using motion matching, and based on the 5.6 GASP project. We recently ran into an issue where under specific circumstances, the motion matching anim node would get the same search result from the Pose Search Database each update, with bJumpToPose set, resulting in it pushing that same pose to the blend stack each update.

The blend stack has this logic in FAnimNode_BlendStack_Standalone::InternalBlendTo:

	// If we don't add a new player, re-use the same graph...
	else if (!bBlendStackIsEmpty && AnimPlayers[0].GetBlendInPercentage() < 1.f &&
		AnimPlayers[0].GetCurrentBlendInTime() < MaxBlendInTimeToOverrideAnimation)
	{
		// replacing AnimPlayers[0] with this new BlendTo request
		UE_LOG(LogBlendStack, Verbose, TEXT("FAnimNode_BlendStack_Standalone '%s' replaced by '%s' because blend time in is less than MaxBlendInTimeToOverrideAnimation (%.2f / %.2f)"), *AnimPlayers[0].GetAnimationName(), *GetNameSafe(AnimationAsset), AnimPlayers[0].GetCurrentBlendInTime(), MaxBlendInTimeToOverrideAnimation);
	}

The second if check in there is the problem. Provided MaxBlendInTimeToOverrideAnimation is > deltatime, then each update, the new blend request replaces the most recent one (index 0), and has its blend weight reset back to 0. Then it ticks once, before being replaced and reset again on the next update.

As a result of this, when the motion matching system picks the same pose each frame in this fashion, the character stays stuck in their original pose and will never blend in to the requested one.

This could be fixed by tweaking MaxBlendInTimeToOverrideAnimation, but this causes other problems, as there are situations where you would want to ignore or replace blends that were only ever requested once and then became irrelevant.

I was able to resolve the issue locally by adding a check in that if statement:

else if (!bBlendStackIsEmpty && (AnimPlayers.Num() == MaxActiveBlends) && AnimPlayers[0].GetBlendInPercentage() < 1.f &&
	AnimPlayers[0].GetCurrentBlendInTime() < MaxBlendInTimeToOverrideAnimation)

however I don’t think this is the best solution. Perhaps we could instead check if the asset is the same as the one in index 0?

[Attachment Removed]

Hey there,

I don’t think there is an issue with the code identified its most likely a tuning problem. There are a couple things you could try.

1.Adjust the parameter “Continuing Pose Cost Bias” in Schema.

This acts as a penalty value, artificially lowering the cost of “playing the next frame naturally.” For example, if the cost of switching animations is 8, and the cost of continuing playback is 10, the system will switch. If you apply a -3 bias to continuation, the cost to continue becomes 7, and the system will then choose to play smoothly onward.

2. Adjust the parameter “Pose Jump Threshold Time” in MM Animation Node.

To prevent the system from frequently switching animations due to minor advantages: if the best pose found in the Search is not beyond the Pose Jump Threshold Time from the current pose, then do not perform a pose jump—instead, continue playing the animation from the current pose.

3. Adjust the parameter “Pose Reselect History” in MM Animation Node.

Ignore any poses that have been selected within the last seconds of reselection history.

4. Check the channel weights.

If the stuck sequence contains motion data, they can moderately increase the weight of the velocity channel.I think there are likely many other ways to achieve the goal, such as increasing the number of sampling samples or the sampling frequency to give the system more options, or making targeted adjustments to the trajectory and rotation/displacement data of the stuck sequence.

Additionally, I think an important point is that each project develops its own PoseSearch strategies and parameters, and animation assets also differ. When such issues occur, using Rewind Debugger to record the state at the moment of the problem and analyzing the debug information to understand why the system performed a jump can help they better comprehend and fine-tune it.

Dustin

[Attachment Removed]