Slider isn't moving smoothly. (Unity3d)

1k Views Asked by At

I have an audio clip and a slider. The slider is acting as a progress bar (Timeline) for the audio clip. I can pause and play the audio also I can skip the track as well. Everything is working fine. The problem is slider isn't moving smoothly it's kinda jittery. Please edit it if somebody can. Thanks in advance.

Here is the code:

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

public class MusicPlayer : MonoBehaviour
{
    AudioSource audioSource;
    Slider slider;
    public AudioClip track;

    // Start is called before the first frame update
    void Start()
    {
        audioSource = GetComponent<AudioSource>();
        slider = GetComponent<Slider>();

        audioSource.clip = track;
        audioSource.Play();

        slider.minValue = 0;
        slider.maxValue = track.length;
    }

    // Update is called once per frame
    void Update()
    {
        slider.value = audioSource.time;
        
    } 

    public void MovePoition()
    {
        audioSource.time = slider.value;
    }

    public void play()
    {
        audioSource.Play();
    }

    public void pause()
    {
        audioSource.Pause();
    }

}
1

There are 1 best solutions below

15
On

On Update, ensure smoothness by using Time.deltaTime to update the slider's value if it is playing. Otherwise, and also in play and pause, re-sync the position with the playtime.

However, you need to avoid the callback when setting the value. Create an empty event at Start and assign it to the slider when updating the value.

Finally, add a flag to keep track of if the track should be playing. This prevents the source from stopping when the end of the clip is played then the slider is dragged.

After setting the source time in MovePoition, depending on the compression of the clip, it might not be able to set to the exact value the slider has. So, you should re-update the slider value with the time that the audio source decides to use.

Altogether:

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

public class MusicPlayer : MonoBehaviour
{
    AudioSource audioSource;
    Slider slider;
    Slider.SliderEvent emptyEvent;
    public AudioClip track;
    private bool isPaused;
    private bool needSync;

    // Start is called before the first frame update
    void Start()
    {
        audioSource = GetComponent<AudioSource>();
        slider = GetComponent<Slider>();

        audioSource.clip = track;
        audioSource.Play();

        slider.minValue = 0;
        slider.maxValue = track.length;

        emptyEvent = new Slider.SliderEvent();
    }

    void SetSliderWithoutCallback(float time) 
    {
        Slider.SliderEvent temp = slider.onValueChanged;
        slider.onValueChanged = emptyEvent;
        slider.value = time;
        slider.onValueChanged = temp;
    }

    // Update is called once per frame
    void Update()
    {
        if (audioSource.isPlaying) 
        {
            float newTime = Mathf.Min(slider.value + Time.deltaTime, slider.maxValue);
            SetSliderWithoutCallback(newTime);
        } 
        else if (!isPaused)
        {
            SetSliderWithoutCallback(slider.maxValue);
            isPaused = true;
        }
    } 

    public void MovePoition()
    {
        audioSource.time = slider.value;
        if (!isPaused) 
        {
            audioSource.Play();
            SetSliderWithoutCallback(audioSource.time);
        }
    }

    public void play()
    {
        audioSource.Play();
        isPaused = false;
        SetSliderWithoutCallback(audioSource.time);
    }

    public void pause()
    {
        isPaused = true;
        audioSource.Pause();
        SetSliderWithoutCallback(audioSource.time);
    }

}