The Sound Manager is used for loading and playing all sounds in a scene. Unlike the Music Manager, the Sound Manager is not persistent across scenes because each scene likely has different audio clips to play.

BaseSoundManager.cs

using UnityEngine;
using System.Collections;

public class SoundObject {
    public AudioSource source;
    public GameObject sourceGO;
    public Transform sourceTR;
    
    public AudioClip clip;
    public string name;
            
    public SoundObject (AudioClip aClip, string aName, float aVolume) {
        // in this (the constructor) we create a new audio source and store the details of the sound itself
        sourceGO = new GameObject("AudioSource_"+aName);
        sourceTR = sourceGO.transform;
        source = sourceGO.AddComponent<AudioSource>();
        source.name = "AudioSource_"+aName;
        source.playOnAwake = false;
        source.clip = aClip;
        source.volume = aVolume;
        clip = aClip;
        name = aName;
    }
    
    public void PlaySound (Vector3 atPosition) {
        sourceTR.position = atPosition;
        source.PlayOneShot(clip);
    }
}

public class BaseSoundManager : MonoBehaviour {
    public static BaseSoundManager Instance;
    
    public AudioClip[] GameSounds;
    
    private int totalSounds;
    private ArrayList soundObjectList;
    private SoundObject tempSoundObj;
    
    public float volume = 1;
    public string gamePrefsName = "DefaultGame"; // DO NOT FORGET TO SET THIS IN THE EDITOR!!

    public void Awake() {
        Instance = this;
    }
    
    void Start () {
        // we will grab the volume from PlayerPrefs when this script first starts
        volume = PlayerPrefs.GetFloat(gamePrefsName+"_SFXVol");
        Debug.Log ("BaseSoundController gets volume from prefs "+gamePrefsName+"_SFXVol at "+volume);
        soundObjectList = new ArrayList();
        
        // make sound objects for all of the sounds in GameSounds array
        foreach (AudioClip theSound in GameSounds) {
            tempSoundObj = new SoundObject(theSound, theSound.name, volume);
            soundObjectList.Add(tempSoundObj);
            totalSounds++;
        }
    }
    
    public void PlaySoundByIndex(int anIndexNumber, Vector3 aPosition) {
        // make sure we're not trying to play a sound indexed higher than exists in the array
        if (anIndexNumber>soundObjectList.Count) {
            Debug.LogWarning ("BaseSoundController>Trying to do PlaySoundByIndex with invalid index number. Playing last sound in array, instead.");
            anIndexNumber = soundObjectList.Count-1;
        }
        
        tempSoundObj = (SoundObject)soundObjectList[anIndexNumber];
        tempSoundObj.PlaySound(aPosition);    
    }

}

Usage

Each scene with audio requirements (excluding background music, which is handled by the Music Manager) should have a Sound Manager object with either the BaseSoundManager or an extended script attached. The Sound Manager is a singleton, but it is not persistent from scene to scene due to different audio requirements. If multiple scenes have the same audio requirements, simply add a DontDestroyOnLoad() call to the Start() function.

The Sound Manager takes an array of audio clips that the scene will require. It also takes in a playerprefs string. These must be set in the inspector.

Each audio clip in the array will have its own AudioSource and GameObject instantiated when the Sound Manager first runs. Each sound has its own audio channel in order to avoid overlaps or too many different sounds playing on a single AudioSource. An internal class called SoundObject is used to store information about each audio source and its associated game object.