AudioRandomizer

If you would like to use a very basic AudioRandomizer, here ya go :stuck_out_tongue:
Add to your Damage Sound GameObject,
Link up the AudioSource,
Add in various desired clips,
Be sure to call the appropriate function on the appropriate script(this) in the Unity Event,
Magic!

using UnityEngine;

namespace RPG_2.Core
{
    public class AudioRandomizer : MonoBehaviour
    {
        [SerializeField] private AudioClip[] audioClips = null;
        
        private AudioSource audioSource = null;

        public void PlayRandomAudioClip()
        {
            if (audioClips != null)
            {
                int index = UnityEngine.Random.Range(0, audioClips.Length);
                var randomClip = audioClips[index];
                audioSource.PlayOneShot(randomClip);
            }  
        }

        private void Start()
        {
            audioSource = GetComponent<AudioSource>();
        }
    }
}
9 Likes

thank you!

Thank you very much very re-useable!

//Add this script to any GameObject that you want to have4 multiple sounds used on in a random way.

Great job!

I wonder what you guys think about that same AusioRandomizer
exposing a public void to playOneShot

using UnityEngine;

namespace RPG_2.Core
{
    public class AudioRandomizer : MonoBehaviour
    {
        //Add this script to any GameObject that you want to have4 multiple sounds used on in a random way.
        [SerializeField] private AudioClip[] audioClips = null;
        
        private AudioSource audioSource = null;

        public void PlayRandomAudioClip()
        {
            if (audioClips != null)
            {
                int index = UnityEngine.Random.Range(0, audioClips.Length);
                var randomClip = audioClips[index];
                audioSource.PlayOneShot(randomClip);
            }  
        }

        public void PlayAudioClip(int index)
        {
            if(index < 0 || index > audioClips.Length || audioClips == null) return;
            var clipToPlay = audioClips[index];
            audioSource.PlayOneShot(clipToPlay);
            // if (audioClips != null)
            // {
            //     //int index = UnityEngine.Random.Range(0, audioClips.Length);
            // }  
        }

        private void Awake()
        {
            audioSource = GetComponent<AudioSource>();
        }
    }
}

I am trying to have one place to drop all audioclips so I can easily manage where all my audio files are in the scene.

Maybe a dictionary with ley value pairs for better choosing…??
thniking…
trying … this and that…

So here’s my AudioRandomizer, which instead of adding all the sounds on each AudioRandomizer (tedious), I use a ScriptableAudioArray…
First the ScriptableAudioArray

using System.Collections.Generic;
using UnityEngine;
#pragma warning disable CS0649
namespace TkrainDesigns.ScriptableObjects
{
    [CreateAssetMenu(fileName = "AudioArray", menuName = "Shared/AudioArray")]
    public class ScriptableAudioArray : ScriptableObject
    {

        [SerializeField] List<AudioClip> clips = new List<AudioClip>();

        public int Count
        {
            get
            {
                return clips.Count;
            }
        }

        public AudioClip GetClip(int clip)
        {
            if (clips.Count == 0) return null;
            return clips[Mathf.Clamp(clip, 0, clips.Count - 1)];
        }

        public AudioClip GetRandomClip()
        {
            if (clips.Count > 0) return clips.RandomElement();
            return null;
        }
    } 
}

Then the AudioRandomizer

using TkrainDesigns.ScriptableObjects;
using UnityEngine;

namespace TkrainDesigns
{
    [RequireComponent(typeof(AudioSource))]
    public class AudioRandomizer : MonoBehaviour
    {
        new AudioSource audio;
        public ScriptableAudioArray audioArray;
        public float maxPitchRange = 1.4f;
        public float minPitchRange = .6f;
        public bool playOnAwake;

        void Awake()
        {
            audio = GetComponent<AudioSource>();
            audio.playOnAwake = false;
            audio.spatialBlend = .95f;
        }

        void Start()
        {
            if (playOnAwake)
            {
                Play();
            }
        }

        public void Play()
        {
            audio.pitch = Random.Range(minPitchRange, maxPitchRange);
            if (!audioArray)
            {
                audio.Play();
                return;
            }

            if (audioArray.Count == 0)
            {
                audio.Play();
                return;
            }

            audio.PlayOneShot(audioArray.GetRandomClip());
        }
    }
}

Then I create AudioArrays with the various types of sounds… like a footsteps collection, a sword on sword collection, a punches collection, etc, and place the appropriate array on the AudioRandomizer

2 Likes

I created my own; here it is; a bit more complex:

#region

using System;
using System.Collections.Generic;
using UnityEngine;
using Random = UnityEngine.Random;

#endregion

