Created
October 4, 2023 20:47
-
-
Save athiedmann/a52a9754f09913022581507d77939214 to your computer and use it in GitHub Desktop.
Unity FMOD Audio Manager with Scene-Based Control and Event Management. Events are stored and called via scriptable objects.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections.Generic; | |
using UnityEngine; | |
using FMODUnity; | |
using FMOD.Studio; | |
using UnityEngine.SceneManagement; | |
public class FMODAudioManager : MonoBehaviour | |
{ | |
public bool useDebug; | |
public static FMODAudioManager instance { get; private set; } | |
public FMODEvents FMODEvents; | |
public FMODSnapshotEvents FMODSnapshots; | |
[SerializeField] EventReference fMODAmbientEvent; | |
private List<EventInstance> fmodEventInstances = new List<EventInstance>(); | |
private EventInstance ambienceEventInstance; | |
private string sceneName; | |
public List<EventInstance> FMODEventInstances { get => fmodEventInstances; } | |
private void Awake() | |
{ | |
sceneName = SceneManager.GetActiveScene().name; | |
if (instance != null) | |
{ | |
if (useDebug) | |
Debug.LogError("Found more than one Audio Manager in the scene."); | |
Destroy(gameObject); | |
return; | |
} | |
instance = this; | |
DontDestroyOnLoad(gameObject); | |
} | |
private void Start() | |
{ | |
CheckIfSceneChange(); | |
InitializeAmbience(fMODAmbientEvent); | |
} | |
public void PlayOneShot(EventReference sound, Vector3 worldPos) | |
{ | |
RuntimeManager.PlayOneShot(sound, worldPos); | |
} | |
public void PlayOneShotAttached(EventReference sound, GameObject gameObject) | |
{ | |
RuntimeManager.PlayOneShotAttached(sound, gameObject); | |
} | |
public void PlayUI() | |
{ | |
PlayOneShot(FMODEvents.clickButton, transform.position); | |
} | |
public void InitializeAmbience(EventReference ambienceReference) | |
{ | |
if (ambienceEventInstance.isValid()) | |
{ | |
ambienceEventInstance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); | |
ambienceEventInstance.release(); | |
} | |
ambienceEventInstance = CreateEventInstance(ambienceReference); | |
ambienceEventInstance.start(); | |
} | |
public EventInstance CreateEventInstance(EventReference eventReference) | |
{ | |
EventInstance eventInstance = RuntimeManager.CreateInstance(eventReference); | |
fmodEventInstances.Add(eventInstance); | |
return eventInstance; | |
} | |
public void CheckIfSceneChange() | |
{ | |
SceneManager.sceneLoaded += OnSceneLoaded; | |
} | |
private void OnSceneLoaded(Scene scene, LoadSceneMode mode) | |
{ | |
sceneName = SceneManager.GetActiveScene().name; | |
if (sceneName == "Scene_Game_Menu" && fmodEventInstances.Count > 0) | |
{ | |
CleanUp(); | |
InitializeAmbience(fMODAmbientEvent); | |
} | |
} | |
private void CleanUp() | |
{ | |
foreach (EventInstance eventInstance in fmodEventInstances) | |
{ | |
eventInstance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE); | |
eventInstance.release(); | |
} | |
fmodEventInstances.Clear(); | |
} | |
private void OnDestroy() | |
{ | |
CleanUp(); | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using FMODUnity; | |
using UnityEngine; | |
[CreateAssetMenu(fileName = "FMODEvents", menuName = "Dragon Crashers/Audio/Events")] | |
public class FMODEvents : ScriptableObject | |
{ | |
[field: Header("UI")] | |
[field: SerializeField] public EventReference clickButton { get; private set; } | |
[field: SerializeField] public EventReference hoverButton { get; private set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using FMODUnity; | |
using UnityEngine; | |
[CreateAssetMenu(fileName = "FMODMusicEvents", menuName = "Dragon Crashers/Audio/Music")] | |
public class FMODMusicEvents : ScriptableObject | |
{ | |
[field: Header("Level Music")] | |
[field: SerializeField] public EventReference skeletonLevelMusic { get; private set; } | |
[field: SerializeField] public EventReference dragonLevelMusic { get; private set; } | |
[field: SerializeField] public EventReference WinMusic { get; private set; } | |
[field: SerializeField] public EventReference DefeatMusic { get; private set; } | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System.Collections; | |
using UnityEngine; | |
using FMOD.Studio; | |
using FMODUnity; | |
using UnityEngine.SceneManagement; | |
public class FMODMusicManager : MonoBehaviour | |
{ | |
public bool useDebug; | |
public static FMODMusicManager instance { get; private set; } | |
public FMODMusicEvents FMODMusicEvents; | |
[SerializeField] bool playMusicOnStart; | |
private EventInstance musicLevelInstance; | |
//private EventInstance musicVictoryDefeatInstance; | |
private string sceneName; | |
private PLAYBACK_STATE musicPlayBackState; | |
private bool isPlaying = false; | |
private bool isFadingOut = false; | |
public bool IsPlaying { get => isPlaying; } | |
private void Awake() | |
{ | |
if (instance != null) | |
{ | |
UseDebug("Found more than one Music Manager in the scene."); | |
Destroy(gameObject); | |
return; | |
} | |
instance = this; | |
DontDestroyOnLoad(gameObject); | |
isPlaying = false; | |
} | |
private void Start() | |
{ | |
CheckIfSceneChange(); | |
if (playMusicOnStart && string.IsNullOrEmpty(sceneName)) | |
{ | |
SetMusicEventForScene(); | |
UseDebug("Play On Start called"); | |
} | |
UseDebug($"Music is playing: {isPlaying}"); | |
} | |
public void InitializeMusic(EventReference musicReference) | |
{ | |
musicLevelInstance = FMODAudioManager.instance.CreateEventInstance(musicReference); | |
musicLevelInstance.start(); | |
isPlaying = true; | |
UseDebug("Music Initialized and PLAYING"); | |
} | |
public void PlayMusic() | |
{ | |
musicLevelInstance.getPlaybackState(out musicPlayBackState); | |
UseDebug("Music Playback State: " + musicPlayBackState); | |
if (musicPlayBackState != PLAYBACK_STATE.PLAYING) | |
{ | |
SetMusicEventForScene(); | |
} | |
else | |
{ | |
Debug.LogWarning("Music instance already playing"); | |
} | |
} | |
public void StopMusic() | |
{ | |
musicLevelInstance.getPlaybackState(out musicPlayBackState); | |
UseDebug("Music Playback State: " + musicPlayBackState); | |
if (musicPlayBackState != PLAYBACK_STATE.PLAYING) | |
{ | |
musicLevelInstance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); | |
musicLevelInstance.release(); | |
} | |
else | |
{ | |
Debug.LogWarning("No music instance playing"); | |
} | |
} | |
public void SetMusicEventForScene() | |
{ | |
sceneName = SceneManager.GetActiveScene().name; | |
UseDebug("Current scene name: " + sceneName); | |
switch (sceneName) | |
{ | |
case "Scene_Battle_Skeletons": | |
InitializeMusic(FMODMusicEvents.skeletonLevelMusic); | |
break; | |
case "Scene_Battle_Dragon": | |
InitializeMusic(FMODMusicEvents.dragonLevelMusic); | |
break; | |
case "Scene_Game_Menu": | |
InitializeMusic(FMODMusicEvents.skeletonLevelMusic); | |
break; | |
default: | |
Debug.LogWarning("Music returning, check if scene names have changed"); | |
return; | |
} | |
} | |
public void FadeOutMusicOnSceneLoad() | |
{ | |
musicLevelInstance.getPlaybackState(out musicPlayBackState); | |
if (musicPlayBackState == PLAYBACK_STATE.PLAYING && isPlaying) | |
{ | |
StartCoroutine(FadeOutCoroutine()); | |
} | |
else | |
{ | |
Debug.LogWarning("musicPlayBackState is not playing anything"); | |
return; | |
} | |
} | |
private IEnumerator FadeOutCoroutine() | |
{ | |
isFadingOut = true; | |
EventInstance musicFadeOutSnapshot = FMODAudioManager.instance.CreateEventInstance(FMODAudioManager.instance.FMODSnapshots.MusicFadeOut); | |
musicFadeOutSnapshot.start(); | |
float fadeDuration = 5.0f; | |
float elapsedTime = 0.0f; | |
while (elapsedTime < fadeDuration) | |
{ | |
elapsedTime += Time.deltaTime; | |
yield return null; | |
} | |
musicLevelInstance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); | |
musicLevelInstance.release(); | |
isPlaying = false; | |
musicFadeOutSnapshot.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT); | |
musicFadeOutSnapshot.release(); | |
isFadingOut = false; | |
} | |
public void CheckIfSceneChange() | |
{ | |
SceneManager.sceneLoaded += OnSceneLoaded; | |
} | |
private void OnSceneLoaded(Scene scene, LoadSceneMode mode) | |
{ | |
sceneName = SceneManager.GetActiveScene().name; | |
if (sceneName == "Scene_Game_Menu") | |
{ | |
SetMusicEventForScene(); | |
} | |
} | |
private void UseDebug(string debugMessage) | |
{ | |
if (useDebug) | |
{ | |
Debug.Log(debugMessage); | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using FMODUnity; | |
using UnityEngine; | |
[CreateAssetMenu(fileName = "FMODSnapshotEvents", menuName = "Dragon Crashers/Audio/Snapshots")] | |
public class FMODSnapshotEvents : ScriptableObject | |
{ | |
[field: Header("Snapshots")] | |
[field: SerializeField] public EventReference MusicFadeOut { get; private set; } | |
[field: SerializeField] public EventReference DragonLevelMusicFade { get; private set; } | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment