Repository navigation
[Enhancement] Add animation playback helpers for synchronized gameplay - #1316
Merged
Merged
Conversation
Adds restartAnimation, getAnimationPlaybackTime, and sampleAnimationJointPosition so callers can replay a one-shot clip from time zero, read its current playback time, and sample a named joint in world space at an arbitrary time without changing the displayed pose. ClipSampler.sample() also unconditionally wrapped time via fmod, even for clips whose channels were flagged non-repeating, defeating the per-channel hold-last-pose logic and causing a completed one-shot clip to jump back to its initial pose. It now clamps to [0, duration] when no animated channel repeats, and only wraps for repeating clips. restartAnimation preserves warmed compiled-pose caches unless the clip's looping configuration actually changes. Fixes #1314.
applyRootMotion computed its own channelTime via fmod(currentTime, clipDuration), unconditionally, regardless of whether the clip's channels repeat. Once currentTime passed a non-repeating clip's duration, this wrapped back near zero, which wrappedChannelTime then misread as a fresh loop and injected a full loop's root displacement at that instant -- a visible snap right as a one-shot animation (e.g. a kick) finished, even though ClipSampler already holds the displayed pose correctly past that point. Match ClipSampler: clamp to [0, duration] when no animated channel repeats, only wrap when at least one does.
untoldengine
force-pushed
the
enhancement/1314
branch
from
October 7, 2026 13:09
5d61334 to
f3422f9
Compare
3 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
restartAnimation,getAnimationPlaybackTime, andsampleAnimationJointPositionso callers can replay a one-shot clip from time zero, read its current playback time, and sample a named joint in world space at an arbitrary time without changing the displayed pose.ClipSampler.sample()unconditionally wrapping time viafmod, even for clips whose channels are flagged non-repeating — this defeated the existing per-channel hold-last-pose logic and caused a completed one-shot clip (e.g. a kick) to jump back to its initial pose. Non-repeating clips now clamp to[0, duration]; repeating clips still wrap as before.restartAnimationpreserves warmed compiled-pose caches unless the clip's looping configuration actually changes.Fixes #1314.
Test plan
swift buildswift test --filter AnimationCompiledSamplerTests— 18/18 pass, including the 4 new tests (final-pose holding, restart reset/rearm, contact-joint world-space sampling without disturbing playback, compiled-cache preservation/invalidation)swift test --filter "AnimationSystemTest|FootIK|MotionMatching|PoseLayer|RootMotion|MLDeformer"— 70/70 passswift test --filter UntoldEngineTests(full unit target) — 1628/1628 pass (2 pre-existing skips)