Simple AudioManager code for your Unity3d project

You know, sometimes very simple code has to be written again and again by lots of different people to solve the same basic problem. I think playing audio is one of such cases in Unity3d.

You have the audio components: AudioSource (attached to your sound emitter) and AudioListener (attached to the main camera). Now, the problem is that audio clips are represented by the AudioClip class, and each AudioSource can have a single AudioClip playing at the moment. That is sometimes ok, but other times, you want your game object to be able to play a number of different sounds, maybe at the same time (Think of a character playing footsteps sounds and maybe saying something at the same time).

Since it is very natural to have one manager object in your scene acting as a singleton, I’ve written a component that can be attached to such manager. The work of this component is to play almost any sound you want to play in your game. The code is very simple and self explationary.

// /////////////////////////////////////////////////////////////////////////////////////////////////////////
//
// Audio Manager.
//
// This code is release under the MIT licence. It is provided as-is and without any warranty.
//
// Developed by Daniel Rodríguez (Seth Illgard) in April 2010
// http://www.silentkraken.com
//
// /////////////////////////////////////////////////////////////////////////////////////////////////////////

using UnityEngine;
using System.Collections;

public class AudioManager : MonoBehaviour
{
    public AudioSource Play(AudioClip clip, Transform emitter)
    {
        return Play(clip, emitter, 1f, 1f);
    }

    public AudioSource Play(AudioClip clip, Transform emitter, float volume)
    {
        return Play(clip, emitter, volume, 1f);
    }

    /// <summary>
    /// Plays a sound by creating an empty game object with an AudioSource
    /// and attaching it to the given transform (so it moves with the transform). Destroys it after it finished playing.
    /// </summary>
    /// <param name="clip"></param>
    /// <param name="emitter"></param>
    /// <param name="volume"></param>
    /// <param name="pitch"></param>
    /// <returns></returns>
    public AudioSource Play(AudioClip clip, Transform emitter, float volume, float pitch)
    {
        //Create an empty game object
        GameObject go = new GameObject ("Audio: " +  clip.name);
        go.transform.position = emitter.position;
        go.transform.parent = emitter;

        //Create the source
        AudioSource source = go.AddComponent<AudioSource>();
        source.clip = clip;
        source.volume = volume;
        source.pitch = pitch;
        source.Play ();
        Destroy (go, clip.length);
        return source;
    }

    public AudioSource Play(AudioClip clip, Vector3 point)
    {
        return Play(clip, point, 1f, 1f);
    }

    public AudioSource Play(AudioClip clip, Vector3 point, float volume)
    {
        return Play(clip, point, volume, 1f);
    }

    /// <summary>
    /// Plays a sound at the given point in space by creating an empty game object with an AudioSource
    /// in that place and destroys it after it finished playing.
    /// </summary>
    /// <param name="clip"></param>
    /// <param name="point"></param>
    /// <param name="volume"></param>
    /// <param name="pitch"></param>
    /// <returns></returns>
    public AudioSource Play(AudioClip clip, Vector3 point, float volume, float pitch)
    {
        //Create an empty game object
        GameObject go = new GameObject("Audio: " + clip.name);
        go.transform.position = point;

        //Create the source
        AudioSource source = go.AddComponent<AudioSource>();
        source.clip = clip;
        source.volume = volume;
        source.pitch = pitch;
        source.Play();
        Destroy(go, clip.length);
        return source;
    }
}

As you can see, this class is basically 6 overloads for the Play function. Basically we have two types: the type that takes a transform (emitter) as parameter and the type that takes a Vector3. The only difference is that if you provide a point (Vector3), the sound will be played there, but if you provide an emitter, the sound will be played where the emitter is, but will also follow the emitter as it moves (e.g. the engine of a passing car).
Hope you find it useful!
By the way, I’m planning on creating on tutorial on how to create Manager systems. By that I don’t mean simple components like this but rather the best way I have found to create such a Singleton object with those components, and how to integrate that with your game when you have multiple game states and game scenes (with potentially different managers). More on that soon.

  • http://helloracer.com C4RL05

    Gracias por el codigo, muy bien resuelto con distintos overloads. Tengo ganas de ver como resuelves los Singletons.

    [WORDPRESS HASHCASH] The poster sent us ’0 which is not a hashcash value.

  • http://www.silentkraken.com Daniel Rodríguez

    Thanks for the comments. Haha, comming soon :)

  • Wiljames Rocksolid

    Sick man, thanks!

  • mipago

    excellent work and thanks for sharing your knowledge. but I think it is most useful if your script attached a simple example.

    you say

  • Virusys

    Thanks for this post! There wouldn't happen to be a javascript alternative for this, would there?

  • Isaac Dart

    Yay- Thanks for saving me some time in nicely implimenting exactly what I had in mind.. :)

  • http://hometheaterspeakerplacement.blogspot.com/ tiffany@home theater

    Great Idea. The source code you have provided is really helpful.  For sure, this will enhance the sound quality of the game programs we have installed. Looking forward on your next project. Thanks for this.

  • Rkait

    Sweet lord thank you for saving my senior project: kaitlynseniordesign.blogspot.com

  • 瀚 郑

    two suggestions:
    1. doesn’t have loop property
    2. can’t play the music through two or more scene(can use DonDestroyOnLoad())

    good job and thanks for sharing.

  • Anonymous

    I saved it as a C# script named AudioManager in Assets/GameLogic/, then added the following code to a .js script:

    AudioSource.Play(victoryClip, transform.position, 1.0);It results in a console error:Assets/Entities/Cars/Scripts/CarMovement.js(219,33): BCE0023: No appropriate version of ‘UnityEngine.AudioSource.Play’ for the argument list ‘(UnityEngine.AudioClip, UnityEngine.Vector3, float)’ was found.Why can’t I refer to a C# singleton from a .js script?

  • MBlack

    The main problem with this is that creating an object takes way too long and you will get noticeable lag before the sound plays.  You need to have a bunch of GameObjects (and components) ready and sitting in a list so you can use/reuse them in real time.

  • Shkarface Noori

    why dont you use AudioSource.PlayClipAtPoint?

  • mohit

    hi,

    I have work on a project in which i will download audio from source and save in

    persistent path than load them and play, its work fine in android but not in IOS.

    my code is:- /* load pinyin audio file */
    IEnumerator LoadAudioFile(string fileName) {
    string path = Application.persistentDataPath + Path.DirectorySeparatorChar +fileName;
    WWW www = new WWW(path);
    AudioClip myAudioClip = http://www.audioClip;
    while (!www.isDone)
    yield return www;
    tempClip = http://www.GetAudioClip(false);
    PlayEffect();
    }

    please help me to solve it asap. thanks in advance.