/// <summary>
 /// Play an audio clip by using an Audio Config
 /// </summary>
 /// <param name="audioConfig">The target audio config</param>
 /// <param name="parent">The source of the audio</param>
 /// <param name="onComplete">The callback when the playback finished</param>
 /// <returns>The channel (AudioSource) which the Audio System are using</returns>
 public static AudioSource Play(this AudioConfig audioConfig, Transform parent, int clipIndex = -1, Action onComplete = null)
 {
     return(audioConfig.Play(audioConfig.VolumeScale, parent, clipIndex, onComplete));
 }
        /// <summary>
        /// Play an audio clip by using an Audio Config but override the volume scale
        /// </summary>
        /// <param name="audioConfig">The target audio config</param>
        /// <param name="volume">The volume scale for the channel (will override the config one)</param>
        /// <param name="parent">The source of the audio</param>
        /// <param name="onComplete">The callback when the playback finished</param>
        /// <returns>The channel (AudioSource) which the Audio System are using</returns>
        public static AudioSource Play(this AudioConfig audioConfig, float volume, Transform parent = null, int clipIndex = -1, Action onComplete = null)
        {
            // Stop the previous playbacks if necessary
            if (audioConfig.CurrentChannel != null)
            {
                switch (audioConfig.PlayMode)
                {
                case AudioConfig.AudioPlayModes.Override:
                {
                    // Stop the current one
                    audioConfig.Stop();
                    break;
                }

                case AudioConfig.AudioPlayModes.OneAtATime:
                {
                    // Return the existing one
                    return(audioConfig.CurrentChannel);
                }

                case AudioConfig.AudioPlayModes.Normal:
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }
            }

            // Play and get the channel. Matching the channel attributes to the config.
            AudioSource targetChannel;

            if (audioConfig.TemplateAudioSource != null)
            {
                targetChannel = AudioSystem.Instance.Play(audioConfig.GetAudioClip(clipIndex),
                                                          audioConfig.TemplateAudioSource, volume, channel => HandleOnComplete(channel, audioConfig));
            }
            else
            {
                targetChannel        = AudioSystem.Instance.GetFreeChannel();
                targetChannel.clip   = audioConfig.GetAudioClip(clipIndex);
                targetChannel.volume = volume;
                targetChannel.loop   = audioConfig.Loop;

                // Override the settings
                targetChannel.priority = audioConfig.Priority;
                switch (audioConfig.SpatialMode)
                {
                case AudioConfig.SpatialModes.Pure2D:
                    break;

                case AudioConfig.SpatialModes.Simple2D:
                    if (parent == null)
                    {
                        Debug.LogWarning(audioConfig.name + ": should attach to a transform for Simple2D spatial playback!");
                    }
                    AudioSystem.Instance.TrackChannelPosition(targetChannel, 0f, audioConfig.VolumeScale,
                                                              audioConfig.MinDistance, audioConfig.MaxDistance);
                    break;

                case AudioConfig.SpatialModes.Simple3D:
                    if (parent == null)
                    {
                        Debug.LogWarning(audioConfig.name + ": should attach to a transform for Simple3D spatial playback!");
                    }
                    targetChannel.minDistance  = audioConfig.MinDistance;
                    targetChannel.maxDistance  = audioConfig.MaxDistance;
                    targetChannel.spatialBlend = 1.0f;
                    targetChannel.rolloffMode  = AudioRolloffMode.Linear;
                    break;

                default:
                    throw new ArgumentOutOfRangeException();
                }

                // Play and add the callback
                AudioSystem.Instance.Play(targetChannel, channel => HandleOnComplete(channel, audioConfig));
            }

            // Set the source of the audio
            if (parent != null)
            {
                targetChannel.transform.SetParent(parent, false);
            }

            // Add the reference
            audioConfig.AddOccupiedChannel(targetChannel);

            // Add the callback to the dictionary
            audioConfig.Callbacks.Add(targetChannel, onComplete);

            return(targetChannel);
        }
 /// <summary>
 /// Play an audio clip by using an Audio Config
 /// </summary>
 /// <param name="audioConfig">The target audio config</param>
 /// <param name="onComplete">The callback when the playback finished</param>
 /// <returns>The channel (AudioSource) which the Audio System are using</returns>
 public static AudioSource Play(this AudioConfig audioConfig, Action onComplete = null)
 {
     return(audioConfig.Play(audioConfig.VolumeScale, null, onComplete: onComplete));
 }