简体   繁体   中英

Unity slider controlling animation

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

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.

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.

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM