4

I'd like to create a slider that displays the current frame of an animation within unity, and when you move the slider it updates the current frame within the animation.

So far I have (edited code)

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class NewAnimController : MonoBehaviour {


public Slider sliderScrubber;
public Animator animator;


void Start()
{
    float t = animator
    .GetCurrentAnimatorStateInfo(0)
    .normalizedTime;


    //animator.speed = 0.0001f;
    //slider.onValueChanged.AddListener(OnValueChanged);
}

public void Update()
{
    float animationTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
    Debug.Log("animationTime (normalized) is " + animationTime);
    sliderScrubber.value = animationTime;
}

public void OnValueChanged(float changedValue)
{
    animator.speed = 0.0001f;
    animator.Play("Take 001", -1, sliderScrubber.normalizedValue);
}
}

At the moment this changes the current frame in the animation when you adjust the slider, but when the animation is played, the slider doesn't update.

How can I get this to work in both directions?

Many thanks

Fattie
  • 27,874
  • 70
  • 431
  • 719
Tim Hanson
  • 251
  • 1
  • 5
  • 17

3 Answers3

2

First be sure to delete all code lines

animation.speed = 0.0001f

which appear to be leftover from a tutorial or debugging.


What about

public void Update()
 {
 float animationTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
 // in case of a looping anime, animationTime = animationTime %1f;

 Debug.Log("animationTime is " + animationTime);
 // of course remove that in production

 slider.value = animationTime;
 }

Note of course set the scrubber min/max to 0f, 1f in the editor.

Note, you may prefer to make a "scrubber" for a joint position; also works nice.

Note, subtle issue: experienced programmers may prefer to set the animation speed to zero, while the user's finger is holding down the slider; probably OK without doing this.


NOTE take care to delete all references to animation.speed. It apears to be a carry-over from an incorrect tutorial.

Fattie
  • 27,874
  • 70
  • 431
  • 719
  • 1
    That is correct, then I've made the slider go from 0 - 1, and made `slider.value = animationTime;` worked fine, I just needed to update the speed of animation playback otherwise it played back much too slowly. I'm about to write a slider into it that can change the playback speed, but for the original code `animation.speed = 0.0001f` was much too slow to see if it was even working. I got this original value from the code I found in the first place. – Tim Hanson Feb 02 '16 at 14:51
  • Ahhh! ok, just totally delete that line `animation.speed = 0.0001f` it's silly! – Fattie Feb 02 '16 at 15:27
  • 1
    Yeah I've got it all working perfectly well now thanks for your help. – Tim Hanson Feb 04 '16 at 09:34
  • I was only ticking the answer that answered the question straight away just in case anyone else had the same issue so they could get things working as fast as possible. – Tim Hanson Feb 04 '16 at 12:16
1

Ok, so after much throwing things around to see what sticks, this is giving me the result I'm after.

I'd like to thank @JoeBlow for all his help.

Somebody buy that guy a drink.

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class NewAnimController : MonoBehaviour {

public Slider sliderScrubber;
public Animator animator;   

public void Update()
{
    float animationTime = animator.GetCurrentAnimatorStateInfo(0).normalizedTime;
    Debug.Log("animationTime (normalized) is " + animationTime);
    sliderScrubber.value = animationTime;
}

public void OnValueChanged(float changedValue)
{
    animator.Play("Take 001", -1, sliderScrubber.normalizedValue);
}
}

I will update this again when I have a play pause button working and a slider that can change the speed of playback.

Tim Hanson
  • 251
  • 1
  • 5
  • 17
0

I think you almost got it just instead of assigning the value directly in the update function:

sliderScrubber.value = animationTime;

Use this:

sliderScrubber.Set(animationTime, false);

the false parameter is to call the OnValueChange() function in your case you don't want that.

Addionally you can check if the animation is being played to avoid unnecesary calls to the Set function:

http://answers.unity3d.com/questions/362629/how-can-i-check-if-an-animation-is-being-played-or.html

and check your slider.maxValue to adjust it to the animation length.

Myke Dev
  • 180
  • 9