The best way to randomize sounds in Unity 3D C#

The best way to randomize sounds in Unity 3D C#

By Victor Engström

The worst random

To make the most out of the sounds in a game you want to have the least repetition and most variation. The most basic way to do this is to have a random sound selection like this:

// The worst random 
audioSource.clip = audioClipArray[Random.Range(0, audioClipArray.Length)];

Why is this a problem?

The Random.Range is a problem because its true random and does not care if it plays sound number 1 five times in a row:

Possible outcome: 1, 1, 1, 1, 1

This can lead to where you get the same sound repeating after itself any number of times.

How to make a better random

One way to make the random better is to remember the last selected value and retry the random if gets that one next time. The problem with this is that you can get very repetitive variations anyway.

// The better but not best random
while (audioSource.clip == lastAudioClip) {
    audioSource.clip = audioClipArray[Random.Range(0, audioClipArray.Length)];
}
lastAudioClip = audioSource.clip;

The worst-case scenario here is that you’d get sound alternating between two variations even if you had more. Like the example below:

Possible outcome 1, 2, 1, 2, 1

The best way

The best way I’ve found is to remember half the length of the possible variations.

using UnityEngine;

[System.Serializable]
public class RandomAudioClip {

    public AudioClip[] audioClipArray;

    private int audioClipIndex;
    private int[] previousArray;
    private int previousArrayIndex;

    // The best random method
    public AudioClip GetRandomAudioClip() {
        // Initialize
        if (previousArray == null) {
            // Sets the length to half of the number of AudioClips
            // This will round downwards
            // So it works with odd numbers like for example 3
            previousArray = new int[audioClipArray.Length / 2];
        }
        if (previousArray.Length == 0) {
            // If the the array length is 0 it returns null
            return null;
        } else {
            // Psuedo random remembering previous clips to avoid repetition
            do {
                audioClipIndex = Random.Range(0, audioClipArray.Length);
            } while (PreviousArrayContainsAudioClipIndex());
            // Adds the selected array index to the array
            previousArray[previousArrayIndex] = audioClipIndex;
            // Wrap the index
            previousArrayIndex++;
            if (previousArrayIndex >= previousArray.Length) {
                previousArrayIndex = 0;
            }
        }

        // Returns the randomly selected clip
        return audioClipArray[audioClipIndex];
    }

    // Returns if the randomIndex is in the array
    private bool PreviousArrayContainsAudioClipIndex() {
        for (int i = 0; i < previousArray.Length; i++) {
            if (previousArray[i] == audioClipIndex) {
                return true;
            }
        }
        return false;
    }
}

This way if the array is 4 AudioClips (remembering the last two) it could pick:

Possible outcome 1, 3, 2, 1, 4, 3

The problems with the worst-case scenarios of the other random ways are not present in this way of randomization.

Conclusion

Sure, it’s a bit of work to set up, but it sounds way better. Also, not even the big shots like Fmod uses this better random, they use the random where you remember the last played sound and not multiple which can yield bad sounding results.

Happy randomization!

Victor Engström

2 replies on “The best way to randomize sounds in Unity 3D C#

  • Simon

    Hey!
    Thanks for the tutorial! I just implemented this in one of my Unity projects, and it saved me quite some time not having to optimize randomization myself. Works pretty damn well so far!

    One thing I noticed was when using an array with 3 clips, you might still end up with two clips alternating. I’m guessing this is due to the previousArray rounding down and ending up with only 1 remembered clip.

    Still a really useful piece of code I’ll be using for my audio implementation!

    Reply
    • Sonigon

      Glad to help mate 🙂
      Its is supposed to round down, but you probably easily could change it yourself to round up if you’d want! 🙂

      Reply

Leave a Reply

Your email address will not be published. Required fields are marked *