From 7f170deb27a5c78f7034e0b3cab9a34ae4af652f Mon Sep 17 00:00:00 2001 From: Kah Wei Date: Thu, 9 Mar 2023 15:46:15 +0800 Subject: [PATCH] Fixed animations not playing from the correct start point --- Assets/Scripts/AnimTest.cs | 17 ++++++++++++----- SHADE_Engine/src/Animation/SHAnimationClip.cpp | 5 ++++- SHADE_Engine/src/Animation/SHAnimationClip.h | 4 +++- .../src/Animation/SHAnimationController.cpp | 14 ++++++++++++-- .../src/Animation/SHAnimatorComponent.cpp | 8 +++++--- 5 files changed, 36 insertions(+), 12 deletions(-) diff --git a/Assets/Scripts/AnimTest.cs b/Assets/Scripts/AnimTest.cs index 324058b2..4ceccbe6 100644 --- a/Assets/Scripts/AnimTest.cs +++ b/Assets/Scripts/AnimTest.cs @@ -1,4 +1,6 @@ -namespace SHADE.Test +using System; + +namespace SHADE.Test { public class AnimTest : Script { @@ -25,21 +27,26 @@ protected override void update() { + // Play loop if shift is held + Action playFunc = Input.GetKey(Input.KeyCode.LeftShift) ? (x) => Animator.Play(x) + : (x) => Animator.PlayOneShot(x); + + // Play animations if (Input.GetKeyUp(Input.KeyCode.Equals)) { - Animator.Play(fullClip); + playFunc(fullClip); } else if (Input.GetKeyUp(Input.KeyCode.Alpha1)) { - Animator.Play(idleClip); + playFunc(idleClip); } else if (Input.GetKeyUp(Input.KeyCode.Alpha2)) { - Animator.Play(runClip); + playFunc(runClip); } else if (Input.GetKeyUp(Input.KeyCode.Alpha3)) { - Animator.Play(pickUpClip); + playFunc(pickUpClip); } } #endregion diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.cpp b/SHADE_Engine/src/Animation/SHAnimationClip.cpp index 130503af..b4a62651 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationClip.cpp @@ -25,11 +25,14 @@ namespace SHADE , startFrameIndex { firstFrame } , endFrameIndex { lastFrame } , duration { 0.0f } + , startTimeStamp { 0.0f } { if (!rawAnim) return; + const float SECS_PER_TICK = 1.0f / static_cast(rawAnim->GetTicksPerSecond()); const int ONE_PAST_LAST_FRAME = lastFrame + 1; - duration = (ONE_PAST_LAST_FRAME - firstFrame) / rawAnim->GetTicksPerSecond(); + duration = static_cast(ONE_PAST_LAST_FRAME - firstFrame) * SECS_PER_TICK; + startTimeStamp = static_cast(firstFrame) * SECS_PER_TICK; } } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationClip.h b/SHADE_Engine/src/Animation/SHAnimationClip.h index 9de621d0..6b97c955 100644 --- a/SHADE_Engine/src/Animation/SHAnimationClip.h +++ b/SHADE_Engine/src/Animation/SHAnimationClip.h @@ -50,6 +50,7 @@ namespace SHADE inline int GetStartFrameIndex() const noexcept { return startFrameIndex; } inline int GetEndFrameIndex() const noexcept { return endFrameIndex; } inline float GetTotalDuration() const noexcept { return duration; } + inline float GetStartTimeStamp() const noexcept { return startTimeStamp; } private: /*---------------------------------------------------------------------------------*/ @@ -58,6 +59,7 @@ namespace SHADE Handle rawAnim; int startFrameIndex; // First Frame int endFrameIndex; // Last Frame (inclusive) - float duration; // Total playback time + float duration; // Total playback time + float startTimeStamp; // Starting time stamp of the raw anim }; } \ No newline at end of file diff --git a/SHADE_Engine/src/Animation/SHAnimationController.cpp b/SHADE_Engine/src/Animation/SHAnimationController.cpp index 9b7b6de2..8152426f 100644 --- a/SHADE_Engine/src/Animation/SHAnimationController.cpp +++ b/SHADE_Engine/src/Animation/SHAnimationController.cpp @@ -65,18 +65,21 @@ namespace SHADE instData.ClipPlaybackTime += dt; // Check if we finished playing - if (instData.ClipPlaybackTime > instData.CurrentNode->Clip->GetTotalDuration()) + const float CLIP_CURR_PLAYED_TIME = instData.ClipPlaybackTime - instData.CurrentNode->Clip->GetStartTimeStamp(); + if (CLIP_CURR_PLAYED_TIME > instData.CurrentNode->Clip->GetTotalDuration()) { // Clamp - instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetTotalDuration(); + instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp() + instData.CurrentNode->Clip->GetTotalDuration(); // Go to next state + bool stateChanged = false; for (const auto& transition : instData.CurrentNode->Transitions) { // Check for no condition special case if (transition.Condition == Transition::ConditionType::None) { changeNode(instData, transition.Target); + stateChanged = true; break; } else @@ -90,6 +93,7 @@ namespace SHADE if (transition.EvaluateCondition(param)) { changeNode(instData, transition.Target); + stateChanged = true; // If trigger, we need to unset it if (param.ParamType == AnimParam::Type::Trigger) @@ -101,6 +105,12 @@ namespace SHADE } } } + + // Handle if there is no next state, we repeat + if (!stateChanged) + { + instData.ClipPlaybackTime = instData.CurrentNode->Clip->GetStartTimeStamp(); + } } } diff --git a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp index 7d4a2765..d21ee5e1 100644 --- a/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp +++ b/SHADE_Engine/src/Animation/SHAnimatorComponent.cpp @@ -62,6 +62,7 @@ namespace SHADE { // Calculate secs for the clip secsPerTick = 1.0f / RAW_ANIM->GetTicksPerSecond(); + currPlaybackTime = currClip->GetStartTimeStamp(); // Start playback Play(); @@ -232,17 +233,18 @@ namespace SHADE void SHAnimatorComponent::updateManualClipState(float dt) { currPlaybackTime += dt; - if (currPlaybackTime > currClip->GetTotalDuration()) + const float CLIP_CURR_PLAYED_TIME = currPlaybackTime - currClip->GetStartTimeStamp(); + if (CLIP_CURR_PLAYED_TIME > currClip->GetTotalDuration()) { if (playOnce) { playOnce = false; isPlaying = false; - currPlaybackTime = currClip->GetTotalDuration(); + currPlaybackTime = currClip->GetStartTimeStamp() + currClip->GetTotalDuration(); } else { - currPlaybackTime = currPlaybackTime - currClip->GetTotalDuration(); + currPlaybackTime = currClip->GetStartTimeStamp(); } } }