Setting "Should Match Sync Phases" to true in blendspace asset causes it to play in-place

Hi,

I am trying to use a blendspace with motion matching and when trying to add my blendspace to my pose search database, it mentioned that “Should Match Sync Phases” should be enabled in my blendspace. I did so and also made sure that marker order and count matches in my blendspace samples. Motion matching works but the blendspace plays in-place.

I investigated this issue a bit myself and I noticed that even if I play the blendspace without motion matching, it plays in-place if “Should Match Sync Phases” is set to true, but it plays fine if I disable it. I looked in the code a bit and noticed that there’s a bit in UBlendSpace::TickAssetPlayer that calls UBlendSpace::ResetBlendSamples:

Inside UBlendSpace::ResetBlendSamples, both LeaderSampleData.Time and LeaderSampleData.PreviousTime are set to the same value and it stays the same when you exit ResetBlendSamples:

After that bHasDeltaTime is set to true because NormalizedCurrentTime and NormalizedPreviousTime have different values, but CurrentSampleDataTime and PrevSampleDataTime end up having the same value because SampleEntry.Time and SampleEntry.PreviousTime share the same value after aforementioned ResetBlendSamples call:

This causes DeltaTimePosition to be set to 0, and even though bHasDeltaTime is true, ExtractRootMotion is called with 0 DeltaTime, so it doesn’t update RootMotionParams and the blendspace plays in-place:

One final thing to mention is that this issue happens even if I add a single sample to my blendspace. Do you know what might be going on here?

Thanks,

Maryam

Hi Maryam, thanks for letting us know about this. It looks like this bug has been there since the ‘Should Match Sync Phases’ codepath was added. That was required to support deterministic sampling of blendspace assets so blendspaces could be properly supported by motion matching. That’s why that codepath resets the playback position as you’ve seen, and as you also noted, it resets the PreviousTime which breaks the delta time calculation for root motion.

I have a potential quick fix for this that just reinstates the old PreviousTime after the reset. I’m just waiting to get that reviewed by the dev team, if they’re okay with it then I’ll send it over soon.

Thanks,

Euan

Hi Maryam, the dev team took a look at the changes I have and are happy with them, at least as a workaround for the issue. The CL with the change is 56887712, and I’ve attached a patch file as well.

In terms of not setting the flag when each sample has the same number of sync markers, I would have to dig through the code to say for sure, but I would be worried that you could still get into situations where a pose on a given frame is affected by the previous frame, which is what shouldn’t be able to happen with Should Match Sync Phases.

Let me know how you get on with the changes.

Thanks,

Euan

ShouldMatchSyncPhases_RootMotionFix_5.8.patch.zip(534 Bytes)

Thanks Maryam, that actually makes a lot more sense as to what happened. Speaking with the team, it seems the change to the property was made after we copied the GASP project out of the working directory that we have internally in P4. But we didn’t then later copy the project back to our internal folder, which is why we have the discrepancy. As you noticed, the animations do use sync markers (I must have removed these when I was testing locally), so it makes sense that the flag would have been disabled, as it causes issues with that blendspace even if they are less noticeable than with yours. So we’ll need to fix the bug before we can update the property in GASP.

I’m going to go back to the dev team this week to discuss what we can do to fix this issue. Do you want me to keep this thread open, or are you happy to follow any progress via the JIRA tracker?

Thanks,

Euan

Great, thanks. I’ll close this one out in that case. Thanks again for the feedback on this

Hi Euan. Thanks for getting back to my inquiry.

We also noticed that if we don’t set ‘Should Match Sync Phases’ to true in our blendspace (but have each sample have the same number of sync markers in the same order), and ignore the warning in pose search database about the blendspace’s ‘Should Match Sync Phases’ flag, MM works for the blendspace and the blendspace plays correctly too. But it would be preferrable to have an official fix from Epic, so thank you for chasing it.

Kind regards,

Maryam

Hello Euan. Thank you for getting back to me with a patch. The file only contains this:

Change 56887712 by euan.carmichael@euan.carmichael_Release-5.8_MZ026ZMB on 2026/08/12 21:16:04 *pending*
 
	Possible fix for issue where generated root motion is invalid when a blend space is running with the bShouldMatchSyncPhases set
	
	#ushell-cherrypick of 56677472 by euan.carmichael
 
Shelved files ...
 
 
Differences ...

Would you mind sending me another patch that contains the changes, please?

Also, I am not sure I understand what you mean by “I would be worried that you could still get into situations where a pose on a given frame is affected by the previous frame, which is what shouldn’t be able to happen with Should Match Sync Phases.”. Do you mind elaborating that a bit more, please?

Kind regards,

Maryam

