Added Unity project files
This commit is contained in:
@ -0,0 +1,181 @@
|
||||
using UnityEngine;
|
||||
using VRC.SDKBase;
|
||||
|
||||
namespace VRC.SDK3.ClientSim
|
||||
{
|
||||
[AddComponentMenu("")]
|
||||
[DisallowMultipleComponent]
|
||||
public class ClientSimSpatialAudioHelper : ONSPAudioSource
|
||||
{
|
||||
private const float EPS = 1e-3f;
|
||||
|
||||
private VRC_SpatialAudioSource _spatialAudioSource;
|
||||
private AudioSource _audioSource;
|
||||
private bool _useAudioSourceCurve;
|
||||
private ONSPAudioSource _onsp;
|
||||
private bool _forceUpdate = true;
|
||||
private bool _updateONSPParams;
|
||||
|
||||
public static void InitializeAudio(VRC_SpatialAudioSource obj)
|
||||
{
|
||||
#if UNITY_EDITOR
|
||||
// VRC_SpatialAudioSource executes in editor, meaning it will try to initialize even outside of playmode.
|
||||
// This code is to prevent adding the ClientSim helper in these cases.
|
||||
if (!UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode ||
|
||||
UnityEditor.SceneManagement.EditorSceneManager.IsPreviewSceneObject(obj))
|
||||
{
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
ClientSimSpatialAudioHelper spatialAudio = obj.GetComponent<ClientSimSpatialAudioHelper>();
|
||||
if (spatialAudio != null)
|
||||
{
|
||||
DestroyImmediate(spatialAudio);
|
||||
}
|
||||
|
||||
spatialAudio = obj.gameObject.AddComponent<ClientSimSpatialAudioHelper>();
|
||||
spatialAudio.PreventComponentFromSaving();
|
||||
spatialAudio.SetSpatializer(obj);
|
||||
}
|
||||
|
||||
private void SetSpatializer(VRC_SpatialAudioSource obj)
|
||||
{
|
||||
_spatialAudioSource = obj;
|
||||
_audioSource = GetComponent<AudioSource>();
|
||||
_onsp = this;
|
||||
_forceUpdate = true;
|
||||
|
||||
UpdateSettings();
|
||||
}
|
||||
|
||||
private void Start()
|
||||
{
|
||||
// Catch Helper not initialized.
|
||||
if (_spatialAudioSource == null)
|
||||
{
|
||||
this.LogWarning($"Destroying uninitialized Helper. Object: {Tools.GetGameObjectPath(gameObject)}");
|
||||
DestroyImmediate(this);
|
||||
}
|
||||
}
|
||||
|
||||
private void OnEnable()
|
||||
{
|
||||
// ONSP needs to reapply audio settings everytime the object is enabled.
|
||||
_forceUpdate = true;
|
||||
_updateONSPParams = true;
|
||||
}
|
||||
|
||||
// Late update to help with testing
|
||||
private void LateUpdate()
|
||||
{
|
||||
UpdateSettings();
|
||||
}
|
||||
|
||||
private void UpdateSettings()
|
||||
{
|
||||
if (_spatialAudioSource == null)
|
||||
{
|
||||
_spatialAudioSource = GetComponent<VRC_SpatialAudioSource>();
|
||||
if (_spatialAudioSource == null)
|
||||
{
|
||||
Destroy(this);
|
||||
}
|
||||
SetSpatializer(_spatialAudioSource);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if we need to make changes.
|
||||
if (
|
||||
_onsp.EnableSpatialization != _spatialAudioSource.EnableSpatialization ||
|
||||
_onsp.Gain != _spatialAudioSource.Gain ||
|
||||
_onsp.Near != _spatialAudioSource.Near ||
|
||||
_onsp.Far != _spatialAudioSource.Far ||
|
||||
_useAudioSourceCurve != _spatialAudioSource.UseAudioSourceVolumeCurve
|
||||
) {
|
||||
_forceUpdate = true;
|
||||
_updateONSPParams = true;
|
||||
}
|
||||
|
||||
_onsp.EnableSpatialization = _spatialAudioSource.EnableSpatialization;
|
||||
_onsp.Gain = _spatialAudioSource.Gain;
|
||||
_useAudioSourceCurve = _spatialAudioSource.UseAudioSourceVolumeCurve;
|
||||
_onsp.Near = _spatialAudioSource.Near;
|
||||
_onsp.Far = _spatialAudioSource.Far;
|
||||
_onsp.VolumetricRadius = _spatialAudioSource.VolumetricRadius;
|
||||
|
||||
// In unity 2022 - updating ONSP params every frame can cause a logspam
|
||||
// This is a workaround to only update when needed
|
||||
if (_updateONSPParams)
|
||||
{
|
||||
_onsp.SetParameters(ref _audioSource);
|
||||
_updateONSPParams = false;
|
||||
}
|
||||
|
||||
if (!_onsp.EnableSpatialization)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_forceUpdate)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
_forceUpdate = false;
|
||||
|
||||
if (!_spatialAudioSource.UseAudioSourceVolumeCurve)
|
||||
{
|
||||
float near = _onsp.VolumetricRadius + _onsp.Near;
|
||||
float far = _onsp.VolumetricRadius + Mathf.Max(near, _onsp.Far + EPS);
|
||||
|
||||
_audioSource.maxDistance = far;
|
||||
|
||||
CreateRolloffCurve(near, far);
|
||||
CreateSpatialCurve(near, far);
|
||||
}
|
||||
}
|
||||
|
||||
// Create volume rolloff curve where Volumetric + near is volume 1, then 2^-x fall off to far.
|
||||
private void CreateRolloffCurve(float near, float far)
|
||||
{
|
||||
_audioSource.rolloffMode = AudioRolloffMode.Custom;
|
||||
|
||||
AnimationCurve curve = new AnimationCurve();
|
||||
curve.AddKey(new Keyframe(near, 1));
|
||||
int max = 8;
|
||||
for (int loc = 1; loc < max; ++loc)
|
||||
{
|
||||
float time = near + Mathf.Pow(2, loc - max) * (far - near);
|
||||
float value = Mathf.Pow(2.2f, -loc);
|
||||
curve.AddKey(new Keyframe(time, value));
|
||||
}
|
||||
curve.AddKey(new Keyframe(far, 0));
|
||||
|
||||
for (int i = 0; i < curve.length; ++i)
|
||||
{
|
||||
curve.SmoothTangents(i, 0);
|
||||
}
|
||||
|
||||
_audioSource.SetCustomCurve(AudioSourceCurveType.CustomRolloff, curve);
|
||||
}
|
||||
|
||||
// Create spatial blend curve so that it goes from (Setting) to 3d from min to max
|
||||
private void CreateSpatialCurve(float near, float far)
|
||||
{
|
||||
AnimationCurve spatialCurve = new AnimationCurve();
|
||||
spatialCurve.AddKey(0, _audioSource.spatialBlend);
|
||||
spatialCurve.AddKey(_onsp.VolumetricRadius, _audioSource.spatialBlend);
|
||||
|
||||
Keyframe nearFrame = new Keyframe(near + EPS, 1);
|
||||
nearFrame.outTangent = 0;
|
||||
spatialCurve.AddKey(nearFrame);
|
||||
|
||||
Keyframe farFrame = new Keyframe(far, 1);
|
||||
farFrame.inTangent = 0;
|
||||
spatialCurve.AddKey(farFrame);
|
||||
|
||||
_audioSource.SetCustomCurve(AudioSourceCurveType.SpatialBlend, spatialCurve);
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user