SpatialAudioCalculatorVideoPlayerWebGL.cs 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using MarksAssets.VideoPlayerWebGL;
  5. public class SpatialAudioCalculatorVideoPlayerWebGL : MonoBehaviour
  6. {
  7. [Tooltip("Volume of audio source when you are close to it (closer than 'Distance Begin Falloff Curve').")]
  8. [Range(0.0f, 1.0f)] public float maxVolume = 1.0f;
  9. [Tooltip("Distance where the smooth falloff curve begins. If distance is less than this, we are at full volume.")]
  10. public float distanceBeginFalloffCurve = 3.0f;
  11. [Tooltip("Distance where smooth falloff curve ends. If distance is greater than this, we are at zero volume.")]
  12. public float distanceEndFalloffCurve = 10.0f;
  13. [Header("References")]
  14. [Tooltip("The position of this transform is used to calculate spatial audio in relation to the active Audio Listener in the scene. If you want audio to come from the video screen, place this transform at the very center of the video screen.")]
  15. public Transform audioSourceTransform;
  16. [Header("Debug")]
  17. [SerializeField] [Range(0.0f, 1.0f)] private float currentVolume = 0.0f;
  18. [SerializeField] [Range(-1.0f, 1.0f)] private float currentPan = 0.0f;
  19. // Private variables
  20. private AudioListener audioListener;
  21. private VideoPlayerWebGL videoPlayerWebGL;
  22. private void Start()
  23. {
  24. if (videoPlayerWebGL == null)
  25. videoPlayerWebGL = GetComponent<VideoPlayerWebGL>();
  26. if (videoPlayerWebGL == null)
  27. {
  28. if (Application.isEditor)
  29. Debug.LogError("'SpatialAudioCalculatorVideoPlayerWebGL' script must be attached to the same game object as the VideoPlayerWebGL script.");
  30. }
  31. else
  32. {
  33. videoPlayerWebGL.ForceMono(true); // Ensure that we are panning a mono audio source (required for correct 3D audio spatialization).
  34. }
  35. }
  36. private void Update()
  37. {
  38. if (videoPlayerWebGL != null && videoPlayerWebGL.enabled)
  39. UpdateSpatialAudio();
  40. }
  41. private void UpdateSpatialAudio()
  42. {
  43. if (audioListener == null || !audioListener.enabled || !audioListener.gameObject.activeInHierarchy)
  44. audioListener = GetActiveAudioListener(); // Get the active audio listener in the scene (if neccessary).
  45. if (audioListener == null) // If there is no active audio listener in the scene, set the volume to zero (no need to adjust pan).
  46. {
  47. currentVolume = 0.0f;
  48. }
  49. else
  50. {
  51. currentVolume = GetProximityVolume();
  52. if (currentVolume > 0.0f) // Only calculate pan if we can actually hear the audio source.
  53. currentPan = GetPan();
  54. }
  55. videoPlayerWebGL.Volume(currentVolume);
  56. videoPlayerWebGL.Pan(currentPan);
  57. }
  58. private float GetPan() // Source (public article from Agora): https://www.agora.io/en/blog/implementing-spatial-audio-chat-in-unity-using-agora/
  59. {
  60. Vector3 directionToAudioSource = audioSourceTransform.position - audioListener.transform.position;
  61. directionToAudioSource.Normalize();
  62. float pan = Vector3.Dot(audioListener.transform.right, directionToAudioSource);
  63. return pan;
  64. }
  65. private float GetProximityVolume()
  66. {
  67. float distance = Vector3.Distance(audioListener.transform.position, audioSourceTransform.position);
  68. float calculatedVolume;
  69. if (distance >= distanceEndFalloffCurve) // Zero volume if audio listener is further than end falloff distance.
  70. calculatedVolume = 0.0f;
  71. else if (distance <= distanceBeginFalloffCurve) // Max volume if audio listener is closer than the begin falloff distance.
  72. calculatedVolume = 1.0f * maxVolume;
  73. else // Otherwise, calculate the falloff curve using the Mathf.SmoothStep function for a smooth transition.
  74. {
  75. float falloffCurveVolume = Mathf.SmoothStep(1.0f, 0.0f, (distance - distanceBeginFalloffCurve) / (distanceEndFalloffCurve - distanceBeginFalloffCurve)); // A smooth 1 to 0 as user gets further away.
  76. calculatedVolume = falloffCurveVolume * maxVolume;
  77. }
  78. return calculatedVolume;
  79. }
  80. private AudioListener GetActiveAudioListener()
  81. {
  82. AudioListener[] audioListenersInScene = GameObject.FindObjectsOfType<AudioListener>();
  83. for (int i = 0; i < audioListenersInScene.Length; i++)
  84. {
  85. if (audioListenersInScene[i].enabled && audioListenersInScene[i].gameObject.activeInHierarchy)
  86. return audioListenersInScene[i]; // Find an enabled audio listener.
  87. }
  88. return null; // Return null if no active audio lister was found.
  89. }
  90. }