Hi, sorry about that, looks like I still had the changes shelved when I made the patch. I’ve reattached it.

> Do you mind elaborating that a bit more, please?

Sure, historically, the problem with using blendspaces for motion matching is that the output of a blendspace isn’t deterministic based on the input. You can end up with a different pose for a given input due to a few factors. And that’s a problem, since when we index assets in the PSD, we assume they produce a deterministic pose given the input.

One of the issues is with how the time update propagates to the different samples within the blendspace. Previously, you could get varying results depending on the follower samples’ previous frame time relative to the lead sample. bShouldMatchSynchPases should prevent this from happening, since the playback time for each sample is reset each frame, and then an absolute update sets the current time for this frame based on the leader’s position.

The other issue with blendspaces is smoothing. If the input to the blendspace is being smoothed, the output pose won’t match what was generated when we indexed the blendspace in the PSD. So you should also turn this off on your blendspace.

Let me know if you’ve got any questions on this.

Thanks,

Euan

ShouldMatchSyncPhases_RootMotionFix_5.8.patch.zip(1.28 KB)

Hi Euan,

Thanks for sending the new patch and explaining the nondeterministic pose issue that can happen without bShouldMatchSynchPases.

I applied your patch and also turned off smoothing on my blendspace. I assume this is what you meant?

I’m asking because I interpolate my blendspace’s input parameter before feeding it to my Blendstack player node, but I suppose that’s OK?

So having added your changes + enabling ShouldMatchSyncPhases + turning off Smoothing inside my blendspace, the play in-place issues disappears, but I get a new issue where my character jumps forward sometimes. I looked into this a bit and I noticed that when it happens, PrevSampleDataTime is greater than CurrentSampleDataTime (equivalent to a frame time, e.g. 0.03s), so DeltaTimePosition becomes negative and the following code triggers:

// if we went against play rate, then loop around.
if ((SampleMoveDelta * DeltaTimePosition) < 0.f)
{
	DeltaTimePosition += FMath::Sign<float>(SampleMoveDelta) * Sample.GetSamplePlayLength();
}

which causes DeltaTimePosition to become lead animation length - 0.03s, which is quite large and causes the character to jump forward. Skimming through the code, I couldn’t figure out why it happens. Maybe you have a clue why it might be happening?

Many thanks,

Maryam

Hi Maryam,

>I applied your patch and also turned off smoothing on my blendspace. I assume this is what you meant?

>I’m asking because I interpolate my blendspace’s input parameter before feeding it to my Blendstack player node, but I suppose that’s OK?

Yeah, smoothing the inputs to the blendspace is fine, since the logic within the blendspace will still give a deterministic output based on whatever your smoothed input parameters are. Also, we touched a little on using blendspaces with motion matching in this section of the latest GASP livestream. There’s not a whole load of extra information in there but I thought it might be of interest.

> So having added your changes + enabling ShouldMatchSyncPhases + turning off Smoothing inside my blendspace, the play in-place issues disappears, but I get a new issue where my character jumps forward sometimes. I looked into this a bit, and I noticed that when it happens, PrevSampleDataTime is greater than CurrentSampleDataTime (equivalent to a frame time, e.g. 0.03s), so DeltaTimePosition becomes negative and the following code triggers

Ok, that sounds like a bug with my changes. Is there any specific behaviour that allows that looping code to be triggered consistently - for instance, does it maybe happen when the lead sample within the blendspace changes to one of the samples that was previously a follower? Or is it not predictable/consistent?

Thanks,

Euan

Hi Euan,

Thanks for sharing the link to GASP livestream. I watched some of it over the weekend but haven’t had time to watch all of it yet. I haven’t seen the blendspace bit yet but I noticed they mentioned they have added it, so I was curious how it works in GASP without the bugs that I am seeing!

> Is there any specific behaviour that allows that looping code to be triggered consistently - for instance, does it maybe happen when the lead sample within the blendspace changes to one of the samples that was previously a follower? Or is it not predictable/consistent?

You’re spot-on with your guess as to when it happens. I printed out the name of the leader sample, and the bug consistently happens when the leader sample changes to another one that used to be a follower. I hope this helps!

Kind regards,

Maryam

Thanks, yeah, that makes sense that it would happen when the leader sample changes. I’ve attached a patch with revised changes which don’t generate a delta on the frames when the leader switches. That should at least get rid of the discontinuity in root motion.

However, this new absolute-time update codepath will be more prone to discontinuities than the old codepath when performing sync marker-based blending, as the followers’ positions can move forward or backwards when the leader changes.

In practice, I’m not sure how bad this will be. But with a synthesised repro where you have two sync markers, the first at 0% of both animations and the second at 10% of one animation and 90% of the other, the pop-in pose is going to be quite noticeable. With a real-world example in which the sync markers are similarly distributed in all animations, it should be less noticeable.

