FMODi paigaldamine projekti sisse, fmod project created, assets are imported into FMOD; AudioManager and FMODEvents scripts, VR is set up
This commit is contained in:
Binary file not shown.
276
Assets/_PROJECT/Scripts/Audio/AudioManager.cs
Normal file
276
Assets/_PROJECT/Scripts/Audio/AudioManager.cs
Normal file
@@ -0,0 +1,276 @@
|
||||
using FMOD.Studio;
|
||||
using FMODUnity;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using UnityEditor;
|
||||
using UnityEngine;
|
||||
using UnityEngine.SceneManagement;
|
||||
|
||||
public class AudioManager : MonoBehaviour
|
||||
{
|
||||
[Header("Volume")]
|
||||
[Range(0, 1)]
|
||||
|
||||
public float MasterVolume = 1;
|
||||
[Range(0, 1)]
|
||||
|
||||
public float MusicVolume = 1;
|
||||
[Range(0, 1)]
|
||||
|
||||
public float SFXVolume = 1;
|
||||
[Range(0, 1)]
|
||||
|
||||
public float UIVolume = 1;
|
||||
[Range(0, 1)]
|
||||
|
||||
private Bus masterBus;
|
||||
private Bus musicBus;
|
||||
private Bus sfxBus;
|
||||
private Bus reverbBus;
|
||||
private Bus uiBus;
|
||||
const string sid = "00000000-0000-0000-0000-000000000000";
|
||||
static readonly Guid nullGuid = new Guid(sid);
|
||||
|
||||
private List<EventInstance> eventInstances = new();
|
||||
class TimelineInfo
|
||||
{
|
||||
public FMOD.StringWrapper LastMarker = new();
|
||||
}
|
||||
TimelineInfo timelineInfo;
|
||||
GCHandle timelineHandle;
|
||||
|
||||
EVENT_CALLBACK beatCallback;
|
||||
|
||||
private static AudioManager _instance { get; set; }
|
||||
public static event Action<string> OnNewBGMMarker;
|
||||
// public static AudioManager instance;
|
||||
private static EventInstance musicEventInstance;
|
||||
|
||||
|
||||
// public access for the Singleton
|
||||
// and lazy instantiation if not exists
|
||||
public static AudioManager Instance
|
||||
{
|
||||
get
|
||||
{
|
||||
// if exists directly return
|
||||
if (_instance) return _instance;
|
||||
|
||||
// otherwise search it in the scene
|
||||
_instance = FindObjectOfType<AudioManager>();
|
||||
|
||||
// found it?
|
||||
if (_instance) return _instance;
|
||||
|
||||
// otherwise create and initialize it
|
||||
CreateInstance();
|
||||
|
||||
return _instance;
|
||||
}
|
||||
}
|
||||
|
||||
[RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.BeforeSceneLoad)]
|
||||
private static void CreateInstance()
|
||||
{
|
||||
// skip if already exists
|
||||
if (_instance) return;
|
||||
if (SceneManager.GetActiveScene().name == "BankLoader") return;
|
||||
InitializeInstance(new GameObject(nameof(AudioManager)).AddComponent<AudioManager>());
|
||||
}
|
||||
|
||||
private static void InitializeInstance(AudioManager instance)
|
||||
{
|
||||
_instance = instance;
|
||||
DontDestroyOnLoad(_instance.gameObject);
|
||||
_instance.eventInstances = new List<EventInstance>();
|
||||
_instance.masterBus = RuntimeManager.GetBus("bus:/");
|
||||
_instance.musicBus = RuntimeManager.GetBus("bus:/Music");
|
||||
_instance.sfxBus = RuntimeManager.GetBus("bus:/SFX");
|
||||
_instance.uiBus = RuntimeManager.GetBus("bus:/UI");
|
||||
// _instance.MasterVolume = SaveManager.Instance.systemData.MasterVolume / 100f;
|
||||
// _instance.SFXVolume = SaveManager.Instance.systemData.SFXVolume / 100f;
|
||||
// _instance.MusicVolume = SaveManager.Instance.systemData.MusicVolume / 100f;
|
||||
// _instance.UIVolume = SaveManager.Instance.systemData.UIVolume / 100f;
|
||||
|
||||
}
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (_instance && _instance != this)
|
||||
{
|
||||
Destroy(gameObject);
|
||||
return;
|
||||
}
|
||||
InitializeInstance(this);
|
||||
}
|
||||
|
||||
public EventInstance CreateInstance(EventReference eventReference)
|
||||
{
|
||||
EventInstance eventInstance = RuntimeManager.CreateInstance(eventReference);
|
||||
eventInstances.Add(eventInstance);
|
||||
return eventInstance;
|
||||
}
|
||||
|
||||
private void Update()
|
||||
{
|
||||
musicBus.setVolume(MusicVolume);
|
||||
sfxBus.setVolume(SFXVolume);
|
||||
uiBus.setVolume(UIVolume);
|
||||
masterBus.setVolume(MasterVolume);
|
||||
}
|
||||
|
||||
public static bool IsEventReferenceValid(EventReference eventReference)
|
||||
{
|
||||
return eventReference.Guid != nullGuid;
|
||||
}
|
||||
public static void PlayOneShot(EventReference eventReference)
|
||||
{
|
||||
if (eventReference.Guid != nullGuid)
|
||||
RuntimeManager.PlayOneShot(eventReference);
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("EventReference is null, ignoring...");
|
||||
}
|
||||
}
|
||||
public void InitializeMusic(EventReference musicEventReference)
|
||||
{
|
||||
if (musicEventReference.Guid == nullGuid)
|
||||
{
|
||||
Debug.LogWarning("EventReference is null, ignoring.");
|
||||
return;
|
||||
}
|
||||
musicEventInstance = CreateInstance(musicEventReference);
|
||||
timelineInfo = new TimelineInfo();
|
||||
|
||||
// Explicitly create the delegate object and assign it to a member so it doesn't get freed
|
||||
// by the garbage collected while it's being used
|
||||
beatCallback = new EVENT_CALLBACK(BeatEventCallback);
|
||||
|
||||
// Pin the class that will store the data modified during the callback
|
||||
timelineHandle = GCHandle.Alloc(timelineInfo);
|
||||
// Pass the object through the userdata of the instance
|
||||
musicEventInstance.setUserData(GCHandle.ToIntPtr(timelineHandle));
|
||||
musicEventInstance.setCallback(beatCallback, EVENT_CALLBACK_TYPE.TIMELINE_BEAT | EVENT_CALLBACK_TYPE.TIMELINE_MARKER);
|
||||
}
|
||||
|
||||
public void SetMusicParameter(string parameter, float value)
|
||||
{
|
||||
musicEventInstance.setParameterByName(parameter, value);
|
||||
}
|
||||
public void StartMusic()
|
||||
{
|
||||
if (!musicEventInstance.isValid())
|
||||
{
|
||||
Debug.LogWarning("Music is not initialized yet, ignoring.");
|
||||
return;
|
||||
}
|
||||
musicEventInstance.start();
|
||||
}
|
||||
|
||||
public int GetMusicPosition()
|
||||
{
|
||||
musicEventInstance.getTimelinePosition(out int position);
|
||||
return position;
|
||||
}
|
||||
|
||||
public void StopSFX()
|
||||
{
|
||||
sfxBus.stopAllEvents(FMOD.Studio.STOP_MODE.IMMEDIATE);
|
||||
}
|
||||
|
||||
public void FadeOutMusic()
|
||||
{
|
||||
musicEventInstance.stop(FMOD.Studio.STOP_MODE.ALLOWFADEOUT);
|
||||
musicEventInstance.release();
|
||||
|
||||
}
|
||||
|
||||
public static bool IsPlaying()
|
||||
{
|
||||
musicEventInstance.getPlaybackState(out PLAYBACK_STATE state);
|
||||
return state != PLAYBACK_STATE.STOPPED;
|
||||
}
|
||||
|
||||
public static bool IsPlaying(EventInstance instance)
|
||||
{
|
||||
instance.getPlaybackState(out PLAYBACK_STATE state);
|
||||
return state != PLAYBACK_STATE.STOPPED;
|
||||
}
|
||||
public static void Unpause()
|
||||
{
|
||||
musicEventInstance.setPaused(false);
|
||||
}
|
||||
|
||||
public static void Unpause(EventInstance instance)
|
||||
{
|
||||
instance.setPaused(false);
|
||||
}
|
||||
|
||||
public static void Pause()
|
||||
{
|
||||
musicEventInstance.setPaused(true);
|
||||
}
|
||||
|
||||
public static void Pause(EventInstance instance)
|
||||
{
|
||||
instance.setPaused(true);
|
||||
}
|
||||
|
||||
private void CleanUp()
|
||||
{
|
||||
if (eventInstances != null)
|
||||
{
|
||||
foreach (EventInstance eventInstance in eventInstances)
|
||||
{
|
||||
eventInstance.stop(FMOD.Studio.STOP_MODE.IMMEDIATE);
|
||||
eventInstance.release();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// taken from https://www.fmod.com/docs/2.02/unity/examples-timeline-callbacks.html
|
||||
[AOT.MonoPInvokeCallback(typeof(EVENT_CALLBACK))]
|
||||
static FMOD.RESULT BeatEventCallback(EVENT_CALLBACK_TYPE type, IntPtr instancePtr, IntPtr parameterPtr)
|
||||
{
|
||||
EventInstance instance = new(instancePtr);
|
||||
|
||||
// Retrieve the user data
|
||||
FMOD.RESULT result = instance.getUserData(out IntPtr timelineInfoPtr);
|
||||
if (result != FMOD.RESULT.OK)
|
||||
{
|
||||
Debug.LogError("Timeline Callback error: " + result);
|
||||
}
|
||||
else if (timelineInfoPtr != IntPtr.Zero)
|
||||
{
|
||||
// Get the object to store beat and marker details
|
||||
GCHandle timelineHandle = GCHandle.FromIntPtr(timelineInfoPtr);
|
||||
TimelineInfo timelineInfo = (TimelineInfo)timelineHandle.Target;
|
||||
|
||||
switch (type)
|
||||
{
|
||||
case EVENT_CALLBACK_TYPE.TIMELINE_MARKER:
|
||||
{
|
||||
var parameter = (TIMELINE_MARKER_PROPERTIES)Marshal.PtrToStructure(parameterPtr, typeof(TIMELINE_MARKER_PROPERTIES));
|
||||
timelineInfo.LastMarker = parameter.name;
|
||||
OnNewBGMMarker?.Invoke(parameter.name);
|
||||
break;
|
||||
}
|
||||
case EVENT_CALLBACK_TYPE.DESTROYED:
|
||||
{
|
||||
// Now the event has been destroyed, unpin the timeline memory so it can be garbage collected
|
||||
timelineHandle.Free();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return FMOD.RESULT.OK;
|
||||
}
|
||||
|
||||
private void OnDestroy()
|
||||
{
|
||||
CleanUp();
|
||||
}
|
||||
|
||||
}
|
||||
11
Assets/_PROJECT/Scripts/Audio/AudioManager.cs.meta
Normal file
11
Assets/_PROJECT/Scripts/Audio/AudioManager.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: c87d04403eccfb742b177e2556692f35
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
24
Assets/_PROJECT/Scripts/Audio/FMODEvents.cs
Normal file
24
Assets/_PROJECT/Scripts/Audio/FMODEvents.cs
Normal file
@@ -0,0 +1,24 @@
|
||||
using FMODUnity;
|
||||
using UnityEngine;
|
||||
|
||||
public class FMODEvents : MonoBehaviour
|
||||
{
|
||||
[field: Header("SFX")]
|
||||
[field: SerializeField] public EventReference TestSound { get; private set; }
|
||||
|
||||
|
||||
[field: Header("UI")]
|
||||
[field: SerializeField] public EventReference ButtonClick { get; private set; }
|
||||
[field: SerializeField] public EventReference ButtonSelect { get; private set; }
|
||||
|
||||
public static FMODEvents Instance { get; private set; }
|
||||
|
||||
private void Awake()
|
||||
{
|
||||
if (Instance != null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
Instance = this;
|
||||
}
|
||||
}
|
||||
11
Assets/_PROJECT/Scripts/Audio/FMODEvents.cs.meta
Normal file
11
Assets/_PROJECT/Scripts/Audio/FMODEvents.cs.meta
Normal file
@@ -0,0 +1,11 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f7db9618133cf954a8f3392be7f313b3
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
Reference in New Issue
Block a user