using UnityEngine;
// Copyright (c) 2013-2023 SCSM Pty Ltd. All rights reserved.
namespace scsmmedia
{
///
/// Based on the versions from RacR4 and AG SSC Racer.
///
[AddComponentMenu("Sci-Fi Ship Controller/Utilities/Music Controller")]
[HelpURL("http://scsmmedia.com/ssc-documentation")]
[RequireComponent(typeof(AudioSource))]
public class MusicController : MonoBehaviour
{
#region Public Static Variables
public static MusicController musicController;
#endregion
#region Public Variables
[Range(0f, 1f)] public float initialMusicVolume = 0.2f;
[Range(0f, 1f)] public float initialGameVolume = 1f;
public AudioClip[] musicTracks;
public float[] trackVolumes;
public float musicToFXFactor = 0.5f;
///
/// At runtime call PauseMusic() or ResumeMusic()
///
public bool isPaused = false;
public int firstTrack = 1000;
#endregion
#region Private variables
private int nextTrack = 0;
private float trackLength = 0f;
private float trackLengthTimer = 0f;
private int previousTrack = 0;
private float musicVolume = 0f;
private float gameVolume = 0f;
private float maxMusicVolume = 0f;
private AudioSource audioSource;
private GameObject optionsPanel;
private float realDeltaTime;
private bool isChangingTracks = false;
private float newVolume = 0f;
private bool isInitialised = false;
private int numMusicTracks = 0;
private int numTrackVolumes = 0;
#endregion
#region Initialise Methods
// Use this for initialization
public void Initialise()
{
// Make sure there is only one instance of this object in the game at one time
if (musicController == null)
{
musicController = this;
isInitialised = false;
numMusicTracks = musicTracks == null ? 0 : musicTracks.Length;
numTrackVolumes = trackVolumes == null ? 0 : trackVolumes.Length;
if (numMusicTracks < 1)
{
#if UNITY_EDITOR
Debug.Log("INFO: MusicController Initialise - no music tracks supplied");
#endif
}
else if (numMusicTracks != numTrackVolumes)
{
#if UNITY_EDITOR
Debug.LogWarning("ERROR: MusicController Initialise - number of music tracks does not match number of track volumes");
#endif
}
else
{
nextTrack = Random.Range(0, musicTracks.Length);
if (firstTrack != 1000)
{
nextTrack = firstTrack;
}
audioSource = gameObject.GetComponent();
if (audioSource != null)
{
audioSource.ignoreListenerVolume = true;
// Make 2D sound so it can be heard equally everywhere in the scene.
audioSource.spatialBlend = 0;
musicVolume = initialMusicVolume;
gameVolume = initialGameVolume;
audioSource.volume = musicVolume;
AudioListener.volume = gameVolume;
//Debug.Log ("music vol: " + audioSource.volume.ToString() + " al vol: " + AudioListener.volume);
isInitialised = true;
}
#if UNITY_EDITOR
else
{
Debug.LogWarning("ERROR: MusicController Initialise could not find AudioSource");
}
#endif
}
}
else if (musicController != this)
{
Destroy(musicController);
}
}
#endregion
#region Update Methods
// Update is called once per frame
void Update()
{
if (isChangingTracks || !isInitialised || isPaused) { return; }
if (nextTrack == 0)
{
previousTrack = trackVolumes.Length - 1;
}
else
{
previousTrack = nextTrack - 1;
}
maxMusicVolume = trackVolumes[previousTrack] * musicVolume;
// The music is louder than the (ship??) audio (SoundFX), so reduce the music accordingly
maxMusicVolume *= musicToFXFactor;
if (Time.timeScale > 0f && audioSource != null)
{
realDeltaTime = Time.deltaTime / Time.timeScale;
trackLengthTimer += realDeltaTime;
if (trackLengthTimer > trackLength)
{
PlayNextTrack();
}
else if (trackLengthTimer > trackLength - 3 && audioSource.volume > Time.deltaTime)
{
newVolume = audioSource.volume - (realDeltaTime / 3f * maxMusicVolume);
audioSource.volume = Mathf.Clamp(newVolume, 0f, 1f);
}
else if (audioSource.volume < maxMusicVolume)
{
newVolume = audioSource.volume + (realDeltaTime / 3f * maxMusicVolume);
audioSource.volume = Mathf.Clamp(newVolume, 0f, 1f);
}
else if (audioSource.clip != null && !audioSource.isPlaying)
{
PlayNextTrack();
}
}
}
#endregion
#region Public API Methods
public void PauseMusic()
{
if (isInitialised && musicTracks != null && audioSource != null && audioSource.clip != null && audioSource.isPlaying)
{
audioSource.Pause();
isPaused = true;
}
}
public void ResumeMusic()
{
if (isInitialised && musicTracks != null && audioSource != null && audioSource.clip != null)
{
audioSource.Play();
isPaused = false;
}
}
public void SetMusicVolume(float newValue)
{
if (newValue < 0f) { musicVolume = 0f; }
else if (newValue > 1f) { musicVolume = 1f; }
else { musicVolume = newValue; }
}
public void SetGameVolume(float newValue)
{
if (newValue < 0f) { gameVolume = 0f; }
else if (newValue > 1f) { gameVolume = 1f; }
else { gameVolume = newValue; }
}
public void PlayNextTrack()
{
if (!isChangingTracks && isInitialised && musicTracks != null && audioSource != null && trackVolumes != null)
{
isChangingTracks = true;
audioSource.Stop();
if (musicTracks[nextTrack] != null)
{
audioSource.clip = musicTracks[nextTrack];
}
#if UNITY_EDITOR
else
{
Debug.LogWarning("ERROR: MusicController PlayNextTrack could not get audio clip: " + nextTrack.ToString());
}
#endif
audioSource.volume = 0f;
if (audioSource.clip != null)
{
trackLength = audioSource.clip.length;
trackLengthTimer = 0;
audioSource.Play();
}
#if UNITY_EDITOR
else
{
Debug.LogWarning("ERROR: MusicController PlayNextTrack audio clip is not defined for track: " + nextTrack.ToString());
}
#endif
// Setup the next track for when this one has finished playing
nextTrack += 1;
if (nextTrack > musicTracks.Length - 1)
{
nextTrack = 0;
}
isChangingTracks = false;
}
}
#endregion
}
}