• Unity
  • Unity: Need to set a animation to a specific frame.

I have a animation of a fuel gauge.
I have it playing from full to empty over 100 frames of animation. Just a simple rotation.

In Unity I want set the gauge to a point given how much fuel you have. If I have 50% left then the gauge would be half way.

I have tried setting timeScale to zero and setting time to the frame I want.. but the animation is never updated to render the needle at that location.

Any advice or other things I could try?

  • Great Community .. thanks for the support..
  • Emblazed
Related Discussions
...

Try this:

int iTrack = s.Track; 
anim.state.SetAnimation(iTrack, s.Animation, (bool) s.Looping);
if (bReset) anim.skeleton.SetBonesToSetupPose();
anim.state.GetCurrent(iTrack).Time = anim.state.GetCurrent(iTrack).EndTime * fProgress;

I get movement in the animation but it jumps around.. not holding at any progress location...

I am calling this to insure that its being set to the desired time every frame.

Thoughts?

void SetTemp( int temp ) // called every update call..
{
   float fProgress = 0.5f; // For to 50% for testing.

   TrackEntry ti = m_FuelGauge.state.SetAnimation(0, "Fuel Gauge",  true ); // doesn't work if false/true
   m_FuelGauge.state.GetCurrent(0).Time = m_FuelGauge.state.GetCurrent(0).EndTime * fProgress;
}

  • Emblazed

Oh. You're trying to freeze the animation at a specific point.

have you tried

anim.timeScale = 0;

Set the anim and time

anim.skeleton.Update(0);
anim.state.Update(0);
anim.state.Apply(anim.skeleton);

I had tried that.. and after some tests and doing some stepping thru the Spine Runtime I found the problem.

When an animation is set it blends to its previous, . . so all I need to do is state.ClearTracks() before I set and lock down the time.

Here is the working code..

temp = Mathf.Min(Mathf.Max(fuel,0), 100);
float fProgress = (float)fuel / 100.0f;

m_FuelGauge.state.ClearTracks();

TrackEntry ti = m_FuelGauge.state.SetAnimation(0, "Fuel Gauge", false );

ti.Time = ti.EndTime  * fProgress;
ti.TimeScale = 0.0f;
  • Thanks for you help, your comments led to finding the location of the problem...
  • Emblazed

The right way to do this is to not use SkeletonAnimation.

Just use SkeletonRenderer and apply an Animation directly to it.

Im Sorry Mitch but I don't follow. Can you give me more information.

Thx

using UnityEngine;
using System.Collections;

[ExecuteInEditMode]
[RequireComponent(typeof(SkeletonRenderer))]
public class SpineGauge : MonoBehaviour{

   [Range(0,1)]
   public float fill = 0;

   [SpineAnimation]
   public string fillAnimationName;
   Spine.Animation fillAnimation;

   SkeletonRenderer skeletonRenderer;

   void Start () {
      skeletonRenderer = GetComponent<SkeletonRenderer>();
   }

   void Update () {
      
var skeleton = skeletonRenderer.skeleton; if (skeleton == null) return; if (fillAnimation == null) { fillAnimation = skeleton.Data.FindAnimation(fillAnimationName); if (fillAnimation == null) return; } fillAnimation.Apply(skeleton, 0, fill, false, null); skeleton.Update(Time.deltaTime); skeleton.UpdateWorldTransform(); } }

I've included an example Gauge that'll get pushed in the next Spine-Unity update as well.

You are a king among men..

Thanks..

-Emblazed

2 年 后

I am new to spine (old to Unity) and want to set a specific anim frame too. It's on my main character where they get into a state where I need to code select the frame they are in, but in other times I need full animation. I noticed the "better" solution doesn't use a Skeleton Animation so am I right in assuming I can't use it if I want other Animations to play normally? I've used Emblazed's solution and it works but was not sure if it was the best way to go.

Thanks

This question was answered in detail recently. Let me look for that thread.


25 Feb 2017 12:07 am


Here it is: Lerping an animation in code
It's framed slightly differently, but it's basically the same thing. You can a) work through AnimationState or b) work with Animation objects and the Skeleton directly. Since you need both normally-playing animations and go to a specific frame, then option A is probably best.

To rephrase from the post:
With AnimationState, when you set the animation, you set the TimeScale to 0 so the animation is paused and you can set the time yourself.

var trackEntry = skeletonAnimation.AnimationState.SetAnimation(0, "your animation", true);
trackEntry.TimeScale = 0f;

float animationTimeInSeconds = frameNumberInSpineDopesheet / 30f; // 30 means the default 30 frames per second dopesheet. Not render framerate.
trackEntry.TrackTime = animationTimeInSeconds;

Alternatively, you could also set the TimeScale on the SkeletonAnimation or AnimationState. It's up to you.
When you need the animation to resume, just set the TimeScale back to 1.

2 年 后

After a year and half, thank you Pharan!!