Skip to content

Instantly share code, notes, and snippets.

@RyanGarber
Created July 24, 2023 06:14
Show Gist options
  • Save RyanGarber/d53b723fbf67db3a76ebf25bbb69c484 to your computer and use it in GitHub Desktop.
Save RyanGarber/d53b723fbf67db3a76ebf25bbb69c484 to your computer and use it in GitHub Desktop.
[FMOD + Steam Audio + Unity] Changing cameras, events, and parameters at runtime. Requires changing some members to public.
using UnityEngine;
using SteamAudio;
public class SpatialAudioListener : MonoBehaviour
{
private SteamAudioListener _steamAudioListener;
private System.Action _onSteamAudioListenerReady;
private bool _isSteamAudioListenerReady = false;
void Awake()
{
_steamAudioListener = gameObject.AddComponent<SteamAudioListener>();
_steamAudioListener.applyReverb = true;
}
void OnEnable()
{
if (!_isSteamAudioListenerReady)
{
_onSteamAudioListenerReady += OnEnable;
return;
}
_steamAudioListener.Reinitialize();
}
void Start()
{
_onSteamAudioListenerReady?.Invoke();
_isSteamAudioListenerReady = true;
}
void Update()
{
if (SteamAudioManager.Singleton.mListener != transform)
{
SteamAudioManager.Singleton.mListener = transform;
SteamAudioManager.Singleton.mListenerComponent = _steamAudioListener;
}
}
}
using System;
using UnityEngine;
using UnityEngine.Serialization;
using FMODUnity;
using SteamAudio;
public class SpatialAudioSource : StudioEventEmitter
{
[Header("Settings")]
[SerializeField] private EventReference _defaultEventReference;
public bool Is3d = true;
public bool KeepAlive = true;
public bool PlayOnStart = false;
private Rigidbody _rigidbody;
private SteamAudioSource _steamAudioSource;
void Awake()
{
if (Is3d)
_rigidbody = GetComponent<Rigidbody>();
if (!_defaultEventReference.IsNull)
SetEventReference(_defaultEventReference);
if (PlayOnStart) Play();
}
void Update()
{
if (!KeepAlive && !IsPlaying())
ReleaseInstance();
}
public void SetEventReference(EventReference eventReference)
{
if (EventReference.Guid == eventReference.Guid)
return;
ReleaseInstance();
EventReference = eventReference;
eventDescription = RuntimeManager.GetEventDescription(eventReference);
}
private void AcquireInstance()
{
eventDescription.createInstance(out instance);
if (Is3d)
{
_steamAudioSource = gameObject.AddComponent<SteamAudioSource>();
_steamAudioSource.pathing = true;
_steamAudioSource.directivity = true;
_steamAudioSource.transmission = true;
_steamAudioSource.occlusion = true;
_steamAudioSource.occlusionType = OcclusionType.Raycast;
_steamAudioSource.reflections = true;
_steamAudioSource.reflectionsType = ReflectionsType.Realtime;
((FMODStudioAudioEngineSource) _steamAudioSource.mAudioEngineSource).mFoundDSP = false;
}
}
private void UpdateInstance()
{
if (Is3d) {
instance.set3DAttributes(RuntimeUtils.To3DAttributes(transform, _rigidbody));
RuntimeManager.AttachInstanceToGameObject(instance, transform, _rigidbody);
}
}
private void ReleaseInstance()
{
if (!instance.isValid())
return;
if (Is3d)
{
Destroy(_steamAudioSource);
RuntimeManager.DetachInstanceFromGameObject(instance);
}
instance.release();
instance.clearHandle();
}
public void SetParameters(params EventParameter[] parameters)
{
foreach (EventParameter parameter in parameters)
{
if (!string.IsNullOrEmpty(parameter.ValueLabel))
instance.setParameterByNameWithLabel(parameter.Name, parameter.ValueLabel);
else
instance.setParameterByName(parameter.Name, parameter.Value);
}
}
public void Play(params EventParameter[] parameters)
{
if (EventReference.IsNull)
{
if (_defaultEventReference.IsNull)
{
Debug.LogError("EventReference is null. Nothing to play.");
return;
}
SetEventReference(_defaultEventReference);
}
if (!instance.isValid())
AcquireInstance();
SetParameters(parameters);
UpdateInstance();
instance.start();
}
public void Play(EventReference eventReference, params EventParameter[] parameters)
{
SetEventReference(eventReference);
Play(parameters);
}
public new void Play()
{
Play(new EventParameter[0]);
}
public void Stop(bool fadeOut = true, bool release = false)
{
if (instance.isValid())
instance.stop(fadeOut ? FMOD.Studio.STOP_MODE.ALLOWFADEOUT : FMOD.Studio.STOP_MODE.IMMEDIATE);
if (release)
ReleaseInstance();
}
public new void Stop()
{
Stop(true);
}
}
[Serializable]
public struct EventParameter
{
public string Name;
public float Value;
public string ValueLabel;
}
using UnityEditor;
[CustomEditor(typeof(SpatialAudioSource))]
public class SpatialAudioSourceEditor : Editor
{
private SerializedProperty _defaultEventReference;
private SerializedProperty _is3d;
private SerializedProperty _keepAlive;
private SerializedProperty _playOnStart;
void OnEnable()
{
_defaultEventReference = serializedObject.FindProperty("_defaultEventReference");
_is3d = serializedObject.FindProperty("Is3d");
_keepAlive = serializedObject.FindProperty("KeepAlive");
_playOnStart = serializedObject.FindProperty("PlayOnStart");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
EditorGUILayout.PropertyField(_defaultEventReference);
EditorGUILayout.PropertyField(_is3d);
EditorGUILayout.PropertyField(_keepAlive);
EditorGUILayout.PropertyField(_playOnStart);
serializedObject.ApplyModifiedProperties();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment