Forum rules - please read before posting.

Making a slider that controls ambiance or music tracks playback

Hi, I'm trying to create a slider that lets players control the playback of ambience or music tracks.

I've got an AC menu with a slider linked to a Unity slider and a custom script. The AC slider controls a float variable.

I can make it work with with game objects with the following script. But can't seem to work out how to hook it up to music or ambiance tracks!

audioSource = FindObjectOfType<AudioSource>(); 

        if (audioSlider != null)
        {
            audioSlider.maxValue = audioSource.clip.length;
            audioSlider.value = audioSource.time; // Initialize slider value with the current time of audio

            audioSlider.onValueChanged.AddListener(OnSliderValueChanged);
        }
    }

    void Update()
    {
        if (audioSource.isPlaying)
        {
            audioSlider.value = audioSource.time;
        }
    }

Is my setup wrong?

Comments

  • The AudioSource of Music and Ambience tracks respectively can be gotten with:

    KickStarter.stateHandler.GetMusicEngine ().audioSource;
    KickStarter.stateHandler.GetAmbienceEngine ().audioSource;
    
  • Thanks so much. Unfortunately, I'm a bit stuck with my custom scripts (I am not a developer).

    This AI-written script does everything right, but I am struggling to make the slider stretch based on the length of the audio clip!

    using UnityEngine;
    using UnityEngine.UI;
    using AC;
    
    public class AudioPlayerSlider : MonoBehaviour
    {
        public Slider audioSlider; // The Unity UI Slider to control audio playback
        private AudioSource audioSource;
    
        void Start()
        {
            // Find the Sound component in the scene (this will be used by Adventure Creator)
            Sound sound = FindObjectOfType<Sound>();
    
            // Check if the Sound component and the Slider are assigned
            if (sound != null && audioSlider != null)
            {
                // Assign the AudioSource from the Sound component
                audioSource = sound.audioSource;
    
                // Ensure the AudioSource has a valid AudioClip
                if (audioSource.clip != null)
                {
                    // Set the maximum value of the slider to the length of the audio clip
                    audioSlider.maxValue = audioSource.clip.length;
    
                    // Initialize the slider value with the current time of the audio
                    audioSlider.value = audioSource.time;
    
                    // Add a listener to the slider to handle changes in the value
                    audioSlider.onValueChanged.AddListener(OnSliderValueChanged);
                }
                else
                {
                    Debug.LogError("AudioSource does not have a valid AudioClip.");
                }
            }
            else
            {
                Debug.LogError("Sound component or Slider not assigned.");
            }
        }
    
        void Update()
        {
            // If the audio is playing, update the slider value with the current playback time
            if (audioSource != null && audioSource.isPlaying)
            {
                audioSlider.value = audioSource.time;
            }
        }
    
        // This method will be called when the slider value is changed by the user
        private void OnSliderValueChanged(float value)
        {
            if (audioSource != null)
            {
                // Set the audio playback time based on the slider value
                audioSource.time = value;
            }
        }
    }
    
  • As in, it's physical size? That's a case of affecting the slider's RectTransform sizeDelta value, i.e.:

    audioSlider.GetComponent<RectTransform> ().sizeDelta
    
  • edited March 29

    Sorry, I wasn't super clear about the issue (note that I'm not using the slider to control music anymore, but to control audio clips played using the Sound > Play action list).

    The slider works fine and the player can click it to "scrub" the audio. But it only works with the latest sound object I add to the scene.

    If I only have one sound object in the scene, I can get the slider to work on multiple clips by playing sounds using Sound > Play > New clip, but the min and max values are still linked to the length of the original audio resource.

    I feel like I'm missing something to get the right length of the audio clip - and/or to detect the right clip that is playing. Is that something AC should be able to do?

  • It's not due to AC. Your script is setting the min/max values in the Start function - i.e. when the scene begins.

    Detecing the "right clip that is playing" is open ended - multiple clips can play at the same time, technically. Are you looking to just affect the most recent to start? You can hook into the OnPlaySound event to extract it there instead of Start.

    That is, replace:

    void Start ()
    

    with:

    void OnEnable () => EventManager.OnPlaySound += OnPlaySound;
    void OnDisable () => EventManager.OnPlaySound -= OnPlaySound;
    
    void OnPlaySound (Sound sound, AudioSource _audioSource, AudioClip audioClip, float fadeInTime)
    
  • Yes! Thank you so much for the support!

    Full updated script in case anyone else wants to achieve something similar:

    using UnityEngine;
    using UnityEngine.UI;
    using AC;
    
    public class AudioPlayerSlider : MonoBehaviour
    {
        public Slider audioSlider; // The Unity UI Slider to control audio playback
        private AudioSource[] audioSources; // Array of AudioSources
    
        // Subscribe to the event to listen for when a sound is played
        void OnEnable () => EventManager.OnPlaySound += OnPlaySound;
    
        void OnDisable () => EventManager.OnPlaySound -= OnPlaySound;
    
        // This method is called when a sound is played
        void OnPlaySound(Sound sound, AudioSource _audioSource, AudioClip audioClip, float fadeInTime)
        {
            // Check if we have an active audio source to work with
            if (_audioSource != null)
            {
                // Initialize the audioSources array with only one audio source (if needed, or multiple if handling more)
                audioSources = new AudioSource[1];
                audioSources[0] = _audioSource; // Assign the incoming audioSource to our array
    
                // Ensure the AudioSource has a valid AudioClip
                if (audioSources[0].clip != null)
                {
                    // Set the maximum value of the slider to the length of the audio clip
                    audioSlider.maxValue = audioSources[0].clip.length;
    
                    // Initialize the slider value with the current time of the audio
                    audioSlider.value = audioSources[0].time;
    
                    // Add a listener to the slider to handle changes in the value
                    audioSlider.onValueChanged.AddListener(OnSliderValueChanged);
                }
                else
                {
                    Debug.LogError("AudioSource does not have a valid AudioClip.");
                }
            }
            else
            {
                Debug.LogError("AudioSource is null in OnPlaySound.");
            }
        }
    
        // Update is called once per frame
        void Update()
        {
            // Ensure that audioSources is initialized before updating
            if (audioSources != null && audioSources.Length > 0)
            {
                // If any audio is playing, update the slider value with the current playback time
                foreach (var audioSource in audioSources)
                {
                    if (audioSource != null && audioSource.isPlaying)
                    {
                        // Update the slider value to reflect the current audio time
                        audioSlider.value = audioSource.time;
                    }
                }
            }
        }
    
        // This method will be called when the slider value is changed by the user
        private void OnSliderValueChanged(float value)
        {
            if (audioSources != null && audioSources.Length > 0)
            {
                foreach (var audioSource in audioSources)
                {
                    if (audioSource != null)
                    {
                        // Set the audio playback time based on the slider value
                        audioSource.time = value;
                    }
                }
            }
        }
    
        // Optionally, remove the listener when the component is destroyed to avoid memory leaks
        private void OnDestroy()
        {
            if (audioSlider != null)
            {
                audioSlider.onValueChanged.RemoveListener(OnSliderValueChanged);
            }
        }
    }
    
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Welcome to the official forum for Adventure Creator.