The other thing with this is that you may not see a pop at all when you use the blendspace with the motion-matching node. When the parameter inputs change for a blendspace in motion matching, the blendspace is re-added as a new layer within the internal motion matching node’s blendstack, and that results in a blend being performed, which may hide any pop.

Anyway, let me know how the root motion looks with the updated patch. And assuming it gets things working, I’d be interested to know how good the setup looks when you use it with the motion-matching node.

Thanks,

Euan

ShouldMatchSyncPhases_RootMotionFix_5.8.patch.zip(1.56 KB)

Hi Euan,

Thanks for sending me an updated fix. I tried it and it fixes the large deltatime issue. However, the blend is not smooth when lead animation changes. It’s also not smooth when blending between the blendspace and other anims.

One thing to mention about my setup is that I am not using the motion matching node. I have a chooser where I decide what anim/blendspace should be played and only when the chooser result changes, I use motion match function to find the frame I should start playing the new anim/blendspace from. I use a blendstack player as it allows me to play both sequences and blendspaces. Therefore, in my case, the pops are visible because the blendspace doesn’t get re-added as a new layer each frame.

I watched GASP video about blendspace addition to MM and I also downloaded the project and looked at the files. I noticed that the blendspace used with MM in that project (BS_Relaxed_Run_Loop_F_Slopes) has ShouldMatchSyncPhases disabled and Smoothing enabled:

And the warning about ShouldMatchSyncPhases not being enabled for that blendspace shows up in its associated PSD too:

So, I am guessing if this is how they have got blendspaces working for GASP, it should be okay for us to use our blendspace without enabling ShouldMatchSyncPhases too (as I mentioned in one of my previous posts that when we don’t enable this flag, our blendspace plays fine and motion matching into it works correctly too)?

Many thanks,

Maryam

Hi Maryam,

> So, I am guessing if this is how they have got blendspaces working for GASP, it should be okay for us to use our blendspace without enabling ShouldMatchSyncPhases too (as I mentioned in one of my previous posts that when we don’t enable this flag, our blendspace plays fine and motion matching into it works correctly too)?

Thanks for flagging this, it’s actually an oversight in the release. The ShouldMatchSyncPhases is set on that asset in our release-5.8 branch, but somehow it didn’t make it into the assets for the sample upload. In practice, it doesn’t really make a difference to the behaviour. None of those animations contain sync markers so aren’t affected by that codepath. But I’ll see if it’s possible to get the assets updated to remove the error text.

> One thing to mention about my setup is that I am not using the motion matching node. I have a chooser where I decide what anim/blendspace should be played and only when the chooser result changes, I use motion match function to find the frame I should start playing the new anim/blendspace from. I use a blendstack player as it allows me to play both sequences and blendspaces. Therefore, in my case, the pops are visible because the blendspace doesn’t get re-added as a new layer each frame.

It sounds like your setup is something like this, where the animation asset input is being changed to the blendspace:

Assuming that’s the case, you can still have the blendstack perform a blend when the blendspace parameters change. It’s controlled via the BlendParametersDeltaThreshold property that I highlighted. So, for instance, if you set that to 0, any change of a blendspace parameter will trigger a new layer being added to the stack. But I’ve tested this, and while it makes the discontinuities a little less obvious, it’s still not great, and I found that the blending could introduce other issues.

Unfortunately, I don’t think we have a good solution for this at the moment. If you want to go down the route of using blendspaces, you’re probably best to just risk the non-determinism with ShouldMatchSyncPhases disabled for now. But you may occasionally get incorrect poses vs what motion matching expects.

I’ll go back to the dev team on this to get it escalated as it’s pretty clear the new flag isn’t really functional to fix the determinism issue. I’ve also created a bug ticket that you can follow here.

Thanks,

Euan

Hi Euan,

Thanks for looking into this and creating a bug ticket for it. I’ll take it up with our team what you have just explained and we’ll make an informed decision.

Just one thing to point out regarding the anims used in GASP blendspace example: you said “In practice, it doesn’t really make a difference to the behaviour. None of those animations contain sync markers so aren’t affected by that codepath”. But I checked them and they do. This is a screenshot of one of the anims:

In fact, if I enable ShouldMatchSyncPhases for that blendspace in GASP, I see some funny artifacts when running on slopes and turning the camera; nothing like a pop, more like sliding and the character not turning. I would have shared a video if it was possible to do so here.

Kind regards,

Maryam

Hi Euan,

Thanks for the clarification. I am happy for you to close this thread. I will follow the JIRA tracker.

Kind regards,

Maryam