Last active
October 6, 2023 18:23
-
-
Save athiedmann/e139f73f66813060caa1921c7c6a8fda to your computer and use it in GitHub Desktop.
The "EllenWwiseFootstepManager" script in Unity handles Ellen's footsteps and landing sounds based on detected ground materials using Wwise Switches. Add "Material: Stone" to appropriate layers in-game.
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 UnityEngine; | |
public class EllenWwiseManager : MonoBehaviour | |
{ | |
// Enum to represent different material type | |
#if UNITY_EDITOR | |
private enum CURRENT_MATERIAL { STONE, PUDDLE, GRASS, EARTH, VEGETATION }; | |
#endif | |
[Header("Wwise Events")] | |
[SerializeField] private AK.Wwise.Event ellenFootsteps; | |
[SerializeField] private AK.Wwise.Event ellenLanding; | |
[Header("Material Check")] | |
#if UNITY_EDITOR | |
[SerializeField] private CURRENT_MATERIAL currentMaterial; // Displays current material detected in Editor | |
#endif | |
[SerializeField] AK.Wwise.Switch[] groundMaterialSwitch; // Array of Wwise switches for ground material | |
private void FixedUpdate() | |
{ | |
MaterialCheck(); | |
} | |
#region Ellen's Methods | |
/// <summary> | |
/// Called by animation events | |
/// </summary> | |
void PlayFootstepsEvent() | |
{ | |
if (ellenFootsteps.IsValid()) | |
ellenFootsteps.Post(gameObject); | |
else | |
{ | |
Debug.LogWarning($"No event assigned to ellenFootsteps at {gameObject.name}"); | |
} | |
} | |
/// <summary> | |
/// Called by animation events | |
/// </summary> | |
/// <param name="landingType">Has a value of 0 for "Idle", 1 for "Run", 2 for "Run_Fast", 3 for "Walk"</param> | |
void PlayLandingEvent(int landingType) | |
{ | |
if (ellenLanding.IsValid()) | |
{ | |
switch (landingType) | |
{ | |
case 0: | |
AkSoundEngine.SetSwitch("PlayerLandingSwitch", "Idle", gameObject); | |
ellenLanding.Post(gameObject); | |
break; | |
case 1: | |
AkSoundEngine.SetSwitch("PlayerLandingSwitch", "Run", gameObject); | |
ellenLanding.Post(gameObject); | |
break; | |
case 2: | |
AkSoundEngine.SetSwitch("PlayerLandingSwitch", "Run_Fast", gameObject); | |
ellenLanding.Post(gameObject); | |
break; | |
case 3: | |
AkSoundEngine.SetSwitch("PlayerLandingSwitch", "Walk", gameObject); | |
ellenLanding.Post(gameObject); | |
break; | |
default: | |
break; | |
} | |
} | |
else | |
{ | |
Debug.LogWarning($"No event assigned to ellenLanding at {gameObject.name}"); | |
return; | |
} | |
} | |
// Perform material check based on raycast hits | |
private void MaterialCheck() | |
{ | |
RaycastHit[] hits = Physics.RaycastAll(transform.position, Vector3.down, 0.1f); | |
int environmentLayer = LayerMask.NameToLayer("Environment"); | |
int waterGeometryLayer = LayerMask.NameToLayer("WaterGeometry"); | |
int vegetationLayer = LayerMask.NameToLayer("Vegetation"); | |
int setDressingLayer = LayerMask.NameToLayer("SetDressing"); | |
AK.Wwise.Switch switchToSet = null; // Variable to store the switch to set | |
foreach (RaycastHit hit in hits) | |
{ | |
GameObject hitObject = hit.transform.gameObject; | |
int hitLayer = hitObject.layer; | |
string hitTag = hit.collider.tag; | |
if (hitLayer == environmentLayer) | |
{ | |
if (hitTag == "Material: Stone") | |
{ | |
#if UNITY_EDITOR | |
currentMaterial = CURRENT_MATERIAL.STONE; | |
#endif | |
switchToSet = groundMaterialSwitch[3]; | |
} | |
else | |
{ | |
#if UNITY_EDITOR | |
currentMaterial = CURRENT_MATERIAL.EARTH; | |
#endif | |
switchToSet = groundMaterialSwitch[0]; | |
} | |
} | |
else if (hitLayer == waterGeometryLayer) | |
{ | |
#if UNITY_EDITOR | |
currentMaterial = CURRENT_MATERIAL.GRASS; | |
#endif | |
switchToSet = groundMaterialSwitch[1]; | |
} | |
else if (hitLayer == vegetationLayer) | |
{ | |
#if UNITY_EDITOR | |
currentMaterial = CURRENT_MATERIAL.VEGETATION; | |
#endif | |
switchToSet = groundMaterialSwitch[1]; | |
} | |
else if (hitLayer == setDressingLayer) | |
{ | |
#if UNITY_EDITOR | |
currentMaterial = CURRENT_MATERIAL.VEGETATION; | |
#endif | |
switchToSet = groundMaterialSwitch[1]; | |
} | |
else | |
{ | |
#if UNITY_EDITOR | |
currentMaterial = CURRENT_MATERIAL.STONE; | |
#endif | |
switchToSet = groundMaterialSwitch[3]; | |
} | |
} | |
// Set the switch outside the loop | |
if (switchToSet != null) | |
{ | |
switchToSet.SetValue(gameObject); | |
} | |
} | |
#endregion | |
} | |
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 UnityEngine; | |
using System.Collections; | |
//////////////////////////////////////////////////////////////////////// | |
// | |
// Adapted and modified version of Volumetric Script from Wwise 301 | |
// | |
//////////////////////////////////////////////////////////////////////// | |
[RequireComponent(typeof(Collider))] | |
public class EventPositionConfiner : MonoBehaviour | |
{ | |
[Header("Event to clamp to AkAudioListener")] | |
public AK.Wwise.Event Event; | |
[Header("Settings")] | |
public float UpdateInterval = 0.05f; | |
public bool isAkRoomAware = false; | |
private BoxCollider trigger; | |
private Transform targetTransform; | |
private GameObject eventEmitter; | |
private Coroutine positionClamperRoutine; | |
private void Awake() | |
{ | |
trigger = GetComponent<BoxCollider>(); | |
trigger.isTrigger = true; | |
CreateEventEmitter(); | |
} | |
private void CreateEventEmitter() | |
{ | |
eventEmitter = new GameObject("Clamped Emitter"); | |
eventEmitter.transform.parent = transform; | |
Rigidbody Rigidboody = eventEmitter.AddComponent<Rigidbody>(); | |
Rigidboody.isKinematic = true; | |
SphereCollider SPC = eventEmitter.AddComponent<SphereCollider>(); | |
SPC.isTrigger = true; | |
eventEmitter.AddComponent<AkGameObj>(); | |
if (isAkRoomAware) | |
{ | |
eventEmitter.AddComponent<AkRoomAwareObject>(); | |
} | |
} | |
private void Start() | |
{ | |
FindListener(); | |
InitializeEmitter(); | |
StartClampingPosition(); | |
} | |
private void FindListener() | |
{ | |
var listenerGameObject = FindObjectOfType<AkAudioListener>(); | |
if (listenerGameObject != null) | |
{ | |
targetTransform = listenerGameObject.transform; | |
} | |
else | |
{ | |
Debug.LogError(this + ": No GameObject with 'AkAudioListener' Component found — Bailing."); | |
enabled = false; | |
} | |
} | |
private void InitializeEmitter() | |
{ | |
Event.Post(eventEmitter); | |
} | |
private void StartClampingPosition() | |
{ | |
positionClamperRoutine = StartCoroutine(ClampEmitterPosition()); | |
} | |
private IEnumerator ClampEmitterPosition() | |
{ | |
while (true) | |
{ | |
Vector3 closestPoint = trigger.ClosestPoint(targetTransform.position); | |
eventEmitter.transform.position = closestPoint; | |
yield return new WaitForSecondsRealtime(UpdateInterval); | |
} | |
} | |
public void OnDisable() | |
{ | |
Event.Stop(eventEmitter); | |
if (positionClamperRoutine != null) | |
{ | |
StopCoroutine(positionClamperRoutine); | |
} | |
} | |
#if UNITY_EDITOR | |
private void OnDrawGizmos() | |
{ | |
Gizmos.color = Color.blue; | |
if (eventEmitter != null) | |
{ | |
Gizmos.DrawSphere(eventEmitter.transform.position, 0.2f); | |
} | |
} | |
#endif | |
} |
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 UnityEngine; | |
//////////////////////////////////////////////////////////////////////// | |
// | |
// From liortal's script that was posted in the Unity forum | |
// | |
//////////////////////////////////////////////////////////////////////// | |
/// <summary> | |
/// A logger that wraps Unity's internal logger. | |
/// Calls to its methods are stripped in case the LOGGER_SYMBOL is not defined. | |
/// In Project Settings under Scripting Define Symbols, add ENABLE_LOG. Remove when building. | |
/// </summary> | |
public sealed class Logger | |
{ | |
public const string LOGGER_SYMBOL = "ENABLE_LOG"; | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void Log(object message) | |
{ | |
Debug.Log(message); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void Log(object message, Object context) | |
{ | |
Debug.Log(message, context); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogFormat(string message, params object[] args) | |
{ | |
Debug.LogFormat(message, args); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogFormat(Object context, string message, params object[] args) | |
{ | |
Debug.LogFormat(context, message, args); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogWarning(object message) | |
{ | |
Debug.LogWarning(message); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogWarning(object message, Object context) | |
{ | |
Debug.LogWarning(message, context); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogWarningFormat(string message, params object[] args) | |
{ | |
Debug.LogWarningFormat(message, args); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogWarningFormat(Object context, string message, params object[] args) | |
{ | |
Debug.LogWarningFormat(context, message, args); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogError(object message) | |
{ | |
Debug.LogError(message); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogError(object message, Object context) | |
{ | |
Debug.LogError(message, context); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogErrorFormat(string message, params object[] args) | |
{ | |
Debug.LogErrorFormat(message, args); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogErrorFormat(Object context, string message, params object[] args) | |
{ | |
Debug.LogErrorFormat(context, message, args); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogException(System.Exception exception) | |
{ | |
Debug.LogException(exception); | |
} | |
[System.Diagnostics.Conditional(LOGGER_SYMBOL)] | |
public static void LogException(System.Exception exception, Object context) | |
{ | |
Debug.LogException(exception, context); | |
} | |
} |
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 UnityEngine; | |
//Uses Logger.cs, there's a commented version using the Unity Debugger wrapped in a region below | |
public class WwiseAmbientOcclusion : MonoBehaviour | |
{ | |
#if UNITY_EDITOR | |
public bool DebugScript = false; | |
#endif | |
public GameObject AudioListener; | |
public GameObject[] WwiseReverbZones; | |
public AK.Wwise.RTPC[] OcclusionsRTPC; | |
public float LowPass_Max = 1; | |
public float Volume_Max = 1; | |
public string NameOfListener = "ListenerName"; | |
private AK.Wwise.RTPC setRTPCLoPass; | |
private AK.Wwise.RTPC setRTPCVolume; | |
private Collider[] reverbZoneColliders; | |
private bool lastOcclusionState = false; | |
private void Awake() | |
{ | |
if (!enabled) | |
{ | |
Destroy(this); | |
return; | |
} | |
SetupChecks(); | |
GetReverbZoneColliders(); | |
} | |
void SetupChecks() | |
{ | |
if (WwiseReverbZones.Length == 0) | |
{ | |
Logger.LogError("Error — Set the WwiseReverbZones array — bailing"); | |
enabled = false; | |
return; | |
} | |
if (OcclusionsRTPC.Length == 2) | |
{ | |
setRTPCLoPass = OcclusionsRTPC[0]; | |
setRTPCVolume = OcclusionsRTPC[1]; | |
} | |
else if (OcclusionsRTPC.Length > 2) | |
{ | |
Logger.LogWarning($"Remember to set additional RTPC's within the Perform/NoPerformOcclusion() functions of {this.name}"); | |
setRTPCLoPass = OcclusionsRTPC[0]; | |
setRTPCVolume = OcclusionsRTPC[1]; | |
} | |
else if (OcclusionsRTPC.Length < 2) | |
{ | |
Logger.LogWarning("Occlusion array not set, returning"); | |
enabled = false; | |
return; | |
} | |
} | |
void GetReverbZoneColliders() | |
{ | |
reverbZoneColliders = new Collider[WwiseReverbZones.Length]; | |
for (int i = 0; i < WwiseReverbZones.Length; i++) | |
{ | |
GameObject reverbZone = WwiseReverbZones[i]; | |
if (reverbZone != null) | |
{ | |
reverbZoneColliders[i] = reverbZone.GetComponent<Collider>(); | |
} | |
} | |
} | |
private void Start() | |
{ | |
if (AudioListener == null || reverbZoneColliders.Length == 0) | |
{ | |
if (DebugScript) Logger.Log("Returning WwiseAmbientOcclusion, check that AudioListener or Wwise Reverb Zones are properly assigned."); | |
enabled = false; | |
return; | |
} | |
AkSoundEngine.RegisterGameObj(gameObject); | |
} | |
private void Update() | |
{ | |
bool currentOcclusionState = OcclusionCheck(); | |
if (currentOcclusionState != lastOcclusionState) | |
{ | |
if (DebugScript) Logger.Log($"{this} occlusion state has changed, setting new state"); | |
switch (currentOcclusionState) | |
{ | |
case true: | |
PerformOcclusion(); | |
break; | |
case false: | |
PerformNoOcclusion(); | |
break; | |
} | |
lastOcclusionState = currentOcclusionState; | |
if (DebugScript) Logger.Log($"LastOcclusionState set to {lastOcclusionState}"); | |
} | |
else | |
{ | |
if (DebugScript) Logger.Log($"{this} occlusion state hasn't changed, returning"); | |
return; | |
} | |
} | |
bool OcclusionCheck() | |
{ | |
bool isOccluded = false; // Track the occlusion state | |
foreach (Collider zoneTriggerCollider in reverbZoneColliders) | |
{ | |
if (zoneTriggerCollider != null && zoneTriggerCollider.bounds.Contains(AudioListener.transform.position)) | |
{ | |
isOccluded = true; // Update the occlusion state | |
if (DebugScript) Logger.Log("player within occlusion zone"); | |
break; // No need to check the remaining colliders if occlusion is already detected | |
} | |
} | |
return isOccluded; | |
} | |
void PerformOcclusion() | |
{ | |
if (DebugScript) | |
Logger.Log("Performing Occlusion"); | |
setRTPCLoPass.SetValue(gameObject, LowPass_Max); | |
setRTPCVolume.SetValue(gameObject, Volume_Max); | |
} | |
void PerformNoOcclusion() | |
{ | |
if (DebugScript) | |
Logger.Log("No Occlusion Performing"); | |
setRTPCLoPass.SetValue(gameObject, 0); | |
setRTPCVolume.SetValue(gameObject, 0); | |
} | |
} | |
#region UnityDebugLogScript | |
//using UnityEngine; | |
//public class WwiseAmbientOcclusion : MonoBehaviour | |
//{ | |
//#if UNITY_EDITOR | |
// public bool DebugScript = false; | |
//#endif | |
// [Header("Playback Settings")] | |
// public GameObject AudioListener; | |
// public GameObject[] WwiseReverbZones; | |
// public AK.Wwise.RTPC[] OcclusionsRTPC; | |
// public float LowPass_Max = 1; | |
// public float Volume_Max = 1; | |
// public string NameOfListener = "CameraBrain"; | |
// private AK.Wwise.RTPC setRTPCLoPass; | |
// private AK.Wwise.RTPC setRTPCVolume; | |
// private Collider[] reverbZoneColliders; | |
// private bool lastOcclusionState = false; | |
// private void Awake() | |
// { | |
// if (!enabled) | |
// { | |
// Destroy(this); | |
// return; | |
// } | |
// SetupChecks(); | |
// GetReverbZoneColliders(); | |
// } | |
// void SetupChecks() | |
// { | |
// if (WwiseReverbZones.Length == 0) | |
// { | |
//#if UNITY_EDITOR | |
// Debug.LogError("Error — Set the WwiseReverbZones array — bailing"); | |
//#endif | |
// enabled = false; | |
// return; | |
// } | |
// | |
// if (OcclusionsRTPC.Length == 2) | |
// { | |
// setRTPCLoPass = OcclusionsRTPC[0]; | |
// setRTPCVolume = OcclusionsRTPC[1]; | |
// } | |
// else if (OcclusionsRTPC.Length > 2) | |
// { | |
//#if UNITY_EDITOR | |
// Debug.LogWarning($"Remember to set additional RTPC's within the Perform/NoPerformOcclusion() functions of {this.name}"); | |
//#endif | |
// setRTPCLoPass = OcclusionsRTPC[0]; | |
// setRTPCVolume = OcclusionsRTPC[1]; | |
// } | |
// else if (OcclusionsRTPC.Length < 2) | |
// { | |
//#if UNITY_EDITOR | |
// Debug.LogWarning("Occlusion array not set, returning"); | |
//#endif | |
// enabled = false; | |
// return; | |
// } | |
// } | |
// void GetReverbZoneColliders() | |
// { | |
// reverbZoneColliders = new Collider[WwiseReverbZones.Length]; | |
// for (int i = 0; i < WwiseReverbZones.Length; i++) | |
// { | |
// GameObject reverbZone = WwiseReverbZones[i]; | |
// if (reverbZone != null) | |
// { | |
// reverbZoneColliders[i] = reverbZone.GetComponent<Collider>(); | |
// } | |
// } | |
// } | |
// private void Start() | |
// { | |
// if (AudioListener == null || reverbZoneColliders.Length == 0) | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log("Returning WwiseAmbientOcclusion, check that AudioListener or Wwise Reverb Zones are properly assigned."); | |
//#endif | |
// enabled = false; | |
// return; | |
// } | |
// AkSoundEngine.RegisterGameObj(gameObject); | |
// } | |
// private void Update() | |
// { | |
// bool currentOcclusionState = OcclusionCheck(); | |
// if (currentOcclusionState != lastOcclusionState) | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log($"{this} occlusion state has changed, setting new state"); | |
//#endif | |
// switch (currentOcclusionState) | |
// { | |
// case true: | |
// PerformOcclusion(); | |
// break; | |
// case false: | |
// PerformNoOcclusion(); | |
// break; | |
// } | |
// lastOcclusionState = currentOcclusionState; | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log($"LastOcclusionState set to {lastOcclusionState}"); | |
//#endif | |
// } | |
// else | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log($"{this} occlusion state hasn't changed, returning"); | |
//#endif | |
// return; | |
// } | |
// } | |
// bool OcclusionCheck() | |
// { | |
// bool isOccluded = false; // Track the occlusion state | |
// foreach (Collider zoneTriggerCollider in reverbZoneColliders) | |
// { | |
// if (zoneTriggerCollider != null && zoneTriggerCollider.bounds.Contains(AudioListener.transform.position)) | |
// { | |
// isOccluded = true; // Update the occlusion state | |
// BypassPlugInEffectsRTPCs(isOccluded, zoneTriggerCollider.name); | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log("player within occlusion zone"); | |
//#endif | |
// break; // No need to check the remaining colliders if occlusion is already detected | |
// } | |
// } | |
// return isOccluded; | |
// } | |
// void PerformOcclusion() | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log("Performing Occlusion"); | |
//#endif | |
// setRTPCLoPass.SetValue(gameObject, LowPass_Max); | |
// setRTPCVolume.SetValue(gameObject, Volume_Max); | |
// } | |
// void PerformNoOcclusion() | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log("No Occlusion Performing"); | |
//#endif | |
// setRTPCLoPass.SetValue(gameObject, 0); | |
// setRTPCVolume.SetValue(gameObject, 0); | |
// AkSoundEngine.SetRTPCValue("RTPC_BypassEffect", 0); | |
// AkSoundEngine.SetRTPCValue("RTPC_BypassEffect_Outdoor", 0); | |
// } | |
// void BypassPlugInEffectsRTPCs(bool isOccluding, string regionName) | |
// { | |
// if (isOccluding) | |
// { | |
// switch (regionName) | |
// { | |
// case "SwitchCavern": | |
//#if UNITY_EDITOR | |
// if (DebugScript) Debug.Log("Bypass RTPC called values called"); | |
//#endif | |
// AkSoundEngine.SetRTPCValue("RTPC_BypassEffect", 1); | |
// AkSoundEngine.SetRTPCValue("RTPC_BypassEffect_Outdoor", 1); | |
// break; | |
// default: | |
// AkSoundEngine.SetRTPCValue("RTPC_BypassEffect", 1); | |
// return; | |
// } | |
// } | |
// else | |
// { | |
// return; | |
// } | |
// } | |
//} | |
#endregion |
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 UnityEngine; | |
public class WwiseLoopEvents : MonoBehaviour | |
{ | |
#if UNITY_EDITOR | |
[SerializeField] bool DebugScript; | |
#endif | |
[Header("Playback Settings")] | |
[SerializeField] bool playOnStart; | |
[SerializeField] bool akTriggerEnterExit; | |
[SerializeField] bool addRigidbody = true; | |
[SerializeField] float maxAttenuationDistance = 20.0f; // Manually defined maximum attenuation distance, set it equivalent to the max value of the Wwise attenuation | |
[Header("Wwise Events")] | |
[SerializeField] AK.Wwise.Event playLoopEvent; | |
[SerializeField] AK.Wwise.Event stopLoopEvent; | |
[Header("Trigger Object (only one needed if using AkTriggerEnter)")] | |
[SerializeField] string triggerObjectTagName = "Player"; | |
[SerializeField] GameObject triggerGameObject; | |
private SphereCollider sphereCollider; | |
private Rigidbody AkRigidbody; | |
private void Awake() | |
{ | |
InitializeTriggerColliderFromAttenuation(); | |
SetOrAddRigidbody(); | |
} | |
// Creates and sets sphere collider radius | |
private void InitializeTriggerColliderFromAttenuation() | |
{ | |
if (akTriggerEnterExit) | |
{ | |
sphereCollider = GetComponent<SphereCollider>(); | |
if (sphereCollider == null) | |
{ | |
Logger.LogWarning($"Sphere collider added during runtime at {gameObject.name}"); | |
sphereCollider = gameObject.AddComponent<SphereCollider>(); | |
} | |
sphereCollider.isTrigger = true; | |
sphereCollider.radius = maxAttenuationDistance; | |
} | |
else | |
{ | |
sphereCollider = null; | |
return; | |
} | |
Logger.Log($"Sphere collider initialized at {gameObject.name}"); | |
} | |
// Creates and initializes Rigidbody | |
private void SetOrAddRigidbody() | |
{ | |
AkRigidbody = GetComponent<Rigidbody>(); | |
if (AkRigidbody == null) | |
{ | |
if (!addRigidbody) | |
{ | |
AkRigidbody = null; | |
return; | |
} | |
AkRigidbody = gameObject.AddComponent<Rigidbody>(); // Add the Rigidbody component dynamically if it doesn't exist | |
Logger.LogWarning($"Rigidbody added during runtime for {gameObject.name}"); | |
} | |
AkRigidbody.useGravity = false; | |
AkRigidbody.isKinematic = true; | |
if (DebugScript) Logger.Log($"Rigidbody set at {gameObject.name}"); | |
} | |
private void Start() | |
{ | |
if (!playLoopEvent.IsValid()) | |
{ | |
if (DebugScript) Logger.LogWarning($"No Wwise Play Loop Event assigned at {gameObject.name}."); | |
return; | |
} | |
if (playOnStart) | |
{ | |
PlayLoopEvent(); | |
if (DebugScript) Logger.Log($"Playing Wwise event on start at {gameObject.name}"); | |
} | |
} | |
private void OnTriggerEnter(Collider other) | |
{ | |
if (akTriggerEnterExit && (other.gameObject.CompareTag(triggerObjectTagName) || other.gameObject == triggerGameObject)) | |
{ | |
if (DebugScript) Logger.Log($"Player detected in {gameObject.name} audio trigger area"); | |
PlayLoopEvent(); | |
} | |
} | |
private void OnTriggerExit(Collider other) | |
{ | |
if (akTriggerEnterExit && (other.gameObject.tag == triggerObjectTagName || other.gameObject == triggerGameObject)) | |
{ | |
if (DebugScript) Logger.Log($"Player left the {gameObject.name} audio trigger area"); | |
StopLoopEvent(); | |
} | |
} | |
public void PlayLoopEvent() | |
{ | |
if (!playLoopEvent.IsValid()) | |
{ | |
return; | |
} | |
playLoopEvent.Post(gameObject); | |
if (DebugScript) Logger.Log($"Wwise Play event posted at {gameObject.name}"); | |
} | |
public void StopLoopEvent() | |
{ | |
if (!playLoopEvent.IsValid()) | |
{ | |
return; | |
} | |
if (!stopLoopEvent.IsValid()) | |
{ | |
if (DebugScript) Logger.LogWarning($"No Wwise Stop Loop Event assigned at {gameObject.name}, stopping Play Loop Event directly"); | |
playLoopEvent.Stop(gameObject); | |
} | |
else | |
{ | |
if (DebugScript) Logger.Log($"Wwise Stop event posted at {gameObject.name}"); | |
stopLoopEvent.Post(gameObject); | |
} | |
} | |
// Call method to stop looping forever if a condition is met in-game | |
public void DestroySphereColliderAndStopEvent() | |
{ | |
StopLoopEvent(); | |
Destroy(sphereCollider); | |
if (DebugScript) Logger.Log($"Destroyed sphere collider and stopped event at {gameObject.name}"); | |
Destroy(this); | |
} | |
} | |
#region UnityDebugLogScript | |
//using UnityEngine; | |
//public class WwiseLoopEvents : MonoBehaviour | |
//{ | |
//#if UNITY_EDITOR | |
// [SerializeField] bool DebugScript; | |
//#endif | |
// [Header("Playback Settings")] | |
// [SerializeField] bool playOnStart; | |
// [SerializeField] bool akTriggerEnterExit; | |
// [SerializeField] bool addRigidbody = true; | |
// [SerializeField] float maxAttenuationDistance = 20.0f; // Manually defined maximum attenuation distance, set it equivalent to the max value of the Wwise attenuation | |
// [Header("Wwise Events")] | |
// [SerializeField] AK.Wwise.Event playLoopEvent; | |
// [SerializeField] AK.Wwise.Event stopLoopEvent; | |
// [Header("Trigger Object (only one needed if using AkTriggerEnter)")] | |
// [SerializeField] string triggerObjectTagName = "Player"; | |
// [SerializeField] GameObject triggerGameObject; | |
// private SphereCollider sphereCollider; | |
// private Rigidbody AkRigidbody; | |
// private void Awake() | |
// { | |
// InitializeTriggerColliderFromAttenuation(); | |
// SetOrAddRigidbody(); | |
// } | |
// // Creates and sets sphere collider radius | |
// private void InitializeTriggerColliderFromAttenuation() | |
// { | |
// if (akTriggerEnterExit) | |
// { | |
// sphereCollider = GetComponent<SphereCollider>(); | |
// if (sphereCollider == null) | |
// { | |
//#if UNITY_EDITOR | |
// DebugMessage($"Sphere collider added during runtime at {gameObject.name}", 1); | |
//#endif | |
// sphereCollider = gameObject.AddComponent<SphereCollider>(); | |
// } | |
// sphereCollider.isTrigger = true; | |
// sphereCollider.radius = maxAttenuationDistance; | |
// } | |
// else | |
// { | |
// sphereCollider = null; | |
// return; | |
// } | |
//#if UNITY_EDITOR | |
// DebugMessage($"Sphere collider initialized at {gameObject.name}", 0); | |
//#endif | |
// } | |
// // Creates and initializes Rigidbody | |
// private void SetOrAddRigidbody() | |
// { | |
// AkRigidbody = GetComponent<Rigidbody>(); | |
// if (AkRigidbody == null) | |
// { | |
// if (!addRigidbody) | |
// { | |
// AkRigidbody = null; | |
// return; | |
// } | |
// AkRigidbody = gameObject.AddComponent<Rigidbody>(); // Add the Rigidbody component dynamically if it doesn't exist | |
//#if UNITY_EDITOR | |
// DebugMessage($"Rigidbody added during runtime for {gameObject.name}", 1); | |
//#endif | |
// } | |
// AkRigidbody.useGravity = false; | |
// AkRigidbody.isKinematic = true; | |
//#if UNITY_EDITOR | |
// DebugMessage($"Rigidbody set at {gameObject.name}", 0); | |
//#endif | |
// } | |
// private void Start() | |
// { | |
// if (!playLoopEvent.IsValid()) | |
// { | |
// DebugMessage($"No Wwise Play Loop Event assigned at {gameObject.name}.", 2); | |
// return; | |
// } | |
// if (playOnStart) | |
// { | |
// PlayLoopEvent(); | |
//#if UNITY_EDITOR | |
// DebugMessage($"Playing Wwise event on start at {gameObject.name}", 0); | |
//#endif | |
// } | |
// } | |
// private void OnTriggerEnter(Collider other) | |
// { | |
// if (akTriggerEnterExit && (other.gameObject.CompareTag(triggerObjectTagName) || other.gameObject == triggerGameObject)) | |
// { | |
//#if UNITY_EDITOR | |
// DebugMessage($"Player detected in {gameObject.name} audio trigger area", 0); | |
//#endif | |
// PlayLoopEvent(); | |
// } | |
// } | |
// private void OnTriggerExit(Collider other) | |
// { | |
// if (akTriggerEnterExit && (other.gameObject.tag == triggerObjectTagName || other.gameObject == triggerGameObject)) | |
// { | |
//#if UNITY_EDITOR | |
// DebugMessage($"Player left the {gameObject.name} audio trigger area", 0); | |
//#endif | |
// StopLoopEvent(); | |
// } | |
// } | |
// public void PlayLoopEvent() | |
// { | |
// if (!playLoopEvent.IsValid()) | |
// { | |
// return; | |
// } | |
// playLoopEvent.Post(gameObject); | |
//#if UNITY_EDITOR | |
// DebugMessage($"Wwise Play event posted at {gameObject.name}", 0); | |
//#endif | |
// } | |
// public void StopLoopEvent() | |
// { | |
// if (!playLoopEvent.IsValid()) | |
// { | |
// return; | |
// } | |
// if (!stopLoopEvent.IsValid()) | |
// { | |
//#if UNITY_EDITOR | |
// DebugMessage($"No Wwise Stop Loop Event assigned at {gameObject.name}, stopping Play Loop Event directly", 1); | |
//#endif | |
// playLoopEvent.Stop(gameObject); | |
// } | |
// else | |
// { | |
// stopLoopEvent.Post(gameObject); | |
//#if UNITY_EDITOR | |
// DebugMessage($"Wwise Stop event posted at {gameObject.name}", 0); | |
//#endif | |
// } | |
// } | |
// // Call method to stop looping forever if a condition is met in-game | |
// public void DestroySphereColliderAndStopEvent() | |
// { | |
// StopLoopEvent(); | |
// Destroy(sphereCollider); | |
//#if UNITY_EDITOR | |
// DebugMessage($"Destroyed sphere collider and stopped event at {gameObject.name}", 0); | |
//#endif | |
// Destroy(this); | |
// } | |
//#if UNITY_EDITOR | |
// /// <summary> | |
// /// Allows easy customization of the different types of debug messages | |
// /// </summary> | |
// /// <param name="debugMessage"> Pass in string </param> | |
// /// <param name="warningType"> Assign 0 for log, 1 for warning, 2 for error </param> | |
// private void DebugMessage(string debugMessage, byte warningType) | |
// { | |
// if (!DebugScript) | |
// return; | |
// switch (warningType) | |
// { | |
// case 0: | |
// Debug.Log(debugMessage); | |
// return; | |
// case 1: | |
// Debug.LogWarning(debugMessage); | |
// return; | |
// case 2: | |
// Debug.LogError(debugMessage); | |
// return; | |
// default: | |
// return; | |
// } | |
// } | |
//#endif | |
//} | |
#endregion |
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 UnityEngine; | |
//////////////////////////////////////////////////////////////////////// | |
// | |
// Adapted and modified from the Occlusion Script from Cujo Sound video "Wwise and Unity - Basic Raycasting To Create Occlusion Parameters" | |
// | |
//////////////////////////////////////////////////////////////////////// | |
//Uses Logger.cs, there's a commented version using the Unity Debugger wrapped in a region below | |
public class WwiseObjectOcclusion : MonoBehaviour | |
{ | |
#if UNITY_EDITOR | |
public bool DebugScript = false; | |
#endif | |
public bool IsInteractable = false; | |
public GameObject AudioListener; | |
public AK.Wwise.RTPC[] OcclusionsRTPC; | |
public float SetLowPassMax = 1; | |
public float SetVolumeMax = 1; | |
public string NameOfListener = "CameraBrain"; | |
public string OmitTypeOccluder; // change to array if multiple and adjust code | |
private bool lastOcclusionState = false; | |
private float maxDistanceOcclusion; | |
private SphereCollider sphereCollider; | |
private AK.Wwise.RTPC setRTPCLoPass; | |
private AK.Wwise.RTPC setRTPCVolume; | |
private void Awake() | |
{ | |
if (!enabled) | |
{ | |
Destroy(this); | |
return; | |
} | |
SetUpChecks(); | |
sphereCollider = GetComponent<SphereCollider>(); | |
maxDistanceOcclusion = sphereCollider.radius; | |
} | |
private void SetUpChecks() | |
{ | |
if (OcclusionsRTPC.Length == 2) | |
{ | |
setRTPCLoPass = OcclusionsRTPC[0]; | |
setRTPCVolume = OcclusionsRTPC[1]; | |
setRTPCLoPass.SetValue(gameObject, 0); | |
setRTPCVolume.SetValue(gameObject, 0); | |
} | |
else if (OcclusionsRTPC.Length > 2) | |
{ | |
setRTPCLoPass = OcclusionsRTPC[0]; | |
setRTPCVolume = OcclusionsRTPC[1]; | |
setRTPCLoPass.SetValue(gameObject, 0); | |
setRTPCVolume.SetValue(gameObject, 0); | |
Logger.Log($"Remember to set up the additional RTPC's within the OcclusionCheck() function of {this.name}."); | |
} | |
else | |
{ | |
Logger.LogError($"Set RTPC array with at least 2 parameters at {this.name}. Returning"); | |
enabled = false; | |
return; | |
} | |
} | |
private void Start() | |
{ | |
if (AudioListener == null || sphereCollider == null) | |
{ | |
if (DebugScript) | |
Logger.LogError($"WwiseObjectOcclusion is returning, AudioListener or sphereCollider aren't properly set on {this.name}"); | |
enabled = false; | |
return; | |
} | |
setRTPCLoPass.SetValue(gameObject, 0); | |
setRTPCVolume.SetValue(gameObject, 0); | |
AkSoundEngine.RegisterGameObj(gameObject); | |
} | |
private void FixedUpdate() | |
{ | |
OcclusionCheck(); | |
if (IsInteractable) | |
IsOneShotInteractable(); | |
} | |
void OcclusionCheck() | |
{ | |
bool currentOcclusionState = false; | |
Vector3 direction = AudioListener.transform.position - transform.position; | |
float distanceToPlayer = direction.magnitude; // Calculate the distance to the player | |
if (distanceToPlayer <= maxDistanceOcclusion) // Check if the player is within the occlusion range | |
{ | |
if (DebugScript) | |
Logger.Log("Player is within range"); | |
if (Physics.Raycast(transform.position, direction, out RaycastHit outInfo, maxDistanceOcclusion)) | |
{ | |
if (DebugScript) | |
Logger.Log(outInfo.collider.gameObject.name); | |
if (outInfo.collider.gameObject.name != NameOfListener && !outInfo.collider.gameObject.name.Contains(OmitTypeOccluder)) | |
{ | |
currentOcclusionState = true; | |
if (lastOcclusionState != currentOcclusionState) | |
{ | |
setRTPCLoPass.SetValue(gameObject, SetLowPassMax); | |
setRTPCVolume.SetValue(gameObject, SetVolumeMax); | |
lastOcclusionState = currentOcclusionState; | |
if (DebugScript) | |
Logger.Log("Occluding"); | |
} | |
} | |
else | |
{ | |
currentOcclusionState = false; | |
if (lastOcclusionState != currentOcclusionState) | |
{ | |
setRTPCLoPass.SetValue(gameObject, 0); | |
setRTPCVolume.SetValue(gameObject, 0); | |
lastOcclusionState = currentOcclusionState; | |
if (DebugScript) | |
Logger.Log("Not Occluding"); | |
} | |
} | |
if (DebugScript) | |
Logger.Log($"lastOcclusionState is {lastOcclusionState}"); | |
} | |
} | |
else | |
{ | |
if (DebugScript) | |
Logger.Log($"Player is beyond {this.name} occlusion range"); | |
if (DebugScript) | |
Logger.Log($"lastOcclusionState is {lastOcclusionState}"); | |
return; | |
} | |
} | |
private void IsOneShotInteractable() | |
{ | |
Animator objectAnimator = GetComponentInParent<Animator>(); | |
bool animatorState = objectAnimator.GetBool("Open"); | |
if (DebugScript) | |
Logger.Log($"Animator state on {this.name} is {animatorState}"); | |
if (animatorState) | |
{ | |
AkSoundEngine.UnregisterGameObj(gameObject); | |
Destroy(GetComponent<AkGameObj>()); | |
Destroy(GetComponent<Rigidbody>()); | |
Destroy(this); | |
} | |
} | |
} | |
#region UnityLogScript | |
//using UnityEngine; | |
//using Debug = UnityEngine.Debug; | |
//////////////////////////////////////////////////////////////////////// | |
// | |
// Adapted and modified from the Occlusion Script from Cujo Sound video "Wwise and Unity - Basic Raycasting To Create Occlusion Parameters" | |
// | |
//////////////////////////////////////////////////////////////////////// | |
////[RequireComponent(typeof(SphereCollider))] | |
//public class WwiseObjectOcclusion : MonoBehaviour | |
//{ | |
//#if UNITY_EDITOR | |
// public bool DebugScript = false; | |
//#endif | |
// public bool IsInteractable = false; | |
// public GameObject AudioListener; | |
// [Tooltip("Index 0: Set LowPass. Index 1: Set Volume")] | |
// public AK.Wwise.RTPC[] OcclusionsRTPC; | |
// public float SetLowPassMax = 1; | |
// public float SetVolumeMax = 1; | |
// public string NameOfListener = "CameraBrain"; | |
// public string OmitTypeOccluder; // change to array if multiple and adjust code | |
// private float maxDistanceOcclusion; | |
// private SphereCollider sphereCollider; | |
// private AK.Wwise.RTPC setRTPCLoPass; | |
// private AK.Wwise.RTPC setRTPCVolume; | |
// private void Awake() | |
// { | |
// if (!enabled) | |
// { | |
// Destroy(this); | |
// return; | |
// } | |
// SetUpChecks(); | |
// sphereCollider = GetComponent<SphereCollider>(); | |
// maxDistanceOcclusion = sphereCollider.radius; | |
// } | |
// private void SetUpChecks() | |
// { | |
// if (OcclusionsRTPC.Length == 2) | |
// { | |
// setRTPCLoPass = OcclusionsRTPC[0]; | |
// setRTPCVolume = OcclusionsRTPC[1]; | |
// setRTPCLoPass.SetValue(gameObject, 0); | |
// setRTPCVolume.SetValue(gameObject, 0); | |
// } | |
// else if (OcclusionsRTPC.Length > 2) | |
// { | |
// setRTPCLoPass = OcclusionsRTPC[0]; | |
// setRTPCVolume = OcclusionsRTPC[1]; | |
// setRTPCLoPass.SetValue(gameObject, 0); | |
// setRTPCVolume.SetValue(gameObject, 0); | |
//#if UNITY_EDITOR | |
// Debug.Log($"Remember to set up the additional RTPC's within the OcclusionCheck() function of {this.name}."); | |
//#endif | |
// } | |
// else | |
// { | |
//#if UNITY_EDITOR | |
// Debug.LogError($"Set RTPC array with at least 2 parameters at {this.name}. Returning"); | |
//#endif | |
// enabled = false; | |
// return; | |
// } | |
// } | |
// private void Start() | |
// { | |
// if (AudioListener == null || sphereCollider == null) | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) | |
// Debug.LogError($"WwiseObjectOcclusion is returning, AudioListener or sphereCollider aren't properly set on {this.name}"); | |
//#endif | |
// enabled = false; | |
// return; | |
// } | |
// AkSoundEngine.RegisterGameObj(gameObject); | |
// } | |
// private void FixedUpdate() | |
// { | |
// OcclusionCheck(); | |
// if (IsInteractable) | |
// IsOneShotInteractable(); | |
// } | |
// void OcclusionCheck() | |
// { | |
// Vector3 direction = AudioListener.transform.position - transform.position; | |
// float distanceToPlayer = direction.magnitude; // Calculate the distance to the player | |
// if (distanceToPlayer <= maxDistanceOcclusion) // Check if the player is within the occlusion range | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) | |
// Debug.Log("Player is within range"); | |
//#endif | |
// if (Physics.Raycast(transform.position, direction, out RaycastHit outInfo, maxDistanceOcclusion)) | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) | |
// Debug.Log(outInfo.collider.gameObject.name); | |
//#endif | |
// if (outInfo.collider.gameObject.name != NameOfListener && !outInfo.collider.gameObject.name.Contains(OmitTypeOccluder)) | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) | |
// Debug.Log("Occluding"); | |
//#endif | |
// setRTPCLoPass.SetValue(gameObject, SetLowPassMax); | |
// setRTPCVolume.SetValue(gameObject, SetVolumeMax); | |
// } | |
// else | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) | |
// Debug.Log("Not Occluding"); | |
//#endif | |
// setRTPCLoPass.SetValue(gameObject, 0); | |
// setRTPCVolume.SetValue(gameObject, 0); | |
// } | |
// } | |
// } | |
// else | |
// { | |
//#if UNITY_EDITOR | |
// if (DebugScript) | |
// Debug.Log($"Player is beyond {this.name} occlusion range"); | |
//#endif | |
// return; | |
// } | |
// } | |
// /// <summary> | |
// /// Configure to your project | |
// /// </summary> | |
// private void IsOneShotInteractable() | |
// { | |
// Animator objectAnimator = GetComponentInParent<Animator>(); //Or simply "GetComponent<Type>()" | |
// bool animatorState = objectAnimator.GetBool("Open"); | |
//#if UNITY_EDITOR | |
// if (DebugScript) | |
// Debug.Log($"Animator state on {this.name} is {animatorState}"); | |
//#endif | |
// if (animatorState) | |
// { | |
// Destroy(this); | |
// } | |
// } | |
//} | |
#endregion |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment