Consider a blend space like this:
Each grid point contains a sample weight calculated using
[Delaunay Triangulation](https://en.wikipedia.org/wiki/Delaunay_triangulation), and this is calculated offline.
For a given (x, y) coordinate, its final weight is calculated using bi-linear interpolation in the rectangle this coordinate locates in:
You may see varying animatino length if you call
UBlendSpaceBase::GetAnimationLengthFromSampleData because the
BlendSpace node is synchronizing playback of the source animation clips within it.
For example, if you have one animation clip that is 1.0 seconds in length being blended in a
BlendSpace with another clip that is 0.5 in length, when the weight of the
BlendSpace is 50% between the two source clips, the value returned from
GetAnimationLengthFromSampleData() will be 0.75.
The playback rate of each animation clip is then scaled to match this weighting. Consider a
BlendSpace like this:
If the delta time of current frame is 0.25s. In order to synchronize all animations, the playback rate of each animation clip is scaled in accordance with the normalized delta time.
Oh and by the way, each blend space holds the normalized time as when dealing with changing anim length, it would be possible to go backwards. As a result, the playback of each animation clip is set by:
CurrentSampleDataTime = SampleNormalizedCurrentTime * Sample.Animation->SequenceLength;
Sync marker in a blendspace is more complicated, compared to sync marker in an animation sequence.
In a blendspace, it will still sync even if only one node in sync group. So you’re never non-sync group unless you have situation where some markers are relevant to one sync group but not all the time.
Here we save NormalizedCurrentTime as Highest weighted samples’ position in sync group. If you’re not in sync group, NormalizedCurrentTime is based on normalized length by sample weights. If you move between sync to non sync within blendspace, you’re going to see pop because we’ll have to jump.
For now, our rule is to keep normalized time as highest weighted sample position within its own length. Also MoveDelta doesn’t work if you’re in sync group. It will move according to sync group position.