namespace Deplorable_Mountaineer.RPG.Audio {
    /// <summary>
    /// Sound bank component for playing randomizable sound effects
    /// </summary>
    public class SoundBank : MonoBehaviour {
        [Tooltip("All sound effects for this game object go here")] [SerializeField]
        private SoundEffectBank[] soundBank;

        [Tooltip("Number of audio sources to spawn to produce sound effects; " +
                 "also is the number that can be playing simultaneously")]
        [SerializeField]
        private int numAudioSources = 2;

        private AudioSource[] _audioSources;

        /// <summary>
        /// Quick lookup of sound effects
        /// </summary>
        private readonly Dictionary<string, List<SoundEffect>> _effects = new();

        /// <summary>
        /// Rotating queue of audio sources
        /// </summary>
        private int _currentAudioSource;

        private void OnValidate(){
            if(soundBank == null) return;

            //Make sound effect names visible in inspector as list labels
            foreach(SoundEffectBank bank in soundBank){
                foreach(SoundEffect effect in bank.effects){
                    if(effect.audioClip) effect.name = effect.audioClip.name;
                }
            }
        }

        private void Awake(){
            //Spawn and set up audio sources
            _audioSources = new AudioSource[numAudioSources];
            for(int i = 0; i < numAudioSources; i++){
                _audioSources[i] = gameObject.AddComponent<AudioSource>();
                _audioSources[i].playOnAwake = false;
                _audioSources[i].spatialize = true;
                _audioSources[i].spatialBlend = 1;
            }

            //Set up quick lookup
            foreach(SoundEffectBank bank in soundBank){
                if(!_effects.ContainsKey(bank.name))
                    _effects[bank.name] = new List<SoundEffect>();

                foreach(SoundEffect effect in bank.effects) _effects[bank.name].Add(effect);
            }

            foreach(string key in _effects.Keys){
                float total = 0;
                foreach(SoundEffect effect in _effects[key]) total += effect.likelihood;
                if(total <= Mathf.Epsilon) continue;
                //normalize probabilities so they add to one
                foreach(SoundEffect effect in _effects[key]) effect.likelihood /= total;
            }
        }

        /// <summary>
        /// Call this to play a random sound effect
        /// </summary>
        /// <param name="bankLabel">The name of the effect to play</param>
        public void Play(string bankLabel){
            if(!_effects.ContainsKey(bankLabel)){
                Debug.Log($"Missing effect: {bankLabel}");
                return;
            }

            //choose a random sound effect weighted by likelihood
            float rollTheDie = Random.value;
            float total = 0;
            foreach(SoundEffect effect in _effects[bankLabel]){
                total += effect.likelihood;
                if(total < rollTheDie) continue;
                if(_audioSources.Length == 0){ //if no audio sources, just play clip at point
                    AudioSource.PlayClipAtPoint(effect.audioClip, transform.position,
                        Random.Range(effect.minVolume, effect.maxVolume));
                    break;
                }

                //Set up and play the clip
                _audioSources[_currentAudioSource].clip = effect.audioClip;
                _audioSources[_currentAudioSource].volume =
                    Random.Range(effect.minVolume, effect.maxVolume);
                _audioSources[_currentAudioSource].pitch =
                    Random.Range(effect.minPitch, effect.maxPitch);
                _audioSources[_currentAudioSource].Play();

                //advance the queue
                _currentAudioSource++;
                if(_currentAudioSource >= _audioSources.Length)
                    _currentAudioSource = 0;
                break;
            }
        }

        /// <summary>
        /// A specific randomizable sound effect
        /// </summary>
        [Serializable]
        public class SoundEffect {
            //list items in inspector are labeled by a string field called "name"
            [HideInInspector] public string name;

            [Tooltip("Audio clip to play")] public AudioClip audioClip;

            [Tooltip("Likelihood weight for this clip; higher " +
                     "numbers are more likely; 0 means never")]
            [Min(0)]
            public float likelihood = 1;

            [Tooltip("Randomize volume: minimum")] public float minVolume = .1f;

            [Tooltip("Randomize volume: maximum")] public float maxVolume = .2f;

            [Tooltip("Randomize pitch multiplier: minimum")]
            public float minPitch = .9f;

            [Tooltip("Randomize pitch multiplier: maximum")]
            public float maxPitch = 1.1f;
        }

        /// <summary>
        /// A bank of audio clips for a specific effect
        /// </summary>
        [Serializable]
        public class SoundEffectBank {
            [Tooltip("Label used to select this effect")]
            public string name;

            [Tooltip("Possible sound effects to play, chosen at random")]
            public SoundEffect[] effects;
        }
    }
}

2 Likes

Privacy & Terms