Feat : Wwise Integration

This commit is contained in:
Alex
2026-03-23 14:28:21 +01:00
parent 627d787695
commit 004bc328ed
1149 changed files with 226567 additions and 19 deletions
@@ -0,0 +1,39 @@
{
"name": "AK.Wwise.Unity.MonoBehaviour",
"rootNamespace": "",
"references": [
"AK.Wwise.Unity.API",
"Unity.Addressables",
"Unity.ResourceManager",
"AK.Wwise.Unity.API.WwiseTypes",
"AK.Wwise.Unity.Addressables",
"AK.Wwise.Unity.ProjectDatabase",
"AK.Wwise.Unity.Utilities",
"AK.Wwise.Unity.Logging"
],
"includePlatforms": [],
"excludePlatforms": [
"Lumin",
"Stadia"
],
"allowUnsafeCode": false,
"overrideReferences": false,
"precompiledReferences": [],
"autoReferenced": true,
"defineConstraints": [
"!UNITY_SERVER"
],
"versionDefines": [
{
"name": "com.unity.addressables",
"expression": "1.8",
"define": "UNITY_ADDRESSABLES"
},
{
"name": "com.audiokinetic.wwise.addressables",
"expression": "1.0.0",
"define": "AK_WWISE_ADDRESSABLES"
}
],
"noEngineReferences": false
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 4fadb0004432d254fbccfa19b3f43341
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,328 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public enum MultiPositionTypeLabel
{
Simple_Mode,
Large_Mode,
MultiPosition_Mode
}
public class AkMultiPosEvent
{
public bool eventIsPlaying;
public System.Collections.Generic.List<AkAmbient> list = new System.Collections.Generic.List<AkAmbient>();
public void FinishedPlaying(object in_cookie, AkCallbackType in_type, object in_info)
{
eventIsPlaying = false;
}
}
[UnityEngine.AddComponentMenu("Wwise/AkAmbient")]
/// @brief Use this component to attach a Wwise Event to any object in a scene.
/// The sound can be started at various moments, dependent on the selected Unity trigger. This component is more useful for ambient sounds (sounds related to scene-bound objects) but could also be used for other purposes.
/// Since AkAmbient has AkEvent as its base class, it features the play/stop, play multiple, stop multiple and stop all buttons for previewing the associated Wwise event.
/// \sa
/// - \ref unity_use_AkEvent_AkAmbient
/// - \ref AkGameObj
/// - \ref AkEvent
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__events.html" target="_blank">Integration Details - Events</a> (Note: This is described in the Wwise SDK documentation.)
public class AkAmbient : AkEvent
{
public static System.Collections.Generic.Dictionary<uint, AkMultiPosEvent> multiPosEventTree =
new System.Collections.Generic.Dictionary<uint, AkMultiPosEvent>();
public AkMultiPositionType MultiPositionType = AkMultiPositionType.AkMultiPositionType_MultiSources;
public MultiPositionTypeLabel multiPositionTypeLabel = MultiPositionTypeLabel.Simple_Mode;
private static UnityEngine.Color SPHERE_DEFAULT_COLOR = new UnityEngine.Color(1.0f, 0.0f, 0.0f, 0.1f);
public UnityEngine.Color attenuationSphereColor= SPHERE_DEFAULT_COLOR;
public AkAmbientLargeModePositioner[] LargeModePositions;
public override void OnEnable()
{
#if UNITY_EDITOR
if (UnityEngine.Application.isBatchMode)
{
return;
}
#endif
if (multiPositionTypeLabel == MultiPositionTypeLabel.MultiPosition_Mode)
{
var gameObj = gameObject.GetComponents<AkGameObj>();
for (var i = 1; i < gameObj.Length; i++)
{
gameObj[i].enabled = false;
}
AkMultiPosEvent eventPosList;
if (multiPosEventTree.TryGetValue(data.Id, out eventPosList))
{
if (!eventPosList.list.Contains(this))
{
eventPosList.list.Add(this);
}
}
else
{
eventPosList = new AkMultiPosEvent();
eventPosList.list.Add(this);
multiPosEventTree.Add(data.Id, eventPosList);
}
var positionArray = BuildMultiDirectionArray(eventPosList);
//Set multiple positions
AkUnitySoundEngine.SetMultiplePositions(eventPosList.list[0].gameObject, positionArray, (ushort) positionArray.Count, MultiPositionType);
}
base.OnEnable();
}
protected override void Start()
{
base.Start();
if (multiPositionTypeLabel == MultiPositionTypeLabel.Simple_Mode)
{
var gameObj = gameObject.GetComponents<AkGameObj>();
for (var i = 0; i < gameObj.Length; i++)
{
gameObj[i].enabled = true;
}
}
else if (multiPositionTypeLabel == MultiPositionTypeLabel.Large_Mode)
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying || UnityEngine.Application.isBatchMode)
{
return;
}
#endif
var positionArray = BuildAkPositionArray();
AkUnitySoundEngine.SetMultiplePositions(gameObject, positionArray, (ushort)positionArray.Count, MultiPositionType);
}
}
private new void OnDisable()
{
#if UNITY_EDITOR
if (UnityEngine.Application.isBatchMode)
{
return;
}
#endif
if (multiPositionTypeLabel == MultiPositionTypeLabel.MultiPosition_Mode)
{
var eventPosList = multiPosEventTree[data.Id];
if (eventPosList.list.Count == 1)
{
multiPosEventTree.Remove(data.Id);
}
else
{
eventPosList.list.Remove(this);
var positionArray = BuildMultiDirectionArray(eventPosList);
AkUnitySoundEngine.SetMultiplePositions(eventPosList.list[0].gameObject, positionArray, (ushort) positionArray.Count, MultiPositionType);
}
}
base.OnDisable();
}
protected new void OnDestroy()
{
if (multiPositionTypeLabel != MultiPositionTypeLabel.MultiPosition_Mode)
{
base.OnDestroy();
}
}
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
if (multiPositionTypeLabel != MultiPositionTypeLabel.MultiPosition_Mode)
{
base.HandleEvent(in_gameObject);
}
else
{
var multiPositionSoundEmitter = multiPosEventTree[data.Id];
if (multiPositionSoundEmitter.eventIsPlaying)
{
return;
}
multiPositionSoundEmitter.eventIsPlaying = true;
soundEmitterObject = multiPositionSoundEmitter.list[0].gameObject;
if (enableActionOnEvent)
{
data.ExecuteAction(soundEmitterObject, actionOnEventType, (int)transitionDuration * 1000, curveInterpolation);
}
else
{
data.Post(soundEmitterObject, (uint)AkCallbackType.AK_EndOfEvent, multiPositionSoundEmitter.FinishedPlaying);
}
}
}
public void OnDrawGizmosSelected()
{
if (!enabled)
{
return;
}
UnityEngine.Gizmos.DrawIcon(transform.position, "WwiseAudioSpeaker.png", false);
#if UNITY_EDITOR
if (multiPositionTypeLabel == MultiPositionTypeLabel.Large_Mode)
{
foreach (var entry in LargeModePositions)
{
if (entry != null)
{
UnityEngine.Gizmos.color = UnityEngine.Color.green;
UnityEngine.Gizmos.DrawSphere(entry.transform.position, 0.1f);
UnityEditor.Handles.Label(entry.transform.position, entry.name);
AkRadialEmitter radialEmitter = GetComponent<AkRadialEmitter>();
if (radialEmitter)
{
UnityEngine.Color SphereColor = UnityEngine.Color.yellow;
SphereColor.a = 0.25f;
UnityEngine.Gizmos.color = SphereColor;
UnityEngine.Gizmos.DrawSphere(entry.transform.position, radialEmitter.innerRadius);
UnityEngine.Gizmos.DrawSphere(entry.transform.position, radialEmitter.outerRadius);
}
}
}
}
#endif
}
public AkPositionArray BuildMultiDirectionArray(AkMultiPosEvent eventPosList)
{
var positionArray = new AkPositionArray((uint) eventPosList.list.Count);
for (var i = 0; i < eventPosList.list.Count; i++)
{
positionArray.Add(eventPosList.list[i].transform.position, eventPosList.list[i].transform.forward,
eventPosList.list[i].transform.up);
}
return positionArray;
}
private AkPositionArray BuildAkPositionArray()
{
var validPositionList = new System.Collections.Generic.List<AkAmbientLargeModePositioner>();
for( int i= 0; i < LargeModePositions.Length; ++i)
{
if (LargeModePositions[i] != null)
{
if (!validPositionList.Contains(LargeModePositions[i]))
{
validPositionList.Add(LargeModePositions[i]);
}
}
}
var positionArray = new AkPositionArray((uint)validPositionList.Count);
for (int i = 0; i < validPositionList.Count; ++i)
{
positionArray.Add(validPositionList[i].Position, validPositionList[i].Forward, validPositionList[i].Up);
}
return positionArray;
}
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
public System.Collections.Generic.List<UnityEngine.Vector3> multiPositionArray = null;
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
public override bool Migrate(UnityEditor.SerializedObject obj)
{
var hasMigrated = base.Migrate(obj);
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.AkAmbient_v2019_1_0))
{
return hasMigrated;
}
var multiPositionTypeLabelProperty = obj.FindProperty("multiPositionTypeLabel");
if (multiPositionTypeLabelProperty == null)
{
return hasMigrated;
}
if (multiPositionTypeLabelProperty.intValue != (int)MultiPositionTypeLabel.Large_Mode)
{
return hasMigrated;
}
var multiPositionArrayProperty = obj.FindProperty("multiPositionArray");
if (multiPositionArrayProperty == null)
{
return hasMigrated;
}
if (multiPositionArrayProperty.arraySize == 0)
{
return hasMigrated;
}
var largeModePositionsProperty = obj.FindProperty("LargeModePositions");
if (largeModePositionsProperty == null)
{
return hasMigrated;
}
largeModePositionsProperty.arraySize = multiPositionArrayProperty.arraySize;
for (int point = 0; point < multiPositionArrayProperty.arraySize; ++point)
{
var elementProperty = multiPositionArrayProperty.GetArrayElementAtIndex(point);
var largeModePositionElementProperty = largeModePositionsProperty.GetArrayElementAtIndex(point);
if (largeModePositionElementProperty != null)
{
var newPoint = new UnityEngine.GameObject("AkAmbientPoint" + point.ToString());
newPoint.AddComponent<AkAmbientLargeModePositioner>();
newPoint.transform.SetParent(transform);
newPoint.transform.position = transform.TransformPoint(elementProperty.vector3Value);
largeModePositionElementProperty.objectReferenceValue = newPoint.GetComponent<AkAmbientLargeModePositioner>();
}
}
multiPositionArrayProperty.arraySize = 0;
return true;
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d8f7c2e3a1433a142b688e469bcd2de5
@@ -0,0 +1,59 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
/// @brief Use this component to add a Large Mode position to any AkAmbient in a Scene.
/// \sa
/// - \ref unity_use_AkEvent_AkAmbient
/// - \ref AkAmbient
public class AkAmbientLargeModePositioner : UnityEngine.MonoBehaviour
{
public UnityEngine.Vector3 Position
{
get
{
return transform.position;
}
}
public UnityEngine.Vector3 Forward
{
get
{
return transform.forward;
}
}
public UnityEngine.Vector3 Up
{
get
{
return transform.up;
}
}
#if UNITY_EDITOR
void OnDrawGizmosSelected()
{
UnityEngine.Gizmos.color = UnityEngine.Color.green;
UnityEngine.Gizmos.DrawSphere(transform.position, 0.1f);
UnityEditor.Handles.Label(transform.position, name);
}
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 678fdbf1414b898409c98bf8497cdb8f
@@ -0,0 +1,286 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
[UnityEngine.AddComponentMenu("Wwise/AkAudioListener")]
[UnityEngine.RequireComponent(typeof(AkGameObj))]
[UnityEngine.DisallowMultipleComponent]
[UnityEngine.DefaultExecutionOrder(-50)]
///@brief Add this script on the game object that represent a listener. This is normally added to the Camera object or the Player object, but can be added to any game object when implementing 3D busses. \c isDefaultListener determines whether the game object will be considered a default listener - a listener that automatically listens to all game objects that do not have listeners attached to their AkGameObjListenerList's.
/// \sa
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__listeners.html" target="_blank">Integrating Listeners</a> (Note: This is described in the Wwise SDK documentation.)
public class AkAudioListener : UnityEngine.MonoBehaviour
{
private static readonly DefaultListenerList defaultListeners = new DefaultListenerList();
private ulong akGameObjectID = AkUnitySoundEngine.AK_INVALID_GAME_OBJECT;
private System.Collections.Generic.List<AkGameObj> EmittersToStartListeningTo =
new System.Collections.Generic.List<AkGameObj>();
private System.Collections.Generic.List<AkGameObj> EmittersToStopListeningTo =
new System.Collections.Generic.List<AkGameObj>();
public bool isDefaultListener = true;
[UnityEngine.SerializeField]
public bool bOverrideScalingFactor = false;
[UnityEngine.SerializeField]
private float scalingFactor = -1f;
public float ScalingFactor
{
get
{
if (bOverrideScalingFactor)
{
return scalingFactor;
}
var settings = AkWwiseInitializationSettings.Instance;
if (settings)
{
return settings.UserSettings.m_DefaultListenerScalingFactor;
}
return 1.0f;
}
set
{
if (value < 0)
{
scalingFactor = 0;
}
else
{
scalingFactor = value;
}
}
}
public static DefaultListenerList DefaultListeners
{
get { return defaultListeners; }
}
public void StartListeningToEmitter(AkGameObj emitter)
{
EmittersToStartListeningTo.Add(emitter);
EmittersToStopListeningTo.Remove(emitter);
}
public void StopListeningToEmitter(AkGameObj emitter)
{
EmittersToStartListeningTo.Remove(emitter);
EmittersToStopListeningTo.Add(emitter);
}
public void SetIsDefaultListener(bool isDefault)
{
if (isDefaultListener != isDefault)
{
isDefaultListener = isDefault;
if (isDefault)
{
DefaultListeners.Add(this);
}
else
{
DefaultListeners.Remove(this);
}
}
}
private void Awake()
{
var akGameObj = GetComponent<AkGameObj>();
UnityEngine.Debug.Assert(akGameObj != null);
if (akGameObj)
{
akGameObj.Register();
}
akGameObjectID = AkUnitySoundEngine.GetAkGameObjectID(gameObject);
}
private void OnEnable()
{
if (isDefaultListener)
{
DefaultListeners.Add(this);
}
if (scalingFactor < 0f)
{
var initializer = AkInitializer.GetAkInitializerGameObject();
if (initializer)
{
scalingFactor = initializer.GetComponent<AkInitializer>().InitializationSettings.UserSettings.m_DefaultListenerScalingFactor;
}
else
{
scalingFactor = 1f;
}
}
var akGameObj = GetComponent<AkGameObj>();
if (akGameObj && gameObject.activeInHierarchy)
{
AkUnitySoundEngine.SetScalingFactor(gameObject, ScalingFactor);
}
}
private void OnDisable()
{
if (isDefaultListener)
{
DefaultListeners.Remove(this);
}
}
private void OnDestroy()
{
AkUnitySoundEngine.UnregisterGameObj(gameObject);
}
private void Update()
{
for (var i = 0; i < EmittersToStartListeningTo.Count; ++i)
{
EmittersToStartListeningTo[i].AddListener(this);
}
EmittersToStartListeningTo.Clear();
for (var i = 0; i < EmittersToStopListeningTo.Count; ++i)
{
EmittersToStopListeningTo[i].RemoveListener(this);
}
EmittersToStopListeningTo.Clear();
}
public ulong GetAkGameObjectID()
{
return akGameObjectID;
}
public class BaseListenerList
{
// @todo: Use HashSet<ulong> and CopyTo() with a private ulong[]
private readonly System.Collections.Generic.List<ulong> listenerIdList = new System.Collections.Generic.List<ulong>();
private readonly System.Collections.Generic.List<AkAudioListener> listenerList =
new System.Collections.Generic.List<AkAudioListener>();
public System.Collections.Generic.List<AkAudioListener> ListenerList
{
get { return listenerList; }
}
/// <summary>
/// Uniquely adds listeners to the list
/// </summary>
/// <param name="listener"></param>
/// <returns></returns>
public virtual bool Add(AkAudioListener listener)
{
if (listener == null)
{
return false;
}
var gameObjectId = listener.GetAkGameObjectID();
if (listenerIdList.Contains(gameObjectId))
{
return false;
}
listenerIdList.Add(gameObjectId);
listenerList.Add(listener);
return true;
}
/// <summary>
/// Removes listeners from the list
/// </summary>
/// <param name="listener"></param>
/// <returns></returns>
public virtual bool Remove(AkAudioListener listener)
{
if (listener == null)
{
return false;
}
var gameObjectId = listener.GetAkGameObjectID();
if (!listenerIdList.Remove(gameObjectId))
{
return false;
}
listenerList.Remove(listener);
return true;
}
public ulong[] GetListenerIds()
{
return listenerIdList.ToArray();
}
}
public class DefaultListenerList : BaseListenerList
{
public override bool Add(AkAudioListener listener)
{
var ret = base.Add(listener);
if (ret && AkUnitySoundEngine.IsInitialized())
{
AkUnitySoundEngine.AddDefaultListener(listener.gameObject);
}
return ret;
}
public override bool Remove(AkAudioListener listener)
{
var ret = base.Remove(listener);
if (ret && AkUnitySoundEngine.IsInitialized())
{
AkUnitySoundEngine.RemoveDefaultListener(listener.gameObject);
}
return ret;
}
}
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.SerializeField]
// Wwise v2016.2 and below supported up to 8 listeners[0-7].
public int listenerId = 0;
#pragma warning restore 0414 // private field assigned but not used.
public void Migrate14()
{
var wasDefaultListener = listenerId == 0;
WwiseLogger.Log("AkAudioListener.Migrate14 for " + gameObject.name);
isDefaultListener = wasDefaultListener;
}
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a835ee92b0863c9459a0f816c5ff62ac
@@ -0,0 +1,189 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/AkBank")]
[UnityEngine.ExecuteInEditMode]
[UnityEngine.DefaultExecutionOrder(-75)]
/// @brief Loads and unloads a SoundBank at a specified moment. Vorbis sounds can be decompressed at a specified moment using the decode compressed data option. In that case, the SoundBank will be prepared.
public class AkBank : AkTriggerHandler
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
public AK.Wwise.Bank data = new AK.Wwise.Bank();
/// DEPRECATED Decode this SoundBank upon load
public bool decodeBank = false;
public bool overrideLoadSetting = false;
/// Check this to load the SoundBank in the background. Be careful, if Events are triggered and the SoundBank hasn't finished loading, you'll have "Event not found" errors.
public bool loadAsynchronous = false;
/// DEPRECATED Save the decoded SoundBank to disk for faster loads in the future
public bool saveDecodedBank = false;
/// Reserved.
public System.Collections.Generic.List<int> unloadTriggerList =
new System.Collections.Generic.List<int> { DESTROY_TRIGGER_ID };
protected override void Awake()
{
#if UNITY_EDITOR
AkUnitySoundEngineInitialization.Instance.initializationDelegate += HandleEvent;
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating)
{
return;
}
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
data.ObjectReference = reference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
#endif
base.Awake();
RegisterTriggers(unloadTriggerList, UnloadBank);
}
#if UNITY_EDITOR
public override void OnEnable()
{
if (UnityEditor.BuildPipeline.isBuildingPlayer)
{
return;
}
base.OnEnable();
}
#endif
protected override void Start()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating)
{
return;
}
if (!UnityEditor.EditorApplication.isPlaying)
{
HandleEvent();
}
#endif
base.Start();
//Call the UnloadBank function if registered to the Start Trigger
if (unloadTriggerList.Contains(START_TRIGGER_ID))
{
UnloadBank(null);
}
}
/// Loads the SoundBank
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
bool asyncResult = loadAsynchronous;
if(!overrideLoadSetting)
{
asyncResult = AkWwiseInitializationSettings.ActivePlatformSettings.LoadBanksAsynchronously;
}
if (asyncResult)
{
data.LoadAsync();
}
else
{
data.Load(decodeBank, saveDecodedBank);
}
}
private void HandleEvent()
{
HandleEvent(gameObject);
}
/// Unloads a SoundBank
public void UnloadBank(UnityEngine.GameObject in_gameObject)
{
data.Unload();
}
protected override void OnDestroy()
{
#if UNITY_EDITOR
AkUnitySoundEngineInitialization.Instance.initializationDelegate -= HandleEvent;
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating)
{
return;
}
#endif
base.OnDestroy();
UnregisterTriggers(unloadTriggerList, UnloadBank);
}
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public string bankName { get { return data == null ? string.Empty : data.Name; } }
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public byte[] valueGuid
{
get
{
if (data == null)
return null;
var objRef = data.ObjectReference;
return !objRef ? null : objRef.Guid.ToByteArray();
}
}
#endregion
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("bankName")]
private string bankNameInternal;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("valueGuid")]
private byte[] valueGuidInternal;
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
bool AK.Wwise.IMigratable.Migrate(UnityEditor.SerializedObject obj)
{
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
return false;
return AK.Wwise.TypeMigration.ProcessSingleGuidType(obj.FindProperty("data.WwiseObjectReference"), WwiseObjectType.Soundbank,
obj.FindProperty("valueGuidInternal"), obj.FindProperty("bankNameInternal"));
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 401f3889052f60e4dad8542d1fd7a96d
@@ -0,0 +1,60 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkEarlyReflections")]
[UnityEngine.RequireComponent(typeof(AkGameObj))]
[UnityEngine.DisallowMultipleComponent]
///@brief Set an early reflections auxiliary bus and send volume for a particular game object.
public class AkEarlyReflections : UnityEngine.MonoBehaviour
{
[UnityEngine.Tooltip("The early reflections auxiliary bus for all sounds playing on this particular game object. The early reflection auxiliary bus specified in the authoring tool has precedence.")]
/// The early reflections auxiliary bus for this particular game object.
/// Geometrical reflection calculation inside spatial audio is enabled for a game object if any sound playing on the game object has a valid early reflections aux bus specified in the authoring tool,
/// or if an aux bus is specified via this parameter. The early reflection auxiliary bus specified in the authoring tool has precedence.
/// Users may apply this function to avoid duplicating sounds in the actor-mixer hierarchy solely for the sake of specifying a unique early reflection bus, or in any situation where the same
/// sound should be played on different game objects with different early reflection aux buses (the early reflection bus must be left blank in the authoring tool if the user intends to specify it through the API).
public AK.Wwise.AuxBus reflectionsAuxBus = new AK.Wwise.AuxBus();
[UnityEngine.Range(0, 1)]
[UnityEngine.Tooltip("The early reflections send volume for all sounds playing on this particular game object. It is combined with the early reflections volume specified in the authoring tool.")]
/// The early reflections send volume for this particular game object.
/// This parameter is used to control the volume of the early reflections send. It is combined with the early reflections volume specified in the authoring tool, and is applied to all sounds playing on the game object.
/// Setting to 0.f will disable all reflection processing for this game object. Valid range 0.f-1.f.
public float reflectionsVolume = 1;
private void OnEnable()
{
if (reflectionsAuxBus != null)
{
AkUnitySoundEngine.SetEarlyReflectionsAuxSend(gameObject, reflectionsAuxBus.Id);
}
AkUnitySoundEngine.SetEarlyReflectionsVolume(gameObject, reflectionsVolume);
}
public void SetEarlyReflectionsVolume(float volume)
{
if (reflectionsVolume != volume)
{
AkUnitySoundEngine.SetEarlyReflectionsVolume(gameObject, volume);
reflectionsVolume = volume;
}
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4ffbdddf1255a664fa019a1000a78287
@@ -0,0 +1,60 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/AkEmitterObstructionOcclusion")]
[UnityEngine.RequireComponent(typeof(AkGameObj))]
/// @brief Completely obstructs/occludes the emitter of the current game object from its listeners if at least one object is between them.
public class AkEmitterObstructionOcclusion : AkObstructionOcclusion
{
private AkGameObj m_gameObj;
private void Awake()
{
InitIntervalsAndFadeRates();
m_gameObj = GetComponent<AkGameObj>();
}
protected override void UpdateCurrentListenerList()
{
if (AkSpatialAudioListener.TheSpatialAudioListener != null && AkRoom.RoomCount > 0)
{
currentListenerList.Add(AkSpatialAudioListener.TheSpatialAudioListener);
return;
}
if (m_gameObj.IsUsingDefaultListeners)
{
currentListenerList.AddRange(AkAudioListener.DefaultListeners.ListenerList);
}
currentListenerList.AddRange(m_gameObj.ListenerList);
}
protected override void SetObstructionOcclusion(
System.Collections.Generic.KeyValuePair<AkAudioListener, ObstructionOcclusionValue> ObsOccPair)
{
if (AkSpatialAudioListener.TheSpatialAudioListener != null && AkRoom.RoomCount > 0)
{
AkUnitySoundEngine.SetObjectObstructionAndOcclusion(gameObject, ObsOccPair.Key.gameObject, ObsOccPair.Value.currentValue, 0.0f);
}
else
{
AkUnitySoundEngine.SetObjectObstructionAndOcclusion(gameObject, ObsOccPair.Key.gameObject, 0.0f, ObsOccPair.Value.currentValue);
}
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2587568098810e748aba262930593206
@@ -0,0 +1,158 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/AkEnvironment")]
[UnityEngine.ExecuteInEditMode]
[UnityEngine.RequireComponent(typeof(UnityEngine.Collider))]
/// @brief Use this component to define a reverb zone. This needs to be added to a collider object to work properly. See \ref unity_use_AkEnvironment_AkEnvironmentPortal.
/// @details This component can be attached to any collider. You can specify a roll-off to fade-in/out of the reverb.
/// The reverb parameters will be defined in the Wwise project, by the sound designer. All AkGameObj that are
/// "environment"-aware will receive a send value when entering the attached collider.
/// \sa
/// - \ref unity_use_AkEnvironment_AkEnvironmentPortal
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=integrating__elements__environments.html" target="_blank">Integrating Environments and Game-defined Auxiliary Sends</a> (Note: This is described in the Wwise SDK documentation.)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=namespace_a_k_1_1_sound_engine_af960fca0239e219b9d08c2659fe9e5d4.html" target="_blank">AK::SoundEngine::SetGameObjectAuxSendValues</a> (Note: This is described in the Wwise SDK documentation.)
public class AkEnvironment : UnityEngine.MonoBehaviour
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
public const int MAX_NB_ENVIRONMENTS = 4;
public static AkEnvironment_CompareByPriority s_compareByPriority = new AkEnvironment_CompareByPriority();
public static AkEnvironment_CompareBySelectionAlgorithm s_compareBySelectionAlgorithm =
new AkEnvironment_CompareBySelectionAlgorithm();
//if excludeOthers, then only the environment with the excludeOthers flag set to true and with the highest priority will be active
public bool excludeOthers = false;
//if isDefault, then this environment will be bumped out if any other is present
public bool isDefault = false;
public AK.Wwise.AuxBus data = new AK.Wwise.AuxBus();
//Cache of the colliders for this environment, to avoid calls to GetComponent.
public UnityEngine.Collider Collider { get; private set; }
//smaller number has a higher priority
public int priority = 0;
public void Awake()
{
#if UNITY_EDITOR
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
data.ObjectReference = reference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
#endif
Collider = GetComponent<UnityEngine.Collider>();
}
/// @brief Sorts AkEnvironments based on their priorities.
public class AkEnvironment_CompareByPriority : System.Collections.Generic.IComparer<AkEnvironment>
{
public virtual int Compare(AkEnvironment a, AkEnvironment b)
{
var result = a.priority.CompareTo(b.priority);
return result == 0 && a != b ? 1 : result;
}
}
/// @brief Sorts AkEnvironments based on the selection algorithm.
/// The selection algorithm is as follows:
/// -# Environments have priorities.
/// -# Environments have a "Default" flag. This flag effectively says that this environment will be bumped out if any other is present.
/// -# Environments have an "Exclude Other" flag. This flag will tell that this env is not overlappable with others. So, only one (the highest priority) should be selected.
public class AkEnvironment_CompareBySelectionAlgorithm : AkEnvironment_CompareByPriority
{
public override int Compare(AkEnvironment a, AkEnvironment b)
{
if (a.isDefault)
return b.isDefault ? base.Compare(a, b) : 1;
if (b.isDefault)
return -1;
if (a.excludeOthers)
return b.excludeOthers ? base.Compare(a, b) : -1;
return b.excludeOthers ? 1 : base.Compare(a, b);
}
}
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_2)]
public int m_auxBusID { get { return (int)(data == null ? AkUnitySoundEngine.AK_INVALID_UNIQUE_ID : data.Id); } }
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public byte[] valueGuid
{
get
{
if (data == null)
return null;
var objRef = data.ObjectReference;
return !objRef ? null : objRef.Guid.ToByteArray();
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_2)]
public uint GetAuxBusID()
{
return data.Id;
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public UnityEngine.Collider GetCollider()
{
return Collider;
}
#endregion
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("m_auxBusID")]
private int auxBusIdInternal = (int)AkUnitySoundEngine.AK_INVALID_UNIQUE_ID;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("valueGuid")]
private byte[] valueGuidInternal;
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
bool AK.Wwise.IMigratable.Migrate(UnityEditor.SerializedObject obj)
{
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
return false;
return AK.Wwise.TypeMigration.ProcessSingleGuidType(obj.FindProperty("data.WwiseObjectReference"), WwiseObjectType.AuxBus,
obj.FindProperty("valueGuidInternal"), obj.FindProperty("auxBusIdInternal"));
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: cf838bd1abd0bcb41b145cbc06b3112f
@@ -0,0 +1,103 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
/// @brief Use this component to define an area that straddles two different AkEnvironment's zones and allow mixing between both zones. \ref unity_use_AkEnvironment_AkEnvironmentPortal
[UnityEngine.AddComponentMenu("Wwise/AkEnvironmentPortal")]
[UnityEngine.RequireComponent(typeof(UnityEngine.BoxCollider))]
public class AkEnvironmentPortal : UnityEngine.MonoBehaviour
{
public const int MAX_ENVIRONMENTS_PER_PORTAL = 2;
///The axis used to find the contribution of each environment
public UnityEngine.Vector3 axis = UnityEngine.Vector3.right;
///The array is already sorted by position.
///The first environment is on the negative side of the portal(opposite to the direction of the chosen axis)
///The second environment is on the positive side of the portal
public AkEnvironment[] environments = new AkEnvironment[MAX_ENVIRONMENTS_PER_PORTAL];
private UnityEngine.BoxCollider m_BoxCollider;
private UnityEngine.BoxCollider BoxCollider
{
get
{
if (!m_BoxCollider)
m_BoxCollider = GetComponent<UnityEngine.BoxCollider>();
return m_BoxCollider;
}
}
public bool EnvironmentsShareAuxBus
{
get
{
if (environments[0] == null)
return environments[1] == null;
if (environments[1] == null)
return false;
if (environments[0].data == null)
return environments[1].data == null;
if (environments[1].data == null)
return false;
return environments[0].data.Id == environments[1].data.Id;
}
}
public float GetAuxSendValueForPosition(UnityEngine.Vector3 in_position, int index)
{
//total length of the portal in the direction of axis
var portalLength = UnityEngine.Vector3.Dot(UnityEngine.Vector3.Scale(BoxCollider.size, transform.lossyScale), axis);
//transform axis to world coordinates
var axisWorld = UnityEngine.Vector3.Normalize(transform.rotation * axis);
//Get distance form left side of the portal(opposite to the direction of axis) to the game object in the direction of axisWorld
var dist = UnityEngine.Vector3.Dot(in_position - (transform.position - portalLength * 0.5f * axisWorld), axisWorld);
dist = UnityEngine.Mathf.Clamp(dist, 0, portalLength);
//calculate value of the environment referred by index
if (index == 0)
return (portalLength - dist) * (portalLength - dist) / (portalLength * portalLength);
return dist * dist / (portalLength * portalLength);
}
#if UNITY_EDITOR
/// This enables us to detect intersections between portals and environments in the editor
[System.Serializable]
public class EnvListWrapper
{
public System.Collections.Generic.List<AkEnvironment> list = new System.Collections.Generic.List<AkEnvironment>();
}
/// Unity can't serialize an array of list so we wrap the list in a serializable class
public EnvListWrapper[] envList =
{
new EnvListWrapper(), //All environments on the negative side of each portal(opposite to the direction of the chosen axis)
new EnvListWrapper() //All environments on the positive side of each portal(same direction as the chosen axis)
};
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4efdb117a2234b74fbdc4a34171a1a11
@@ -0,0 +1,270 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
/// <summary>
/// Event callback information.
/// Event callback functions can receive this structure as a parameter
/// </summary>
public class AkEventCallbackMsg
{
///For more information about the event callback, see the classes derived from AkCallbackInfo.
public AkCallbackInfo info;
/// GameObject from whom the callback function was called
public UnityEngine.GameObject sender;
///AkUnitySoundEngine.PostEvent callback flags. See the AkCallbackType enumeration for a list of all callbacks
public AkCallbackType type;
}
[UnityEngine.AddComponentMenu("Wwise/AkEvent")]
[UnityEngine.ExecuteInEditMode]
[UnityEngine.RequireComponent(typeof(AkGameObj))]
/// @brief Helper class that knows a Wwise Event and when to trigger it in Unity. As of 2017.2.0, the AkEvent inspector has buttons for play/stop, play multiple, stop multiple, and stop all.
/// Play/Stop will play or stop the event such that it can be previewed both in edit mode and play mode. When multiple objects are selected, Play Multiple and Stop Multiple will play or stop the associated AkEvent for each object.
/// \sa
/// - \ref sect_edit_mode
/// - \ref unity_use_AkEvent_AkAmbient
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__events.html" target="_blank">Integration Details - Events</a> (Note: This is described in the Wwise SDK documentation.)
public class AkEvent : AkDragDropTriggerHandler
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
/// Replacement action. See AK::SoundEngine::ExecuteEventOnAction()
public AkActionOnEventType actionOnEventType = AkActionOnEventType.AkActionOnEventType_Stop;
/// Fade curve to use with the new Action. See AK::SoundEngine::ExecuteEventOnAction()
public AkCurveInterpolation curveInterpolation = AkCurveInterpolation.AkCurveInterpolation_Linear;
/// Enables additional options to reuse existing events. Use it to transform a Play event into a Stop event without having to define one in the Wwise Project.
public bool enableActionOnEvent = false;
public AK.Wwise.Event data = new AK.Wwise.Event();
protected override AK.Wwise.BaseType WwiseType { get { return data; } }
[System.Serializable]
public class CallbackData
{
public AK.Wwise.CallbackFlags Flags;
public string FunctionName;
public UnityEngine.GameObject GameObject;
public void CallFunction(AkEventCallbackMsg eventCallbackMsg)
{
if (((uint)eventCallbackMsg.type & Flags.value) != 0 && GameObject)
GameObject.SendMessage(FunctionName, eventCallbackMsg);
}
}
private UnityEngine.GameObject otherGameObject;
public bool useCallbacks = false;
public bool stopSoundOnDestroy = true;
public System.Collections.Generic.List<CallbackData> Callbacks = new System.Collections.Generic.List<CallbackData>();
public uint playingId => data.PlayingId;
/// Game object onto which the Event will be posted. By default, when empty, it is posted on the same object on which the component was added.
public UnityEngine.GameObject soundEmitterObject;
/// Duration of the fade, in milliseconds. See <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=namespace_a_k_1_1_sound_engine_ac55e3d6ac464b0579a8487c88a755d8c.html" target="_blank">AK::SoundEngine::ExecuteEventOnAction()</a>.
public float transitionDuration = 0.0f;
private AkEventCallbackMsg EventCallbackMsg = null;
protected override void Awake()
{
base.Awake();
#if UNITY_EDITOR
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
data.ObjectReference = reference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
#endif
}
protected override void Start()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
return;
#endif
if (useCallbacks)
{
EventCallbackMsg = new AkEventCallbackMsg { sender = gameObject };
}
soundEmitterObject = gameObject;
base.Start();
}
private void Callback(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info)
{
EventCallbackMsg.type = in_type;
EventCallbackMsg.info = in_info;
for (var i = 0; i < Callbacks.Count; ++i)
{
Callbacks[i].CallFunction(EventCallbackMsg);
}
}
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
var gameObj = useOtherObject && in_gameObject != null ? in_gameObject : gameObject;
soundEmitterObject = gameObj;
if (useOtherObject)
{
otherGameObject = in_gameObject;
}
if (enableActionOnEvent)
{
data.ExecuteAction(gameObj, actionOnEventType, (int)transitionDuration * 1000, curveInterpolation);
return;
}
if (useCallbacks)
{
uint flags = 0;
for (var i = 0; i < Callbacks.Count; ++i)
{
if (Callbacks[i].GameObject)
{
flags |= Callbacks[i].Flags.value;
}
}
if (flags != 0)
{
data.Post(gameObj, flags, Callback);
return;
}
}
data.Post(gameObj);
}
protected void OnDisable()
{
var akGameObj = gameObject.GetComponent<AkGameObj>();
if (stopSoundOnDestroy && akGameObj != null && akGameObj.GameObjIsRegistered())
{
var gameObj = useOtherObject && otherGameObject != null ? otherGameObject : gameObject;
data.ExecuteAction(gameObj, AkActionOnEventType.AkActionOnEventType_Stop, (int)transitionDuration * 1000, curveInterpolation);
}
}
public void Stop(int _transitionDuration)
{
Stop(_transitionDuration, AkCurveInterpolation.AkCurveInterpolation_Linear);
}
public void Stop(int _transitionDuration, AkCurveInterpolation _curveInterpolation)
{
data.Stop(soundEmitterObject ? soundEmitterObject : gameObject, _transitionDuration, _curveInterpolation);
}
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_2)]
public int eventID { get { return (int)(data == null ? AkUnitySoundEngine.AK_INVALID_UNIQUE_ID : data.Id); } }
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public byte[] valueGuid
{
get
{
if (data == null)
return null;
var objRef = data.ObjectReference;
return !objRef ? null : objRef.Guid.ToByteArray();
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public AkEventCallbackData m_callbackData { get { return m_callbackDataInternal; } }
#endregion
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("eventID")]
private int eventIdInternal = (int)AkUnitySoundEngine.AK_INVALID_UNIQUE_ID;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("valueGuid")]
private byte[] valueGuidInternal;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("m_callbackData")]
private AkEventCallbackData m_callbackDataInternal = null;
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
public virtual bool Migrate(UnityEditor.SerializedObject obj)
{
var hasMigrated = false;
if (AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
{
hasMigrated = AK.Wwise.TypeMigration.ProcessSingleGuidType(obj.FindProperty("data.WwiseObjectReference"), WwiseObjectType.Event,
obj.FindProperty("valueGuidInternal"), obj.FindProperty("eventIdInternal"));
}
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.AkEventCallback_v2018_1_6))
return hasMigrated;
var oldCallbackDataProperty = obj.FindProperty("m_callbackDataInternal");
var oldCallbackData = oldCallbackDataProperty.objectReferenceValue as AkEventCallbackData;
if (!oldCallbackData)
return hasMigrated;
var count = oldCallbackData.callbackFlags.Count;
if (count != oldCallbackData.callbackFunc.Count || count != oldCallbackData.callbackGameObj.Count)
{
WwiseLogger.Warning("Inconsistent callback data!");
return hasMigrated;
}
var newCallbackData = obj.FindProperty("Callbacks");
newCallbackData.arraySize = count;
obj.FindProperty("useCallbacks").boolValue = true;
for (var i = 0; i < count; ++i)
{
var data = newCallbackData.GetArrayElementAtIndex(i);
data.FindPropertyRelative("GameObject").objectReferenceValue = oldCallbackData.callbackGameObj[i];
data.FindPropertyRelative("FunctionName").stringValue = oldCallbackData.callbackFunc[i];
data.FindPropertyRelative("Flags.value").intValue = oldCallbackData.callbackFlags[i];
WwiseLogger.Log("Migrated Callback for function \"" + oldCallbackData.callbackFunc[i] + "\" on <" + oldCallbackData.callbackGameObj[i] + "> with flags <" + (AkCallbackType)oldCallbackData.callbackFlags[i] + ">.");
}
return true;
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: eec618f338d13bf43b8519814d335311
@@ -0,0 +1,35 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkEventCallbackData : UnityEngine.ScriptableObject
{
////AkUnitySoundEngine.PostEvent callback flags. See the AkCallbackType enumeration for a list of all callbacks
public System.Collections.Generic.List<int> callbackFlags = new System.Collections.Generic.List<int>();
////Names of the callback functions.
public System.Collections.Generic.List<string> callbackFunc = new System.Collections.Generic.List<string>();
////GameObject that will receive the callback
public System.Collections.Generic.List<UnityEngine.GameObject> callbackGameObj =
new System.Collections.Generic.List<UnityEngine.GameObject>();
////The sum of the flags of all game objects. This is the flag that will be passed to AkUnitySoundEngine.PostEvent
public int uFlags = 0;
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2b86bc90937438846b772e3f72ff18c9
@@ -0,0 +1,531 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using UnityEngine;
using AK.Wwise.Unity.Logging;
[UnityEngine.AddComponentMenu("Wwise/AkGameObj")]
[UnityEngine.DisallowMultipleComponent]
[UnityEngine.ExecuteInEditMode] //ExecuteInEditMode necessary to maintain proper state of isStaticObject.
[UnityEngine.DefaultExecutionOrder(-25)]
///@brief This component represents a sound object in your scene and tracks its position and other game syncs such as Switches, RTPCs, and environment values. You can add this to any object that emits sound, and it is added to any object to which an AkAudioListener is attached. If it is not present, Wwise adds it automatically, with the default values, to any Unity Game Object that is passed to Wwise.
/// \sa
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__gameobj.html" target="_blank">Integration Details - Game Objects</a> (SDK documentation)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__events.html" target="_blank">Integration Details - Events</a> (SDK documentation)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__listeners.html" target="_blank">Integrating Listeners</a> (SDK documentation)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__switch.html" target="_blank">Integration Details - Switches</a> (SDK documentation)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__states.html" target="_blank">Integration Details - States</a> (SDK documentation)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__environments.html" target="_blank">Integration Details - Environments and Game-defined Auxiliary Sends</a> (SDK documentation)
public class AkGameObj : UnityEngine.MonoBehaviour
{
[UnityEngine.SerializeField] private AkGameObjListenerList m_listeners = new AkGameObjListenerList();
/// Indicates whether the object is affected by environmental changes. Set to false if the object is not affected in order to save some unnecessary calls. The default value is true.
public bool isEnvironmentAware = true;
/// Maintains and persists the Static setting of the game object, which is available only in the editor.
[UnityEngine.SerializeField] private bool isStaticObject = false;
/// Cache the bounds to avoid calls to GetComponent()
private UnityEngine.Collider m_Collider;
private AkGameObjEnvironmentData m_envData;
private AkGameObjPositionData m_posData;
public bool usePositionOffsetData;
/// When not set to null, the position is offset relative to the Game Object position by the Position Offset
public AkGameObjPositionOffsetData m_positionOffsetData;
[UnityEngine.SerializeField]
private float scalingFactor = 1f;
public float ScalingFactor
{
get => scalingFactor;
set
{
if (value > 0)
{
scalingFactor = value;
if (gameObject.activeInHierarchy)
{
AkUnitySoundEngine.SetScalingFactor(gameObject, scalingFactor);
}
}
else
{
WwiseLogger.Error("Scaling Factor needs to be a positive value greater than 0.");
}
}
}
public bool IsUsingDefaultListeners
{
get { return m_listeners.useDefaultListeners; }
}
public System.Collections.Generic.List<AkAudioListener> ListenerList
{
get { return m_listeners.ListenerList; }
}
private bool isRegistered = false;
public bool GameObjIsRegistered()
{
return isRegistered;
}
internal void AddListener(AkAudioListener listener)
{
m_listeners.Add(listener);
}
internal void RemoveListener(AkAudioListener listener)
{
m_listeners.Remove(listener);
}
public AKRESULT Register()
{
if (isRegistered)
{
return AKRESULT.AK_Success;
}
isRegistered = true;
return AkUnitySoundEngine.RegisterGameObj(gameObject, gameObject.name);
}
private void UnregisterGameObject()
{
if (AkUnitySoundEngine.IsInitialized())
{
Unregister();
}
}
public AKRESULT Unregister()
{
if (!isRegistered)
{
return AKRESULT.AK_Success;
}
isRegistered = false;
m_posData = null;
return AkUnitySoundEngine.UnregisterGameObj(gameObject);
}
private void SetPosition()
{
var position = GetPosition();
var forward = GetForward();
var up = GetUpward();
if (m_posData != null)
{
if (m_posData.position == position && m_posData.forward == forward && m_posData.up == up)
{
return;
}
m_posData.position = position;
m_posData.forward = forward;
m_posData.up = up;
}
AkUnitySoundEngine.SetObjectPosition(gameObject, position, forward, up);
}
private void Awake()
{
#if UNITY_EDITOR
if (AkUtilities.IsMigrating)
{
return;
}
if (!UnityEditor.EditorApplication.isPlaying)
{
UnityEditor.EditorApplication.update += CheckStaticStatus;
}
AkUnitySoundEngineInitialization.Instance.initializationDelegate += RegisterGameObject;
AkUnitySoundEngineInitialization.Instance.terminationDelegate += UnregisterGameObject;
#endif
// If the object was marked as static, don't update its position to save cycles.
if (!isStaticObject)
{
m_posData = new AkGameObjPositionData();
}
// Cache the bounds to avoid calls to GetComponent()
m_Collider = GetComponent<UnityEngine.Collider>();
}
private void RegisterGameObject()
{
if (!AkUnitySoundEngine.IsInitialized())
{
return;
}
//Register a Game Object in the sound engine, with its name.
if (Register() == AKRESULT.AK_Success)
{
SetPosition();
if (isEnvironmentAware)
{
m_envData = new AkGameObjEnvironmentData();
if (m_Collider)
{
m_envData.AddAkEnvironment(m_Collider, m_Collider);
}
m_envData.UpdateAuxSend(gameObject, transform.position);
}
m_listeners.Init(this);
//The Listener will win for the scaling factor
if (gameObject.GetComponent<AkAudioListener>() == null && gameObject.activeInHierarchy)
{
AkUnitySoundEngine.SetScalingFactor(gameObject, ScalingFactor);
}
}
}
private void CheckStaticStatus()
{
#if UNITY_EDITOR
if (AkUtilities.IsMigrating)
{
return;
}
try
{
if (gameObject != null && isStaticObject != gameObject.isStatic)
{
isStaticObject = gameObject.isStatic;
UnityEditor.EditorUtility.SetDirty(this);
}
}
catch
{
UnityEditor.EditorApplication.update -= CheckStaticStatus;
}
#endif
}
private void OnEnable()
{
#if UNITY_EDITOR
if (AkUtilities.IsMigrating)
{
return;
}
#endif
RegisterGameObject();
}
#if UNITY_EDITOR
private void OnDisable()
{
if (!AkUnitySoundEngineInitialization.Instance.ShouldKeepSoundEngineEnabled())
{
Unregister();
}
}
#endif
private void OnDestroy()
{
#if UNITY_EDITOR
if (AkUtilities.IsMigrating)
{
return;
}
if (!UnityEditor.EditorApplication.isPlaying)
{
UnityEditor.EditorApplication.update -= CheckStaticStatus;
}
AkUnitySoundEngineInitialization.Instance.initializationDelegate -= RegisterGameObject;
AkUnitySoundEngineInitialization.Instance.terminationDelegate -= UnregisterGameObject;
#endif
// We can't do the code in OnDestroy if the gameObj is unregistered, so do it now.
var eventHandlers = gameObject.GetComponents<AkTriggerHandler>();
foreach (var handler in eventHandlers)
{
if (handler.triggerList.Contains(AkTriggerHandler.DESTROY_TRIGGER_ID))
{
handler.DoDestroy();
}
}
if (AkUnitySoundEngine.IsInitialized())
{
Unregister();
}
}
private void Update()
{
#if UNITY_EDITOR
if (AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
if (!isStaticObject)
{
if (m_envData != null)
{
m_envData.UpdateAuxSend(gameObject, transform.position);
}
SetPosition();
}
}
/// Gets the position including the position offset, if applyPositionOffset is enabled. User can also override this method to calculate an arbitrary position.
/// \return The position.
public virtual UnityEngine.Vector3 GetPosition()
{
if (!usePositionOffsetData)
{
return transform.position;
}
var worldOffset = transform.rotation * m_positionOffsetData.positionOffset;
return transform.position + worldOffset;
}
/// Gets the orientation forward vector. User can also override this method to calculate an arbitrary vector.
/// \return The forward vector of orientation.
public virtual UnityEngine.Vector3 GetForward()
{
return transform.forward;
}
/// Gets the orientation upward vector. User can also override this method to calculate an arbitrary vector.
/// \return The upward vector of orientation.
public virtual UnityEngine.Vector3 GetUpward()
{
return transform.up;
}
private void OnTriggerEnter(UnityEngine.Collider other)
{
#if UNITY_EDITOR
if (AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
if (isEnvironmentAware && m_envData != null)
{
m_envData.AddAkEnvironment(other, m_Collider);
}
}
private void OnTriggerExit(UnityEngine.Collider other)
{
#if UNITY_EDITOR
if (AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
if (isEnvironmentAware && m_envData != null)
{
m_envData.RemoveAkEnvironment(other, m_Collider);
}
}
#if UNITY_EDITOR
public void OnDrawGizmosSelected()
{
if (AkUtilities.IsMigrating)
{
return;
}
var position = GetPosition();
UnityEngine.Gizmos.DrawIcon(position, "WwiseAudioSpeaker.png", false);
}
#endif
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
private AkGameObjPosOffsetData m_posOffsetData;
// Wwise v2016.2 and below supported up to 8 listeners[0-7].
private const int AK_NUM_LISTENERS = 8;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
/// Listener 0 by default.
private int listenerMask = 1;
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
public void Migrate9()
{
WwiseLogger.Log("AkGameObj.Migrate9 for " + gameObject.name);
const int ALL_LISTENER_MASK = (1 << AK_NUM_LISTENERS) - 1;
if ((listenerMask & ALL_LISTENER_MASK) == ALL_LISTENER_MASK)
listenerMask = 1;
}
public void Migrate10()
{
WwiseLogger.Log("AkGameObj.Migrate10 for " + gameObject.name);
if (m_posOffsetData != null)
{
m_positionOffsetData = new AkGameObjPositionOffsetData(true);
m_positionOffsetData.positionOffset = m_posOffsetData.positionOffset;
m_posOffsetData = null;
}
}
private class Migration14Data
{
private readonly System.Collections.Generic.List<AkAudioListener>[] listeners =
new System.Collections.Generic.List<AkAudioListener>[AK_NUM_LISTENERS];
public Migration14Data()
{
var fullSceneListenerMask = 0;
// Get all AkAudioListeners in the scene.
#if UNITY_6000_0_OR_NEWER
var listenerObjects = FindObjectsByType<AkAudioListener>(FindObjectsSortMode.None);
#else
var listenerObjects = FindObjectsOfType<AkAudioListener>();
#endif
foreach (var listener in listenerObjects)
{
// Add AkGameObj to AkAudioListeners
if (listener.GetComponent<AkGameObj>() == null)
{
var akGameObj = listener.gameObject.AddComponent<AkGameObj>();
if (akGameObj)
{
akGameObj.isEnvironmentAware = false;
WwiseLogger.Log("Added AkGameObj to <" + listener.gameObject.name + ">.");
}
else
WwiseLogger.Error("Failed to add AkGameObj to <" + listener.gameObject.name + ">.");
}
var listenerId = listener.listenerId;
if (listenerId >= 0 && listenerId < AK_NUM_LISTENERS)
{
if (listeners[listenerId] == null)
listeners[listenerId] = new System.Collections.Generic.List<AkAudioListener>();
listeners[listenerId].Add(listener);
fullSceneListenerMask |= 1 << listenerId;
}
else
WwiseLogger.Error("Invalid listenerId <" + listenerId + "> found during migration.");
}
if (fullSceneListenerMask == 0)
{
WwiseLogger.Warning("Listeners were not added via components within this Scene.");
listeners = null;
}
else
{
for (var ii = 0; ii < AK_NUM_LISTENERS; ++ii)
{
if (listeners[ii] != null && listeners[ii].Count > 1)
{
WwiseLogger.Warning("Multiple listeners <" + listeners[ii].Count +
"> with same listenerId <" + ii + "> found during migration.");
}
}
if (fullSceneListenerMask == 1)
{
WwiseLogger.Log("Default listeners will be used for this Scene.");
listeners = null;
}
}
}
public void Migrate(AkGameObj akGameObj)
{
if (listeners != null)
{
for (var ii = 0; ii < AK_NUM_LISTENERS; ++ii)
{
var idMask = 1 << ii;
if ((akGameObj.listenerMask & idMask) != 0 && listeners[ii] != null)
{
foreach (var listener in listeners[ii])
akGameObj.m_listeners.AddToInitialListenerList(listener);
}
}
}
}
}
private static Migration14Data migration14data;
public static void PreMigration14()
{
migration14data = new Migration14Data();
}
public void Migrate14()
{
WwiseLogger.Log("AkGameObj.Migrate14 for " + gameObject.name);
if (migration14data != null)
migration14data.Migrate(this);
}
public static void PostMigration14()
{
migration14data = null;
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4ccb80e2899444642bdbf406a3c31f7b
@@ -0,0 +1,203 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkGameObjEnvironmentData
{
/// Contains all active environments sorted by default, excludeOthers and priority, even those inside a portal.
private readonly System.Collections.Generic.List<AkEnvironment> activeEnvironments =
new System.Collections.Generic.List<AkEnvironment>();
/// Contains all active environments sorted by priority, even those inside a portal.
private readonly System.Collections.Generic.List<AkEnvironment> activeEnvironmentsFromPortals =
new System.Collections.Generic.List<AkEnvironment>();
/// Contains all active portals.
private readonly System.Collections.Generic.List<AkEnvironmentPortal> activePortals =
new System.Collections.Generic.List<AkEnvironmentPortal>();
private readonly AkAuxSendArray auxSendValues = new AkAuxSendArray();
private UnityEngine.Vector3 lastPosition = UnityEngine.Vector3.zero;
private bool hasEnvironmentListChanged = true;
private bool hasActivePortalListChanged = true;
private bool hasSentZero = false;
private void AddHighestPriorityEnvironmentsFromPortals(UnityEngine.Vector3 position)
{
for (var i = 0; i < activePortals.Count; i++)
{
var portal = activePortals[i];
if (portal.EnvironmentsShareAuxBus)
{
var env = portal.environments[0];
if (env == null)
continue;
var index = activeEnvironmentsFromPortals.BinarySearch(env, AkEnvironment.s_compareByPriority);
if (index < 0 || index >= AkEnvironment.MAX_NB_ENVIRONMENTS)
continue;
var auxBusID = env.data.Id;
if (!auxSendValues.Contains(auxBusID))
{
auxSendValues.Add(auxBusID, 1.0f);
if (auxSendValues.isFull)
return;
}
continue;
}
for (var j = 0; j < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; j++)
{
var env = portal.environments[j];
if (env == null)
continue;
var index = activeEnvironmentsFromPortals.BinarySearch(env, AkEnvironment.s_compareByPriority);
if (index < 0 || index >= AkEnvironment.MAX_NB_ENVIRONMENTS)
continue;
var auxBusID = env.data.Id;
if (!auxSendValues.Contains(auxBusID))
{
auxSendValues.Add(auxBusID, portal.GetAuxSendValueForPosition(position, j));
if (auxSendValues.isFull)
return;
}
}
}
}
private void AddHighestPriorityEnvironments(UnityEngine.Vector3 position)
{
if (!auxSendValues.isFull && auxSendValues.Count() < activeEnvironments.Count)
{
for (var i = 0; i < activeEnvironments.Count; i++)
{
var env = activeEnvironments[i];
var auxBusID = env.data.Id;
if ((!env.isDefault || i == 0) && !auxSendValues.Contains(auxBusID))
{
auxSendValues.Add(auxBusID, 1.0f);
//No other environment can be added after an environment with the excludeOthers flag set to true
if (env.excludeOthers || auxSendValues.isFull)
break;
}
}
}
}
public void UpdateAuxSend(UnityEngine.GameObject gameObject, UnityEngine.Vector3 position)
{
if (!hasEnvironmentListChanged && !hasActivePortalListChanged && lastPosition == position)
return;
auxSendValues.Reset();
AddHighestPriorityEnvironmentsFromPortals(position);
AddHighestPriorityEnvironments(position);
bool isSendingZero = auxSendValues.Count() == 0;
if (!hasSentZero || !isSendingZero)
auxSendValues.SetValues(gameObject);
hasSentZero = isSendingZero;
lastPosition = position;
hasActivePortalListChanged = false;
hasEnvironmentListChanged = false;
}
private void TryAddEnvironment(AkEnvironment env)
{
if (env == null)
return;
var index = activeEnvironmentsFromPortals.BinarySearch(env, AkEnvironment.s_compareByPriority);
if (index >= 0)
return;
activeEnvironmentsFromPortals.Insert(~index, env);
index = activeEnvironments.BinarySearch(env, AkEnvironment.s_compareBySelectionAlgorithm);
if (index < 0)
activeEnvironments.Insert(~index, env);
hasEnvironmentListChanged = true;
}
private void RemoveEnvironment(AkEnvironment env)
{
activeEnvironmentsFromPortals.Remove(env);
activeEnvironments.Remove(env);
hasEnvironmentListChanged = true;
}
public void AddAkEnvironment(UnityEngine.Collider environmentCollider, UnityEngine.Collider gameObjectCollider)
{
var portal = environmentCollider.GetComponent<AkEnvironmentPortal>();
if (portal == null)
{
var env = environmentCollider.GetComponent<AkEnvironment>();
TryAddEnvironment(env);
return;
}
activePortals.Add(portal);
hasActivePortalListChanged = true;
for (var i = 0; i < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; i++)
TryAddEnvironment(portal.environments[i]);
}
private bool AkEnvironmentBelongsToActivePortals(AkEnvironment env)
{
for (var i = 0; i < activePortals.Count; i++)
for (var j = 0; j < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; j++)
{
if (env == activePortals[i].environments[j])
return true;
}
return false;
}
public void RemoveAkEnvironment(UnityEngine.Collider environmentCollider, UnityEngine.Collider gameObjectCollider)
{
var portal = environmentCollider.GetComponent<AkEnvironmentPortal>();
if (portal != null)
{
for (var i = 0; i < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; i++)
{
var env = portal.environments[i];
if (env != null && !gameObjectCollider.bounds.Intersects(env.Collider.bounds))
RemoveEnvironment(env);
}
activePortals.Remove(portal);
hasActivePortalListChanged = true;
}
else
{
var env = environmentCollider.GetComponent<AkEnvironment>();
if (env != null && !AkEnvironmentBelongsToActivePortals(env))
RemoveEnvironment(env);
}
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ed0f82de77a42fc4090c3ca5876767a2
@@ -0,0 +1,91 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[System.Serializable]
public class AkGameObjListenerList : AkAudioListener.BaseListenerList
{
[System.NonSerialized] private AkGameObj akGameObj;
[UnityEngine.SerializeField]
public System.Collections.Generic.List<AkAudioListener> initialListenerList =
new System.Collections.Generic.List<AkAudioListener>();
[UnityEngine.SerializeField] public bool useDefaultListeners = true;
public void SetUseDefaultListeners(bool useDefault)
{
if (useDefaultListeners != useDefault)
{
useDefaultListeners = useDefault;
if (useDefault)
{
AkUnitySoundEngine.ResetListenersToDefault(akGameObj.gameObject);
for (var i = 0; i < ListenerList.Count; ++i)
AkUnitySoundEngine.AddListener(akGameObj.gameObject, ListenerList[i].gameObject);
}
else
{
var Ids = GetListenerIds();
AkUnitySoundEngine.SetListeners(akGameObj.gameObject, Ids, Ids == null ? 0 : (uint) Ids.Length);
}
}
}
public void Init(AkGameObj akGameObj)
{
this.akGameObj = akGameObj;
if (!useDefaultListeners)
AkUnitySoundEngine.SetListeners(akGameObj.gameObject, null, 0);
for (var ii = 0; ii < initialListenerList.Count; ++ii)
initialListenerList[ii].StartListeningToEmitter(akGameObj);
}
public override bool Add(AkAudioListener listener)
{
var ret = base.Add(listener);
if (ret && AkUnitySoundEngine.IsInitialized())
AkUnitySoundEngine.AddListener(akGameObj.gameObject, listener.gameObject);
return ret;
}
public override bool Remove(AkAudioListener listener)
{
var ret = base.Remove(listener);
if (ret && AkUnitySoundEngine.IsInitialized())
AkUnitySoundEngine.RemoveListener(akGameObj.gameObject, listener.gameObject);
return ret;
}
#if UNITY_EDITOR
public void AddToInitialListenerList(AkAudioListener listener)
{
if (!initialListenerList.Contains(listener))
initialListenerList.Add(listener);
}
public void RemoveFromInitialListenerList(AkAudioListener listener)
{
initialListenerList.Remove(listener);
}
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7d21f88ef110b7f4db9f0ab69030084e
@@ -0,0 +1,28 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
// *** THIS FILE IS KEPT FOR THE MIGRATION SYSTEM, DO NOT USE THIS CLASS !!! ***
// DEPRECATED
public class AkGameObjPosOffsetData : UnityEngine.ScriptableObject
{
public UnityEngine.Vector3 positionOffset;
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c1e48680c5dc123428385ce50f8e9cf9
@@ -0,0 +1,26 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkGameObjPositionData
{
public UnityEngine.Vector3 forward;
public UnityEngine.Vector3 position;
public UnityEngine.Vector3 up;
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 602941824d606dc4bafa3188213fc76f
@@ -0,0 +1,33 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[System.Serializable]
public class AkGameObjPositionOffsetData
{
public bool KeepMe;
public UnityEngine.Vector3 positionOffset;
// Unity tries to construct a AkGameObjPositionOffsetData all the time. Need this ugly workaround
// to prevent it from doing this.
public AkGameObjPositionOffsetData(bool IReallyWantToBeConstructed = false)
{
KeepMe = IReallyWantToBeConstructed;
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7e99604e683f0564aa145dd231ad10fb
@@ -0,0 +1,356 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
using AK.Wwise.Unity.WwiseAddressables;
#endif
using AK.Wwise.Unity.Logging;
[UnityEngine.AddComponentMenu("Wwise/AkInitializer")]
[UnityEngine.ExecuteAlways]
[UnityEngine.DisallowMultipleComponent]
[UnityEngine.DefaultExecutionOrder(-100)]
/// @brief This script deals with initialization, and frame updates of the Wwise audio engine.
/// It is marked as \c DontDestroyOnLoad so it stays active for the life of the game,
/// not only one scene. Double-click the Initialization Settings entry, AkWwiseInitializationSettings,
/// to review and edit Wwise initialization settings.
/// \sa
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=workingwithsdks__initialization.html" target="_blank">Initialize the Different Modules of the Sound Engine</a> (Note: This is described in the Wwise SDK documentation.)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=namespace_a_k_1_1_sound_engine_a9a26da64092b97243844df77cbcdbf5f.html" target="_blank">AK::SoundEngine::Init()</a> (Note: This is described in the Wwise SDK documentation.)
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=namespace_a_k_1_1_sound_engine_a90f8c91937038615480db2b57ce2279e.html" target="_blank">AK::SoundEngine::Term()</a> (Note: This is described in the Wwise SDK documentation.)
/// - <a href="https://www.audiokinetic.com/en/library/edge/?source=Unity&id=enter_play_mode_behaviors.html" target="_blank">Enter Play Mode Behaviors</a>
/// - AkCallbackManager
public class AkInitializer : UnityEngine.MonoBehaviour
{
private static AkInitializer ms_Instance;
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
public AkWwiseAddressablesInitializationSettings InitializationSettings;
#else
public AkWwiseInitializationSettings InitializationSettings;
#endif
#if UNITY_WEBGL && !UNITY_EDITOR
[System.Runtime.InteropServices.DllImport("__Internal")]
private static extern bool AkVerifyPluginRegistration();
#endif
public static AkSurfaceReflector.GeometryData CubeGeometryData;
public static AkSurfaceReflector.GeometryData SphereGeometryData;
/// <summary>
/// Create Spatial Audio Geometry from Unity Box and Sphere Colliders.
/// When an AkRoom component is placed on a GameObject without a SurfaceReflector component, the AkRoom component's geometry is based on its sibling collider component.
/// Box, capsule, sphere, and mesh colliders can be converted to Spatial Audio Geometries and used as the geometry of Rooms.
/// For Box and sphere colliders, the geometry data is saved here to be used later for each corresponding AkRoom component.
/// </summary>
private void CreateRoomGeometryData()
{
float[] transmissionLossValue = { 0 };
// Cube Geometry
UnityEngine.GameObject tempGameObject = UnityEngine.GameObject.CreatePrimitive(UnityEngine.PrimitiveType.Cube);
UnityEngine.Mesh mesh = tempGameObject.GetComponent<UnityEngine.MeshFilter>().sharedMesh;
AkSurfaceReflector.GetGeometryDataFromMesh(mesh, ref CubeGeometryData, null, transmissionLossValue);
UnityEngine.GameObject.DestroyImmediate(tempGameObject);
// Sphere Geometry
tempGameObject = UnityEngine.GameObject.CreatePrimitive(UnityEngine.PrimitiveType.Sphere);
mesh = tempGameObject.GetComponent<UnityEngine.MeshFilter>().sharedMesh;
AkSurfaceReflector.GetGeometryDataFromMesh(mesh, ref SphereGeometryData, null, transmissionLossValue);
UnityEngine.GameObject.DestroyImmediate(tempGameObject);
}
private void Awake()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer)
{
return;
}
#endif
if (ms_Instance)
{
DestroyImmediate(this);
return;
}
ms_Instance = this;
#if UNITY_EDITOR
UnityEditor.EditorApplication.quitting += OnApplicationQuit;
if (!UnityEditor.EditorApplication.isPlaying)
{
return;
}
#if !(AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES)
WwiseProjectDatabase.SoundBankDirectoryUpdated += AkBankManager.ReloadAllBanks;
#endif
#endif
DontDestroyOnLoad(this);
}
private bool IsInstance()
{
if(ms_Instance == null)
{
ms_Instance = this;
return true;
}
return ms_Instance == this;
}
public static UnityEngine.GameObject GetAkInitializerGameObject()
{
if(ms_Instance != null)
{
return ms_Instance.gameObject;
}
WwiseLogger.Warning("AkInitializer is null.");
return null;
}
private void OnEnable()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
if (!AkWwiseEditorSettings.Instance.LoadSoundEngineInEditMode && !UnityEngine.Application.isPlaying)
{
return;
}
if(!UnityEngine.Application.isPlaying && UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
{
return;
}
#endif
InitializeInitializationSettings();
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES && UNITY_EDITOR
var bankHolder = UnityEngine.Object.FindObjectOfType<AK.Wwise.Unity.WwiseAddressables.InitBankHolder>();
if (bankHolder == null)
{
if (AkUtilities.IsRunningTest())
{
bankHolder = gameObject.AddComponent<InitBankHolder>();
}
else
{
bankHolder = UnityEditor.Undo.AddComponent<AK.Wwise.Unity.WwiseAddressables.InitBankHolder>(gameObject);
}
}
#endif
if (IsInstance())
{
#if UNITY_WEBGL && !UNITY_EDITOR
bool bRegistered = AkVerifyPluginRegistration();
if (!bRegistered)
WwiseLogger.Log("Wwise plug-in registration has failed. Some plug-ins may fail to initialize.");
#endif
AkSoundEngineController.Instance.Init(this);
CreateRoomGeometryData();
}
}
public void InitializeInitializationSettings()
{
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
InitializationSettings = AkWwiseAddressablesInitializationSettings.Instance;
#else
InitializationSettings = AkWwiseInitializationSettings.Instance;
#endif
}
private void OnDisable()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer)
{
return;
}
#endif
if (IsInstance())
{
AkSoundEngineController.Instance.OnDisable();
}
}
private void OnDestroy()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer)
{
return;
}
#endif
if (IsInstance())
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.quitting -= OnApplicationQuit;
#endif
ms_Instance = null;
}
#if UNITY_EDITOR
AkWwiseTypes.DragAndDropObjectReference = null;
#endif
}
private void OnApplicationPause(bool pauseStatus)
{
if (IsInstance())
{
AkSoundEngineController.Instance.OnApplicationPause(pauseStatus);
}
}
private void OnApplicationFocus(bool focus)
{
if (IsInstance())
{
AkSoundEngineController.Instance.OnApplicationFocus(focus);
}
}
private void OnApplicationQuit()
{
if (IsInstance() && !AkUnitySoundEngineInitialization.Instance.ShouldKeepSoundEngineEnabled())
{
AkSoundEngineController.Instance.Terminate();
}
}
//Use LateUpdate instead of Update() to ensure all gameobjects positions, listener positions, environements, RTPC, etc are set before finishing the audio frame.
private void LateUpdate()
{
if (IsInstance())
{
AkSoundEngineController.Instance.LateUpdate();
}
}
#region WwiseMigration
#if UNITY_EDITOR
#pragma warning disable 0414 // private field assigned but not used.
// previously serialized data that will be consumed by migration
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private string basePath = string.Empty;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private string language = string.Empty;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private int defaultPoolSize = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private int lowerPoolSize = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private int streamingPoolSize = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private float memoryCutoffThreshold = 0f;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private int monitorPoolSize = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private int monitorQueuePoolSize = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private int callbackManagerBufferSize = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private int spatialAudioPoolSize = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private uint maxSoundPropagationDepth = 0;
[UnityEngine.HideInInspector][UnityEngine.SerializeField] private bool engineLogging = false;
#pragma warning restore 0414 // private field assigned but not used.
private class Migration15Data
{
bool hasMigrated = false;
public void Migrate(AkInitializer akInitializer)
{
if (hasMigrated)
return;
var initializationSettings = akInitializer.InitializationSettings;
if (!initializationSettings)
{
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
initializationSettings = AkWwiseAddressablesInitializationSettings.Instance;
#else
initializationSettings = AkWwiseInitializationSettings.Instance;
#endif
if (!initializationSettings)
return;
}
if (initializationSettings.UserSettings == null)
{
initializationSettings.UserSettings = new AkCommonUserSettings();
}
if (initializationSettings.AdvancedSettings == null)
{
initializationSettings.AdvancedSettings = new AkCommonAdvancedSettings();
}
if (initializationSettings.CommsSettings == null)
{
initializationSettings.CommsSettings = new AkCommonCommSettings();
}
if (initializationSettings.UserSettings.m_SpatialAudioSettings == null)
{
initializationSettings.UserSettings.m_SpatialAudioSettings =
new AkCommonUserSettings.SpatialAudioSettings();
}
initializationSettings.UserSettings.m_BasePath = akInitializer.basePath;
initializationSettings.UserSettings.m_StartupLanguage = akInitializer.language;
initializationSettings.AdvancedSettings.m_MonitorQueuePoolSize = (uint)akInitializer.monitorQueuePoolSize * 1024;
initializationSettings.UserSettings.m_SpatialAudioSettings.m_MaxSoundPropagationDepth = akInitializer.maxSoundPropagationDepth;
initializationSettings.CallbackManagerInitializationSettings.IsLoggingEnabled = akInitializer.engineLogging;
UnityEditor.EditorUtility.SetDirty(initializationSettings);
UnityEditor.AssetDatabase.SaveAssets();
WwiseLogger.Log("Converted from AkInitializer to AkWwiseInitializationSettings.");
hasMigrated = true;
}
}
private static Migration15Data migration15data;
public static void PreMigration15()
{
migration15data = new Migration15Data();
}
public void Migrate15()
{
WwiseLogger.Log("AkInitializer.Migrate15 for " + gameObject.name);
if (migration15data != null)
{
migration15data.Migrate(this);
}
}
public static void PostMigration15()
{
migration15data = null;
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ca8082afa1214454c828fd22641b8692
@@ -0,0 +1,49 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.RequireComponent(typeof(AkAudioListener))]
[UnityEngine.DisallowMultipleComponent]
[UnityEngine.DefaultExecutionOrder(-10)]
///@brief Add this script on a listener game object to assign another game object as a distance probe.
/// The position of the distance probe will be used for distance calculations for the listener, instead of the position of the listener itself.
/// In third-person perspective applications, the distance probe Game Object may be set to the player character's position,
/// and the listener Game Object's position to that of the camera.
/// In this scenario, attenuation is based on the distance between the character and the sound, whereas panning, spatialization, and spread and focus calculations are based on the camera.
public class AkListenerDistanceProbe : UnityEngine.MonoBehaviour
{
[UnityEngine.Tooltip("Game object that is assigned as the distance probe for this listener.")]
public AkGameObj distanceProbe;
private void OnEnable()
{
if (distanceProbe)
{
var listenerGameObjectID = AkUnitySoundEngine.GetAkGameObjectID(this.gameObject);
var distanceProbeGameObjectID = AkUnitySoundEngine.GetAkGameObjectID(distanceProbe.gameObject);
AkUnitySoundEngine.SetDistanceProbe(listenerGameObjectID, distanceProbeGameObjectID);
}
}
private void OnDisable()
{
var listenerGameObjectID = AkUnitySoundEngine.GetAkGameObjectID(this.gameObject);
AkUnitySoundEngine.SetDistanceProbe(listenerGameObjectID, AkUnitySoundEngine.AK_INVALID_GAME_OBJECT);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: b55b2b6d08c631b4ca8721aeca3b4c4c
@@ -0,0 +1,150 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
/// @brief This class is an example of how to load banks in Wwise, if the bank data was preloaded in memory.
/// This would be useful for situations where you use the WWW class
public class AkMemBankLoader : UnityEngine.MonoBehaviour
{
private const int WaitMs = 50;
private const long AK_BANK_PLATFORM_DATA_ALIGNMENT = AkUnitySoundEngine.AK_BANK_PLATFORM_DATA_ALIGNMENT;
private const long AK_BANK_PLATFORM_DATA_ALIGNMENT_MASK = AK_BANK_PLATFORM_DATA_ALIGNMENT - 1;
/// Name of the bank to load
public string bankName = "";
/// Is the bank localized (situated in the language-specific folders)
public bool isLocalizedBank = false;
private string m_bankPath;
[UnityEngine.HideInInspector] public uint ms_bankID = AkUnitySoundEngine.AK_INVALID_BANK_ID;
private System.IntPtr ms_pInMemoryBankPtr = System.IntPtr.Zero;
private System.Runtime.InteropServices.GCHandle ms_pinnedArray;
#if UNITY_2018_3_OR_NEWER
private UnityEngine.Networking.UnityWebRequest ms_www;
#else
private UnityEngine.WWW ms_www;
#endif
private void Start()
{
if (isLocalizedBank)
LoadLocalizedBank(bankName);
else
LoadNonLocalizedBank(bankName);
}
/// Load a SoundBank from WWW object
public void LoadNonLocalizedBank(string in_bankFilename)
{
var bankPath = "file://" + System.IO.Path.Combine(AkBasePathGetter.Get().SoundBankBasePath, in_bankFilename);
DoLoadBank(bankPath);
}
/// Load a language-specific bank from WWW object
public void LoadLocalizedBank(string in_bankFilename)
{
var bankPath = "file://" + System.IO.Path.Combine(
System.IO.Path.Combine(AkBasePathGetter.Get().SoundBankBasePath, AkUnitySoundEngine.GetCurrentLanguage()),
in_bankFilename);
DoLoadBank(bankPath);
}
private uint AllocateAlignedBuffer(byte[] data)
{
uint uInMemoryBankSize = 0;
// Allocate an aligned buffer
try
{
ms_pinnedArray =
System.Runtime.InteropServices.GCHandle.Alloc(data, System.Runtime.InteropServices.GCHandleType.Pinned);
ms_pInMemoryBankPtr = ms_pinnedArray.AddrOfPinnedObject();
uInMemoryBankSize = (uint)data.Length;
// Array inside the WWW object is not aligned. Allocate a new array for which we can guarantee the alignment.
if ((ms_pInMemoryBankPtr.ToInt64() & AK_BANK_PLATFORM_DATA_ALIGNMENT_MASK) != 0)
{
var alignedBytes = new byte[data.Length + AK_BANK_PLATFORM_DATA_ALIGNMENT];
var new_pinnedArray =
System.Runtime.InteropServices.GCHandle.Alloc(alignedBytes, System.Runtime.InteropServices.GCHandleType.Pinned);
var new_pInMemoryBankPtr = new_pinnedArray.AddrOfPinnedObject();
var alignedOffset = 0;
// New array is not aligned, so we will need to use an offset inside it to align our data.
if ((new_pInMemoryBankPtr.ToInt64() & AK_BANK_PLATFORM_DATA_ALIGNMENT_MASK) != 0)
{
var alignedPtr = (new_pInMemoryBankPtr.ToInt64() + AK_BANK_PLATFORM_DATA_ALIGNMENT_MASK) &
~AK_BANK_PLATFORM_DATA_ALIGNMENT_MASK;
alignedOffset = (int)(alignedPtr - new_pInMemoryBankPtr.ToInt64());
new_pInMemoryBankPtr = new System.IntPtr(alignedPtr);
}
// Copy the bank's bytes in our new array, at the correct aligned offset.
System.Array.Copy(data, 0, alignedBytes, alignedOffset, data.Length);
ms_pInMemoryBankPtr = new_pInMemoryBankPtr;
ms_pinnedArray.Free();
ms_pinnedArray = new_pinnedArray;
}
}
catch
{
}
return uInMemoryBankSize;
}
private System.Collections.IEnumerator LoadFile()
{
#if UNITY_2018_3_OR_NEWER
ms_www = UnityEngine.Networking.UnityWebRequest.Get(m_bankPath);
yield return ms_www.SendWebRequest();
uint uInMemoryBankSize = AllocateAlignedBuffer(ms_www.downloadHandler.data);
#else
ms_www = new UnityEngine.WWW(m_bankPath);
yield return ms_www;
uint uInMemoryBankSize = AllocateAlignedBuffer(ms_www.bytes);
#endif
uint BankType;
var result = AkUnitySoundEngine.LoadBankMemoryView(ms_pInMemoryBankPtr, uInMemoryBankSize, out ms_bankID, out BankType);
if (result != AKRESULT.AK_Success)
WwiseLogger.Error("AkMemBankLoader: bank loading failed with result " + result);
}
private void DoLoadBank(string in_bankPath)
{
m_bankPath = in_bankPath;
StartCoroutine(LoadFile());
}
private void OnDestroy()
{
if (ms_pInMemoryBankPtr != System.IntPtr.Zero)
{
var result = AkUnitySoundEngine.UnloadBank(ms_bankID, ms_pInMemoryBankPtr);
if (result == AKRESULT.AK_Success)
ms_pinnedArray.Free();
}
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 3ba6e82404b309147b0da18460d6c359
@@ -0,0 +1,152 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public abstract class AkObstructionOcclusion : UnityEngine.MonoBehaviour
{
private readonly System.Collections.Generic.List<AkAudioListener> listenersToRemove =
new System.Collections.Generic.List<AkAudioListener>();
protected readonly System.Collections.Generic.List<AkAudioListener> currentListenerList = new System.Collections.Generic.List<AkAudioListener>();
private readonly System.Collections.Generic.Dictionary<AkAudioListener, ObstructionOcclusionValue>
ObstructionOcclusionValues = new System.Collections.Generic.Dictionary<AkAudioListener, ObstructionOcclusionValue>();
protected float fadeRate;
[UnityEngine.Tooltip("Fade time in seconds")]
/// The number of seconds for fade ins and fade outs.
public float fadeTime = 0.5f;
[UnityEngine.Tooltip("Layers of obstructers/occluders")]
/// Indicates which layers act as obstructers/occluders.
public UnityEngine.LayerMask LayerMask = -1;
[UnityEngine.Tooltip("Maximum distance to perform the obstruction/occlusion. Negative values mean infinite")]
/// The maximum distance at which to perform obstruction/occlusion. A negative value will be interpreted as inifinite distance.
public float maxDistance = -1.0f;
[UnityEngine.Tooltip("The number of seconds between raycasts")]
/// The number of seconds between obstruction/occlusion checks.
public float refreshInterval = 1;
private float refreshTime;
protected void InitIntervalsAndFadeRates()
{
refreshTime = refreshInterval + UnityEngine.Random.Range(0.0f, refreshInterval);
fadeRate = 1 / fadeTime;
}
protected abstract void UpdateCurrentListenerList();
private void UpdateObstructionOcclusionValues()
{
// add new listeners
for (var i = 0; i < currentListenerList.Count; ++i)
{
if (!ObstructionOcclusionValues.ContainsKey(currentListenerList[i]))
{
ObstructionOcclusionValues.Add(currentListenerList[i], new ObstructionOcclusionValue());
}
}
// remove listeners
foreach (var ObsOccPair in ObstructionOcclusionValues)
{
if (!currentListenerList.Contains(ObsOccPair.Key))
{
listenersToRemove.Add(ObsOccPair.Key);
}
}
for (var i = 0; i < listenersToRemove.Count; ++i)
{
ObstructionOcclusionValues.Remove(listenersToRemove[i]);
}
listenersToRemove.Clear();
}
private void CastRays()
{
if (refreshTime >= refreshInterval)
{
refreshTime -= refreshInterval;
foreach (var ObsOccPair in ObstructionOcclusionValues)
{
var listener = ObsOccPair.Key;
var ObsOccValue = ObsOccPair.Value;
var difference = listener.transform.position - transform.position;
var magnitude = difference.magnitude;
if (maxDistance > 0 && magnitude > maxDistance)
{
ObsOccValue.targetValue = ObsOccValue.currentValue;
}
else
{
ObsOccValue.targetValue =
UnityEngine.Physics.Raycast(transform.position, difference / magnitude, magnitude, LayerMask.value) ? 1.0f : 0.0f;
}
}
}
refreshTime += UnityEngine.Time.deltaTime;
}
protected abstract void SetObstructionOcclusion(
System.Collections.Generic.KeyValuePair<AkAudioListener, ObstructionOcclusionValue> ObsOccPair);
private void Update()
{
currentListenerList.Clear();
UpdateCurrentListenerList();
UpdateObstructionOcclusionValues();
CastRays();
foreach (var ObsOccPair in ObstructionOcclusionValues)
{
if (ObsOccPair.Value.Update(fadeRate))
{
SetObstructionOcclusion(ObsOccPair);
}
}
}
protected class ObstructionOcclusionValue
{
public float currentValue;
public float targetValue;
public bool Update(float fadeRate)
{
if (UnityEngine.Mathf.Approximately(targetValue, currentValue))
{
return false;
}
currentValue += fadeRate * UnityEngine.Mathf.Sign(targetValue - currentValue) * UnityEngine.Time.deltaTime;
currentValue = UnityEngine.Mathf.Clamp(currentValue, 0.0f, 1.0f);
return true;
}
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 37d0f6fdc8cb88a40b7b7bfc2e0ecf41
@@ -0,0 +1,128 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkRadialEmitter")]
[UnityEngine.RequireComponent(typeof(AkGameObj))]
[UnityEngine.DisallowMultipleComponent]
/// @brief A radial emitter is for sounds that are not point sources, but instead originate from a region of space.
/// @details A radial emitter is described by an inner and outer radius. The radii are used in spread and distance calculations, simulating a radial sound source.
/// Since all game objects have a position and orientation, the position (center) and local axes are defined by the AkGameObj component required by this component.
public class AkRadialEmitter : UnityEngine.MonoBehaviour
{
#region Fields
[UnityEngine.Tooltip("Define the outer radius around each sound position to simulate a radial sound source. If the listener is outside the outer radius, the spread is defined by the area that the sphere takes in the listener field of view. When the listener intersects the outer radius, the spread is exactly 50%. When the listener is in between the inner and outer radius, the spread interpolates linearly from 50% to 100%.")]
/// Define an outer radius around each sound position to simulate a radial sound source.
/// The distance used for applying attenuation curves is taken as the distance between the listener and the point on the sphere, defined by the sound position and the outer radius, that is closest to the listener.
/// The spread for each sound position is calculated as follows:
/// - If the listener is outside the outer radius, the spread is defined by the area that the sphere takes in the listener field of view. Specifically, this angle is calculated as 2.0*asinf( outerRadius / distance ), where distance is the distance between the listener and the sound position.
/// - When the listener intersects the outer radius (the listener is exactly outerRadius units away from the sound position), the spread is exactly 50%.
/// - When the listener is in between the inner and outer radius, the spread interpolates linearly from 50% to 100% as the listener transitions from the outer radius towards the inner radius.
/// Note that transmission and diffraction calculations in Spatial Audio always use the center of the sphere (the position(s) passed into \c AK::SoundEngine::SetPosition or \c AK::SoundEngine::SetMultiplePositions) for raycasting.
/// To obtain accurate diffraction and transmission calculations for radial sources, where different parts of the volume may take different paths through or around geometry,
/// it is necessary to pass multiple sound positions into \c AK::SoundEngine::SetMultiplePositions to allow the engine to 'sample' the area at different points.
public float outerRadius = 0.0f;
[UnityEngine.Tooltip("Define an inner radius around each sound position to simulate a radial sound source. If the listener is inside the inner radius, the spread is 100%.")]
/// Define an inner radius around each sound position to simulate a radial sound source. If the listener is inside the inner radius, the spread is 100%.
/// Note that transmission and diffraction calculations in Spatial Audio always use the center of the sphere (the position(s) passed into \c AK::SoundEngine::SetPosition or \c AK::SoundEngine::SetMultiplePositions) for raycasting.
/// To obtain accurate diffraction and transmission calculations for radial sources, where different parts of the volume may take different paths through or around geometry,
/// it is necessary to pass multiple sound positions into \c AK::SoundEngine::SetMultiplePositions to allow the engine to 'sample' the area at different points.
public float innerRadius = 0.0f;
private float previousOuterRadius = 0.0f;
private float previousInnerRadius = 0.0f;
#endregion
public void SetGameObjectOuterRadius(float in_outerRadius)
{
AkUnitySoundEngine.SetGameObjectRadius(AkUnitySoundEngine.GetAkGameObjectID(gameObject), in_outerRadius, innerRadius);
previousOuterRadius = outerRadius = in_outerRadius;
previousInnerRadius = innerRadius;
}
public void SetGameObjectInnerRadius(float in_innerRadius)
{
AkUnitySoundEngine.SetGameObjectRadius(AkUnitySoundEngine.GetAkGameObjectID(gameObject), outerRadius, in_innerRadius);
previousOuterRadius = outerRadius;
previousInnerRadius = innerRadius = in_innerRadius;
}
public void SetGameObjectRadius(float in_outerRadius, float in_innerRadius)
{
AkUnitySoundEngine.SetGameObjectRadius(AkUnitySoundEngine.GetAkGameObjectID(gameObject), in_outerRadius, in_innerRadius);
previousOuterRadius = outerRadius = in_outerRadius;
previousInnerRadius = innerRadius = in_innerRadius;
}
public void SetGameObjectRadius()
{
AkUnitySoundEngine.SetGameObjectRadius(AkUnitySoundEngine.GetAkGameObjectID(gameObject), outerRadius, innerRadius);
previousOuterRadius = outerRadius;
previousInnerRadius = innerRadius;
}
public void SetGameObjectRadius(UnityEngine.GameObject in_gameObject)
{
AkUnitySoundEngine.SetGameObjectRadius(AkUnitySoundEngine.GetAkGameObjectID(in_gameObject), outerRadius, innerRadius);
}
private void OnEnable()
{
SetGameObjectRadius();
}
#if UNITY_EDITOR
private void Update()
{
if (UnityEditor.EditorApplication.isPlaying)
{
if (previousOuterRadius != outerRadius ||
previousInnerRadius != innerRadius)
{
SetGameObjectRadius();
}
}
}
private void OnDrawGizmosSelected()
{
if (!enabled)
{
return;
}
AkAmbient Ambient = GetComponent<AkAmbient>();
bool showSpheres = true;
if (Ambient && Ambient.multiPositionTypeLabel == MultiPositionTypeLabel.Large_Mode)
{
showSpheres = false;
}
if (showSpheres)
{
UnityEngine.Color SphereColor = UnityEngine.Color.yellow;
SphereColor.a = 0.25f;
UnityEngine.Gizmos.color = SphereColor;
UnityEngine.Gizmos.DrawSphere(gameObject.transform.position, innerRadius);
UnityEngine.Gizmos.DrawSphere(gameObject.transform.position, outerRadius);
}
}
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ec853a51e37c023448f363de496cf452
@@ -0,0 +1,158 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkReverbZone")]
///@brief This component establishes a parent-child relationship between two Rooms and allows for sound propagation between them as if they were the same Room, without the need for a connecting Portal.
///@details Setting a Room as a Reverb Zone is useful in situations where two or more acoustic environments are not easily modeled as closed rooms connected by portals.
/// Possible uses for Reverb Zones include: a covered area with no walls, a forested area within an outdoor space, or any situation where multiple reverb effects are desired within a common space.
/// Reverb Zones have many advantages compared to standard Game-Defined Auxiliary Sends.
/// They are part of the wet path, and form reverb chains with other Rooms; they are spatialized according to their 3D extent; they are also subject to other acoustic phenomena simulated in Wwise Spatial Audio, such as diffraction and transmission.
/// A parent Room can have multiple Reverb Zones, but a Reverb Zone can only have a single Parent. A Room cannot be its own parent.
public class AkReverbZone : UnityEngine.MonoBehaviour
{
#region Fields
[UnityEngine.Tooltip("Set this Room as a Reverb Zone. Sound propagates between the Reverb Zone and its parent Room as if it were the same Room without the need for a connecting Portal. This is automatically populated by the current GameObject's Room component, if available.")]
/// Set this Room as a Reverb Zone. Sound propagates between the Reverb Zone and its parent Room as if it were the same Room without the need for a connecting Portal.
/// Examples include a covered area with no walls, a forested area within an outdoor space, or any situation where multiple reverb effects are desired within a common space.
public AkRoom ReverbZone;
[UnityEngine.Tooltip("Set this Room as the parent of the Reverb Zone. Sound propagates between the Reverb Zone and its parent Room as if it were the same Room without the need for a connecting Portal. A parent Room can have multiple Reverb Zones, but a Reverb Zone can only have a single Parent. A Room cannot be its own parent. Leave this set to None to attach the Reverb Zone to the automatically created 'Outdoors' Room.")]
/// Set this Room as the parent of the Reverb Zone. Sound propagates between the Reverb Zone and its parent Room as if it were the same Room without the need for a connecting Portal.
/// A parent Room can have multiple Reverb Zones, but a Reverb Zone can only have a single Parent. A Room cannot be its own parent.
/// The automatically created 'Outdoors' Room is commonly used as a parent Room for Reverb Zones, because they often model open spaces. Leave this set to None to attach the Reverb Zone to 'Outdoors'.
public AkRoom ParentRoom;
[UnityEngine.Tooltip("Width of the transition region between the Reverb Zone and its parent. The transition region is centered around the Reverb Zone geometry. It only applies where triangle transmission loss is set to 0.")]
/// Width of the transition region between the Reverb Zone and its parent. The transition zone is centered around the Reverb Zone geometry. It only applies where triangle transmission loss is set to 0.
public float TransitionRegionWidth = 1.0f;
#if UNITY_EDITOR
private bool needsUpdate = false;
#endif
#endregion
/// <summary>
/// Establish a parent-child relationship between two Rooms. Sound propagate between a Reverb Zone and its parent as if they were the same Room, without the need for a connecting Portal.
/// Examples of Reverb Zones include a covered area with no walls, a forested area within an outdoor space, or any situation where multiple reverb effects are desired within a common space.
/// Reverb Zones have many advantages compared to standard Game-Defined Auxiliary Sends. They are part of the wet path, and form reverb chains with other Rooms; they are spatialized according to their 3D extent; they are also subject to other acoustic phenomena simulated in Wwise Spatial Audio, such as diffraction and transmission.
/// If a Room is already assigned to a parent Room, it is first be removed from the original parent (exactly as if RemoveReverbZone were called) before it is assigned to the new parent Room.
/// The automatically created 'Outdoors' Room is commonly used as a parent Room for Reverb Zones, since they often model open spaces.
/// Calls AkRoom::SetReverbZone() from the Reverb Zone AkRoom component with the Parent Room and transition Region Width parameters.
/// </summary>
/// <param name="reverbZone">The AkRoom component to set as a Reverb Zone.</param>
/// <param name="parentRoom">The AkRoom component to set as the Reverb Zone's parent. A parent Room can have multiple Reverb Zones, but a Reverb Zone can only have a single Parent. A Room cannot be its own parent. Set to null to attach the Reverb Zone to the automatically created 'Outdoors' room.</param>
/// <param name="transitionRegionWidth">The width of the transition region between the Reverb Zone and its parent. The transition region is centered around the Reverb Zone geometry. It only applies where triangle transmission loss is set to 0.</param>
public static void SetReverbZone(
AkRoom reverbZone,
AkRoom parentRoom,
float transitionRegionWidth)
{
if (reverbZone == null)
{
WwiseLogger.Error("SetReverbZone: Invalid Room component as the Reverb Zone parameter.");
return;
}
reverbZone.SetReverbZone(parentRoom, transitionRegionWidth);
}
/// <summary>
/// Remove a Reverb Zone from its parent. Sound can no longer propagate between the two Rooms, unless they are explicitly connected with a Portal.
/// Calls AkRoom::RemoveReverbZone() from the Reverb Zone AkRoom component.
/// </summary>
/// <param name="reverbZone">The Reverb Zone AkRoom component.</param>
public static void RemoveReverbZone(
AkRoom reverbZone)
{
if (reverbZone == null)
{
WwiseLogger.Warning("RemoveReverbZone has an invalid Room component as its Reverb Zone parameter.");
return;
}
reverbZone.RemoveReverbZone();
}
/// <summary>
/// Calls AkReverbZone::SetReverbZone() with this component's properties
/// </summary>
public void SetReverbZone()
{
SetReverbZone(ReverbZone, ParentRoom, TransitionRegionWidth);
#if UNITY_EDITOR
needsUpdate = false;
#endif
}
/// <summary>
/// Calls AkReverbZone::RemoveReverbZone() with this component's properties
/// </summary>
public void RemoveReverbZone()
{
RemoveReverbZone(ReverbZone);
}
private void OnEnable()
{
SetReverbZone();
}
private void OnDisable()
{
RemoveReverbZone();
}
#if UNITY_EDITOR
// editor only function
// putting this in #if UNITY_EDITOR because of needsUpdate
private void OnValidate()
{
if (ReverbZone == null)
{
var currentGameObjectRoom = GetComponent<AkRoom>();
if (currentGameObjectRoom != null)
{
ReverbZone = currentGameObjectRoom;
}
}
if (TransitionRegionWidth < 0.0f)
{
TransitionRegionWidth = 0.0f;
}
needsUpdate = true;
}
// needsUpdate is only set to true in editor. No need to update in non-editor
private void Update()
{
if (!UnityEditor.EditorApplication.isPlaying)
{
return;
}
if (isActiveAndEnabled && needsUpdate)
{
SetReverbZone();
}
}
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 46c219bf9b866fe4b8065a9d7e6d1f2b
@@ -0,0 +1,899 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
// Matches the values of AkRoomDistanceBehavior
public enum AkRoomDistanceBehaviorLabel
{
Subtract = AkRoomDistanceBehavior.AkRoomDistanceBehavior_Subtract,
Exclude = AkRoomDistanceBehavior.AkRoomDistanceBehavior_Exclude
}
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkRoom")]
[UnityEngine.RequireComponent(typeof(UnityEngine.Collider))]
[UnityEngine.DisallowMultipleComponent]
/// @brief An AkRoom is an enclosed environment that can only communicate to the outside/other rooms with AkRoomPortals
/// @details The AkRoom component uses its required Collider component to determine when AkRoomAwareObjects enter and exit the room using the OnTriggerEnter and OnTriggerExit callbacks.
/// When using Spatial Audio Rooms and Portals, a default Room is automatically created to contain game objects that are currently not in a Room. This Room is typically used for the outdoors and is therefore called the Outdoors Room.
/// Because the Outdoors Room is automatically created, you do not have to add it to a scene, but you can customize it by using static functions in the AkRoom class.
public class AkRoom : AkTriggerHandler
{
public static ulong INVALID_ROOM_ID = unchecked((ulong)(-1));
public static ulong GetAkRoomID(AkRoom room)
{
return room == null ? INVALID_ROOM_ID : room.GetID();
}
public static int RoomCount { get; private set; }
#region Fields
[UnityEngine.Tooltip("Higher number has a higher priority")]
/// In cases where a game object is in an area with two rooms, the higher priority room will be chosen for AK::SpatialAudio::SetGameObjectInRoom()
/// The higher the priority number, the higher the priority of a room.
public int priority = 0;
/// The reverb auxiliary bus.
public AK.Wwise.AuxBus reverbAuxBus = new AK.Wwise.AuxBus();
[UnityEngine.Range(0, 1)]
/// The reverb control value for the send to the reverb aux bus.
public float reverbLevel = 1;
[UnityEngine.Range(0, 1)]
/// Loss value modeling transmission through walls.
public float transmissionLoss = 1;
/// [Experimental] Determines how a room interacts with the distance calculation of other rooms that it overlaps or is nested within.
public AkRoomDistanceBehaviorLabel distanceBehavior = (AkRoomDistanceBehaviorLabel)AkRoomDistanceBehavior.AkRoomDistanceBehavior_Default;
/// Wwise Event to be posted on the room game object.
public AK.Wwise.Event roomToneEvent = new AK.Wwise.Event();
[UnityEngine.Range(0, 1)]
[UnityEngine.Tooltip("Send level for sounds that are posted on the room game object; adds reverb to ambience and room tones. Valid range: (0.f-1.f). A value of 0 disables the aux send.")]
/// Send level for sounds that are posted on the room game object; adds reverb to ambience and room tones. Valid range: (0.f-1.f). A value of 0 disables the aux send.
public float roomToneAuxSend = 0;
[UnityEngine.Tooltip("Set to true to set this room as static: a room that will not move nor will its properties change during gameplay. A non-static room will check the state of its transform and the state of its properties each frame and update the room in Wwise if there is a change.")]
/// Set to true to set this room as static: a room that will not move nor will its properties change during gameplay. A non-static room will check the state of its transform and the state of its properties each frame and update the room in Wwise if there is a change.
public bool isStatic = false;
/// This is the list of AkRoomAwareObjects that have entered this AkRoom
private System.Collections.Generic.List<AkRoomAwareObject> roomAwareObjectsEntered = new System.Collections.Generic.List<AkRoomAwareObject>();
/// This is the list of AkRoomAwareObjects that have entered this AkRoom while it was inactive or disabled.
private System.Collections.Generic.List<AkRoomAwareObject> roomAwareObjectsDetectedWhileDisabled = new System.Collections.Generic.List<AkRoomAwareObject>();
private UnityEngine.Collider roomCollider = null;
private int previousRoomState;
private int previousTransformState;
private int previousGeometryTransformState;
private int previousGeometryState;
private bool bSentToWwise = false;
private bool bypassPortalSubtraction = false;
private bool isSolid = false;
private ulong geometryID = AkSurfaceReflector.INVALID_GEOMETRY_ID;
private bool bGeometrySetByRoom = false;
private bool _isAReverbZoneInWwise = false;
private ulong _parentRoomID = AkRoom.INVALID_ROOM_ID;
public bool IsAReverbZoneInWwise { get { return _isAReverbZoneInWwise; } }
public ulong ParentRoomID { get { return _parentRoomID; } }
#endregion
private int GetRoomState()
{
int[] hashCodes = new[] {
reverbAuxBus.IsValid() ? reverbAuxBus.GetHashCode() : 0,
reverbLevel.GetHashCode(),
transmissionLoss.GetHashCode(),
distanceBehavior.GetHashCode(),
priority.GetHashCode(),
roomToneEvent.IsValid() ? roomToneEvent.GetHashCode() : 0,
roomToneAuxSend.GetHashCode(),
transform.rotation.GetHashCode()
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
private int GetTransformState()
{
int[] hashCodes = new[] {
transform.position.GetHashCode(),
transform.lossyScale.GetHashCode(),
transform.rotation.GetHashCode()
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
private int GetGeometryTransformState()
{
if (IsAssociatedGeometryFromCollider())
{
if (roomCollider == null)
{
roomCollider = GetComponent<UnityEngine.Collider>();
}
if (roomCollider.GetType() == typeof(UnityEngine.BoxCollider))
{
int[] hashCodes = new[] {
((UnityEngine.BoxCollider)roomCollider).center.GetHashCode(),
((UnityEngine.BoxCollider)roomCollider).size.GetHashCode(),
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
else if (roomCollider.GetType() == typeof(UnityEngine.CapsuleCollider))
{
int[] hashCodes = new[] {
((UnityEngine.CapsuleCollider)roomCollider).center.GetHashCode(),
((UnityEngine.CapsuleCollider)roomCollider).radius.GetHashCode(),
((UnityEngine.CapsuleCollider)roomCollider).height.GetHashCode(),
((UnityEngine.CapsuleCollider)roomCollider).direction.GetHashCode(),
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
else if (roomCollider.GetType() == typeof(UnityEngine.SphereCollider))
{
int[] hashCodes = new[] {
((UnityEngine.SphereCollider)roomCollider).center.GetHashCode(),
((UnityEngine.SphereCollider)roomCollider).radius.GetHashCode(),
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
}
return 0;
}
private int GetGeometryState()
{
if (IsAssociatedGeometryFromCollider())
{
if (roomCollider == null)
{
roomCollider = GetComponent<UnityEngine.Collider>();
}
int colliderHash = roomCollider.GetHashCode();
int meshHash = 0;
if (roomCollider.GetType() == typeof(UnityEngine.MeshCollider))
{
meshHash = ((UnityEngine.MeshCollider)roomCollider).sharedMesh.GetHashCode();
}
int[] hashCodes = new[] {
colliderHash,
meshHash
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
return 0;
}
public bool TryEnter(AkRoomAwareObject roomAwareObject)
{
if (roomAwareObject)
{
if (isActiveAndEnabled)
{
if(!roomAwareObjectsEntered.Contains(roomAwareObject))
{
roomAwareObjectsEntered.Add(roomAwareObject);
}
return true;
}
else
{
if (!roomAwareObjectsDetectedWhileDisabled.Contains(roomAwareObject))
{
roomAwareObjectsDetectedWhileDisabled.Add(roomAwareObject);
}
return false;
}
}
return false;
}
public void Exit(AkRoomAwareObject roomAwareObject)
{
if (roomAwareObject)
{
roomAwareObjectsEntered.Remove(roomAwareObject);
roomAwareObjectsDetectedWhileDisabled.Remove(roomAwareObject);
}
}
/// Access the room's ID
public ulong GetID()
{
return AkUnitySoundEngine.GetAkGameObjectID(gameObject);
}
public bool IsAssociatedGeometryFromCollider()
{
return geometryID == GetID();
}
private void SetGeometryFromCollider()
{
if (roomCollider == null)
{
roomCollider = GetComponent<UnityEngine.Collider>();
}
if (roomCollider.GetType() == typeof(UnityEngine.MeshCollider))
{
var MeshGeometryData = new AkSurfaceReflector.GeometryData();
AkSurfaceReflector.GetGeometryDataFromMesh(((UnityEngine.MeshCollider)roomCollider).sharedMesh, ref MeshGeometryData);
for (int s = 0; s < MeshGeometryData.numSurfaces; s++)
{
MeshGeometryData.surfaces[s].transmissionLoss = 0;
}
geometryID = GetID();
AkUnitySoundEngine.SetGeometry(
geometryID,
MeshGeometryData.triangles,
MeshGeometryData.numTriangles,
MeshGeometryData.vertices,
MeshGeometryData.numVertices,
MeshGeometryData.surfaces,
MeshGeometryData.numSurfaces,
false,
false);
bGeometrySetByRoom = true;
}
else if ((roomCollider.GetType() == typeof(UnityEngine.BoxCollider) || (roomCollider.GetType() == typeof(UnityEngine.CapsuleCollider)) && AkInitializer.CubeGeometryData.numTriangles != 0))
{
// The capsule collider is approximated with a cube geometry
geometryID = GetID();
AkUnitySoundEngine.SetGeometry(
geometryID,
AkInitializer.CubeGeometryData.triangles,
AkInitializer.CubeGeometryData.numTriangles,
AkInitializer.CubeGeometryData.vertices,
AkInitializer.CubeGeometryData.numVertices,
AkInitializer.CubeGeometryData.surfaces,
AkInitializer.CubeGeometryData.numSurfaces,
false,
false);
bGeometrySetByRoom = true;
}
else if (roomCollider.GetType() == typeof(UnityEngine.SphereCollider) && AkInitializer.SphereGeometryData.numTriangles != 0)
{
geometryID = GetID();
AkUnitySoundEngine.SetGeometry(
geometryID,
AkInitializer.SphereGeometryData.triangles,
AkInitializer.SphereGeometryData.numTriangles,
AkInitializer.SphereGeometryData.vertices,
AkInitializer.SphereGeometryData.numVertices,
AkInitializer.SphereGeometryData.surfaces,
AkInitializer.SphereGeometryData.numSurfaces,
false,
false);
bGeometrySetByRoom = true;
}
else
{
WwiseLogger.Warning(name + " has an invalid collider for wet transmission. Wet Transmission will be disabled.");
geometryID = AkSurfaceReflector.INVALID_GEOMETRY_ID;
}
}
private void SetGeometryInstanceFromCollider()
{
if (!bGeometrySetByRoom)
{
SetGeometryFromCollider();
}
if (!bGeometrySetByRoom)
{
return;
}
if (roomCollider == null)
{
roomCollider = GetComponent<UnityEngine.Collider>();
}
if (roomCollider.GetType() == typeof(UnityEngine.MeshCollider))
{
geometryID = GetID();
AkSurfaceReflector.SetGeometryInstance(geometryID, geometryID, transform, false, bypassPortalSubtraction, isSolid);
}
else if (roomCollider.GetType() == typeof(UnityEngine.BoxCollider) && AkInitializer.CubeGeometryData.numTriangles != 0)
{
geometryID = GetID();
AkTransform geometryInstanceTransform = new AkTransform();
geometryInstanceTransform.Set(roomCollider.bounds.center, transform.forward, transform.up);
UnityEngine.Vector3 geometryInstanceScale = new UnityEngine.Vector3(
transform.lossyScale.x * ((UnityEngine.BoxCollider)roomCollider).size.x,
transform.lossyScale.y * ((UnityEngine.BoxCollider)roomCollider).size.y,
transform.lossyScale.z * ((UnityEngine.BoxCollider)roomCollider).size.z);
AkUnitySoundEngine.SetGeometryInstance(geometryID, geometryInstanceTransform, geometryInstanceScale, geometryID, false, bypassPortalSubtraction, isSolid);
}
else if (roomCollider.GetType() == typeof(UnityEngine.CapsuleCollider) && AkInitializer.CubeGeometryData.numTriangles != 0)
{
geometryID = GetID();
AkTransform geometryInstanceTransform = new AkTransform();
geometryInstanceTransform.Set(roomCollider.bounds.center, transform.forward, transform.up);
UnityEngine.Vector3 geometryInstanceScale = GetCubeScaleFromCapsule(
transform.lossyScale,
((UnityEngine.CapsuleCollider)roomCollider).radius,
((UnityEngine.CapsuleCollider)roomCollider).height,
((UnityEngine.CapsuleCollider)roomCollider).direction);
AkUnitySoundEngine.SetGeometryInstance(geometryID, geometryInstanceTransform, geometryInstanceScale, geometryID, false, bypassPortalSubtraction, isSolid);
}
else if (roomCollider.GetType() == typeof(UnityEngine.SphereCollider) && AkInitializer.SphereGeometryData.numTriangles != 0)
{
geometryID = GetID();
AkTransform geometryInstanceTransform = new AkTransform();
geometryInstanceTransform.Set(roomCollider.bounds.center, transform.forward, transform.up);
UnityEngine.Vector3 geometryInstanceScale = roomCollider.bounds.size;
AkUnitySoundEngine.SetGeometryInstance(geometryID, geometryInstanceTransform, geometryInstanceScale, geometryID, false, bypassPortalSubtraction, isSolid);
}
else
{
WwiseLogger.Warning(name + " has an invalid collider for wet transmission. Wet Transmission will be disabled.");
geometryID = AkSurfaceReflector.INVALID_GEOMETRY_ID;
}
}
public void SetRoom()
{
if (!AkUnitySoundEngine.IsInitialized())
{
return;
}
var roomParams = new AkRoomParams
{
Up = transform.up,
Front = transform.forward,
ReverbAuxBus = reverbAuxBus.Id,
ReverbLevel = reverbLevel,
TransmissionLoss = transmissionLoss,
RoomGameObj_AuxSendLevelToSelf = roomToneAuxSend,
RoomGameObj_KeepRegistered = roomToneEvent.IsValid(),
RoomPriority = priority,
DistanceBehavior = (AkRoomDistanceBehavior)distanceBehavior
};
if (bSentToWwise == false)
{
RoomCount++;
}
if (geometryID == AkSurfaceReflector.INVALID_GEOMETRY_ID)
{
SetGeometryInstanceFromCollider();
}
AkUnitySoundEngine.SetRoom(GetID(), roomParams, geometryID, name);
bSentToWwise = true;
}
public void SetRoom(ulong id)
{
if (geometryID != id)
{
if (IsAssociatedGeometryFromCollider())
{
AkUnitySoundEngine.RemoveGeometryInstance(GetID());
}
geometryID = id;
}
SetRoom();
}
public bool UsesGeometry(ulong id)
{
return geometryID == id;
}
private void Update()
{
// don't update if is static
if (isStatic) return;
bool GeometryNeedsUpdate = false;
bool GeometryInstanceNeedsUpdate = false;
bool RoomNeedsUpdate = false;
bool PortalsNeedUpdate = false;
int currentTransformState = GetTransformState();
if (previousTransformState != currentTransformState)
{
if (IsAssociatedGeometryFromCollider())
{
GeometryInstanceNeedsUpdate = true;
}
PortalsNeedUpdate = true;
previousTransformState = currentTransformState;
}
else
{
int currentGeometryTransformState = GetGeometryTransformState();
if (previousGeometryTransformState != currentGeometryTransformState)
{
if (IsAssociatedGeometryFromCollider())
{
GeometryInstanceNeedsUpdate = true;
}
PortalsNeedUpdate = true;
previousGeometryTransformState = currentGeometryTransformState;
}
}
int currentGeometryState = GetGeometryState();
if (previousGeometryState != currentGeometryState)
{
if (IsAssociatedGeometryFromCollider())
{
GeometryNeedsUpdate = true;
}
PortalsNeedUpdate = true;
previousGeometryState = currentGeometryState;
}
int currentRoomState = GetRoomState();
if (previousRoomState != currentRoomState)
{
RoomNeedsUpdate = true;
previousRoomState = currentRoomState;
}
if (GeometryNeedsUpdate)
{
SetGeometryFromCollider();
}
if (GeometryInstanceNeedsUpdate)
{
SetGeometryInstanceFromCollider();
}
if (RoomNeedsUpdate)
{
SetRoom();
}
if (PortalsNeedUpdate)
{
AkRoomManager.RegisterRoomUpdate(this);
}
}
private UnityEngine.Vector3 GetCubeScaleFromCapsule(UnityEngine.Vector3 capsuleScale, float capsuleRadius, float capsuleHeight, int capsuleDirection)
{
UnityEngine.Vector3 cubeScale = new UnityEngine.Vector3();
capsuleScale.x = UnityEngine.Mathf.Abs(capsuleScale.x);
capsuleScale.y = UnityEngine.Mathf.Abs(capsuleScale.y);
capsuleScale.z = UnityEngine.Mathf.Abs(capsuleScale.z);
switch (capsuleDirection)
{
case 0:
cubeScale.y = UnityEngine.Mathf.Max(capsuleScale.y, capsuleScale.z) * (capsuleRadius * 2);
cubeScale.z = cubeScale.y;
cubeScale.x = UnityEngine.Mathf.Max(cubeScale.y, capsuleScale.x * capsuleHeight);
break;
case 2:
cubeScale.x = UnityEngine.Mathf.Max(capsuleScale.x, capsuleScale.y) * (capsuleRadius * 2);
cubeScale.y = cubeScale.x;
cubeScale.z = UnityEngine.Mathf.Max(cubeScale.x, capsuleScale.z * capsuleHeight);
break;
case 1:
default:
cubeScale.x = UnityEngine.Mathf.Max(capsuleScale.x, capsuleScale.z) * (capsuleRadius * 2);
cubeScale.y = UnityEngine.Mathf.Max(cubeScale.x, capsuleScale.y * capsuleHeight);
cubeScale.z = cubeScale.x;
break;
}
return cubeScale;
}
public override void OnEnable()
{
roomCollider = GetComponent<UnityEngine.Collider>();
AkSurfaceReflector surfaceReflectorComponent = gameObject.GetComponent<AkSurfaceReflector>();
if (surfaceReflectorComponent != null && surfaceReflectorComponent.enabled)
{
bypassPortalSubtraction = surfaceReflectorComponent.BypassPortalSubtraction;
isSolid = surfaceReflectorComponent.Solid;
geometryID = surfaceReflectorComponent.GetID();
}
else
{
// better call both, even if the geometry might have already been sent to wwise, in case something related to the geometry changed while the room was disabled.
SetGeometryFromCollider();
SetGeometryInstanceFromCollider();
}
SetRoom();
AkRoomManager.RegisterRoomUpdate(this);
// if objects entered the room while disabled, enter them now
for (var i = 0; i < roomAwareObjectsDetectedWhileDisabled.Count; ++i)
{
AkRoomAwareManager.ObjectEnteredRoom(roomAwareObjectsDetectedWhileDisabled[i], this);
}
roomAwareObjectsDetectedWhileDisabled.Clear();
base.OnEnable();
// init update condition
previousRoomState = GetRoomState();
previousTransformState = GetTransformState();
previousGeometryTransformState = GetGeometryTransformState();
previousGeometryState = GetGeometryState();
}
private void OnDisable()
{
for (var i = 0; i < roomAwareObjectsEntered.Count; ++i)
{
roomAwareObjectsEntered[i].ExitedRoom(this);
AkRoomAwareManager.RegisterRoomAwareObjectForUpdate(roomAwareObjectsEntered[i]);
roomAwareObjectsDetectedWhileDisabled.Add(roomAwareObjectsEntered[i]);
}
roomAwareObjectsEntered.Clear();
AkRoomManager.RegisterRoomUpdate(this);
if (IsAssociatedGeometryFromCollider())
{
AkUnitySoundEngine.RemoveGeometryInstance(GetID());
}
geometryID = AkSurfaceReflector.INVALID_GEOMETRY_ID;
// stop sounds applied to the room game object
if (roomToneEvent.IsValid())
{
AkUnitySoundEngine.StopAll(GetID());
}
RoomCount--;
AkUnitySoundEngine.RemoveRoom(GetID());
bSentToWwise = false;
}
protected override void OnDestroy()
{
if (bGeometrySetByRoom)
{
AkUnitySoundEngine.RemoveGeometry(GetID());
bGeometrySetByRoom = false;
}
base.OnDestroy();
}
private void OnTriggerEnter(UnityEngine.Collider in_other)
{
AkRoomAwareManager.ObjectEnteredRoom(in_other, this);
}
private void OnTriggerExit(UnityEngine.Collider in_other)
{
AkRoomAwareManager.ObjectExitedRoom(in_other, this);
}
public void PostRoomTone()
{
if (roomToneEvent.IsValid() && isActiveAndEnabled)
{
roomToneEvent.Post(GetID());
}
}
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
PostRoomTone();
}
/// <summary>
/// Establish a parent-child relationship between this Room and a parent Room. Sound propagate between a Reverb Zone and its parent as if they were the same Room, without the need for a connecting Portal.
/// Examples of Reverb Zones include a covered area with no walls, a forested area within an outdoor space, or any situation where multiple reverb effects are desired within a common space.
/// Reverb Zones have many advantages compared to standard Game-Defined Auxiliary Sends. They are part of the wet path, and form reverb chains with other Rooms; they are spatialized according to their 3D extent; they are also subject to other acoustic phenomena simulated in Wwise Spatial Audio, such as diffraction and transmission.
/// If a Room is already assigned to a parent Room, it is first be removed from the original parent (exactly as if RemoveReverbZone were called) before it is assigned to the new parent Room.
/// The automatically created 'Outdoors' Room is commonly used as a parent Room for Reverb Zones, since they often model open spaces.
/// Calls AK::SpatialAudio::SetReverbZone() with the Parent Room and transition Region Width parameters.
/// </summary>
/// <param name="parentRoom">The AkRoom component to set as the Reverb Zone's parent. A parent Room can have multiple Reverb Zones, but a Reverb Zone can only have a single Parent. A Room cannot be its own parent. Set to null to attach the Reverb Zone to the automatically created 'Outdoors' room.</param>
/// <param name="transitionRegionWidth">The width of the transition region between the Reverb Zone and its parent. The transition region is centered around the Reverb Zone geometry. It only applies where triangle transmission loss is set to 0.</param>
public void SetReverbZone(AkRoom parentRoom, float transitionRegionWidth)
{
_parentRoomID = AkRoom.INVALID_ROOM_ID;
if (parentRoom != null)
{
_parentRoomID = parentRoom.GetID();
}
if (transitionRegionWidth < 0.0f)
{
WwiseLogger.Warning("SetReverbZone: Transition region width is a negative number. It has been clamped to 0.");
transitionRegionWidth = 0.0f;
}
AkUnitySoundEngine.SetReverbZone(GetID(), ParentRoomID, transitionRegionWidth);
_isAReverbZoneInWwise = true;
}
/// <summary>
/// Remove this Room, a Reverb Zone, from its parent. Sound can no longer propagate between this Room and its parent, unless they are explicitly connected with a Portal.
/// Calls AK::SpatialAudio::RemoveReverbZone() with this Room's ID."/>.
/// </summary>
public void RemoveReverbZone()
{
AkUnitySoundEngine.RemoveReverbZone(GetID());
_isAReverbZoneInWwise = false;
}
public class PriorityList
{
private static readonly CompareByPriority s_compareByPriority = new CompareByPriority();
/// Contains all active rooms sorted by priority.
private System.Collections.Generic.List<AkRoom> rooms = new System.Collections.Generic.List<AkRoom>();
public ulong GetHighestPriorityActiveAndEnabledRoomID()
{
var room = GetHighestPriorityActiveAndEnabledRoom();
return GetAkRoomID(room);
}
public AkRoom GetHighestPriorityActiveAndEnabledRoom()
{
for (int i = 0; i < rooms.Count; i++)
{
if (rooms[i].isActiveAndEnabled)
{
return rooms[i];
}
}
return null;
}
public int Count { get { return rooms.Count; } }
public void Clear()
{
rooms.Clear();
}
public void Add(AkRoom room)
{
var index = BinarySearch(room);
if (index < 0)
{
rooms.Insert(~index, room);
}
}
public void Remove(AkRoom room)
{
rooms.Remove(room);
}
public bool Contains(AkRoom room)
{
return room && rooms.Contains(room);
}
public int BinarySearch(AkRoom room)
{
return room ? rooms.BinarySearch(room, s_compareByPriority) : -1;
}
public AkRoom this[int index]
{
get { return rooms[index]; }
}
private class CompareByPriority : System.Collections.Generic.IComparer<AkRoom>
{
public virtual int Compare(AkRoom a, AkRoom b)
{
var result = a.priority.CompareTo(b.priority);
if (result == 0 && a != b)
{
return 1;
}
return -result; // inverted to have highest priority first
}
}
}
#region OutdoorsRoom
private static ulong INVALID_ROOM_GAMEOBJECT_ID = unchecked((ulong)(-4));
private static AkRoom.OutdoorsRoomParameters _currentOutdoorsRoomParameters = AkRoom.OutdoorsRoomParameters.Default;
/// <summary>
/// The current Outdoors Room parameters.
/// </summary>
static public AkRoom.OutdoorsRoomParameters currentOutdoorsRoomParameters { get { return _currentOutdoorsRoomParameters; } }
/// <summary>
/// Structure containing the parameters of the Outdoors Room.
/// When using the Spatial Audio Rooms and Portal feature, a default Room is automatically created to place game objects that are currently not in a Room. This Room is typically used for outdoors and is therefore nicknamed the Outdoors Room.
/// </summary>
public struct OutdoorsRoomParameters
{
public OutdoorsRoomParameters(AK.Wwise.AuxBus in_reverbAuxBus, float in_reverbLevel, float in_transmissionLoss, float in_auxSendLevel, bool in_keepRegistered)
{
reverbAuxBus = in_reverbAuxBus;
reverbLevel = in_reverbLevel;
transmissionLoss = in_transmissionLoss;
auxSendLevel = in_auxSendLevel;
keepRegistered = in_keepRegistered;
}
/// The reverb auxiliary bus used by the Outdoors Room.
public AK.Wwise.AuxBus reverbAuxBus;
/// The reverb control value for the send to the reverb aux bus. Valid range: (0.f-1.f). Default value is 1.
public float reverbLevel;
/// Loss value modeling transmission through the outdoors room volume. Valid range: (0.f-1.f). Default value is 0.
public float transmissionLoss;
/// Send level for sounds that are posted on the outdoors room game object. This property adds reverb to ambience and room tones. Valid range: (0.f-1.f). A value of 0 disables the aux send. Default value is 0.
public float auxSendLevel;
/// If set to false, Spatial Audio registers the room object only when it is needed by the sound propagation system for the purposes of reverb,
/// and unregisters the game object when all reverb tails are finished.
/// We recommend that you set this property to true if you call PostEvent() for the purpose of ambience or room tones.
/// Default value is false.
public bool keepRegistered;
/// <summary>
/// Gets an OutdoorsRoomParameters structure with all parameters set to their Default values.
/// </summary>
public static OutdoorsRoomParameters Default
{
get { return new OutdoorsRoomParameters(null, 1.0f, .0f, .0f, false); }
}
}
/// <summary>
/// Sets the parameters of the defaut Outdoors Room.
/// </summary>
/// <param name="in_outdoorsRoomParameters">Structure containing the new parameters of the Outdoors Room.</param>
static public void SetOutdoorsRoomParameters(OutdoorsRoomParameters in_outdoorsRoomParameters)
{
_currentOutdoorsRoomParameters = in_outdoorsRoomParameters;
if (!AkUnitySoundEngine.IsInitialized())
{
return;
}
AkRoomParams roomParams = new AkRoomParams();
uint shortID = AK.Wwise.AuxBus.InvalidId;
if (_currentOutdoorsRoomParameters.reverbAuxBus != null && _currentOutdoorsRoomParameters.reverbAuxBus.IsValid())
{
shortID = _currentOutdoorsRoomParameters.reverbAuxBus.Id;
if (shortID == AK.Wwise.AuxBus.InvalidId)
{
WwiseLogger.Log("AkRoom.SetOutdoorsRoomParameters : AuxBus passed in parameters has an invalid ShortId.");
}
}
roomParams.ReverbAuxBus = shortID;
roomParams.ReverbLevel = _currentOutdoorsRoomParameters.reverbLevel;
roomParams.TransmissionLoss = _currentOutdoorsRoomParameters.transmissionLoss;
roomParams.RoomGameObj_AuxSendLevelToSelf = _currentOutdoorsRoomParameters.auxSendLevel;
roomParams.RoomGameObj_KeepRegistered = _currentOutdoorsRoomParameters.keepRegistered;
roomParams.RoomPriority = 1;
AkUnitySoundEngine.SetRoom(AkRoom.INVALID_ROOM_ID, roomParams, AkSurfaceReflector.INVALID_GEOMETRY_ID, "Outdoors");
}
/// <summary>
/// Posts an Event on the Outdoors Room.
/// </summary>
/// <param name="in_event">Envent to play.</param>
/// <returns></returns>
static public uint PostEventOutdoors(AK.Wwise.Event in_event)
{
if (!in_event.IsValid())
return AkUnitySoundEngine.AK_INVALID_PLAYING_ID;
// before posting an event to the outdoors room, we need to make sure the room Game Object ID exists
// We need to set AkRoomParams.RoomGameObj_KeepRegistered to true
if (!_currentOutdoorsRoomParameters.keepRegistered)
{
_currentOutdoorsRoomParameters.keepRegistered = true;
AkRoom.SetOutdoorsRoomParameters(_currentOutdoorsRoomParameters);
}
return in_event.Post(AkRoom.INVALID_ROOM_GAMEOBJECT_ID);
}
/// <summary>
/// Stops all sounds for the Outdoors Room.
/// </summary>
static public void StopOutdoors()
{
AkUnitySoundEngine.StopAll(AkRoom.INVALID_ROOM_GAMEOBJECT_ID);
}
#endregion
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2021_1_0)]
public float wallOcclusion
{
get
{
return transmissionLoss;
}
set
{
transmissionLoss = value;
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2023_1_0)]
public ulong GetGeometryID()
{
return geometryID;
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2023_1_0)]
public void SetGeometryID(ulong id)
{
geometryID = id;
}
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 841693c577a177142b4841aafaab4c42
@@ -0,0 +1,105 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
/// @brief This manager tracks the AkRoomAwareObjects and the AkRooms in which they enter and exit.
/// @details At the end of the frame, the AkRoomAwareObject is set in the highest priority AkRoom in Spatial Audio.
public static class AkRoomAwareManager
{
private static readonly System.Collections.Generic.HashSet<AkRoomAwareObject> m_RoomAwareObjects =
new System.Collections.Generic.HashSet<AkRoomAwareObject>();
private static readonly System.Collections.Generic.HashSet<AkRoomAwareObject> m_RoomAwareObjectToUpdate =
new System.Collections.Generic.HashSet<AkRoomAwareObject>();
public static void RegisterRoomAwareObject(AkRoomAwareObject roomAwareObject)
{
m_RoomAwareObjects.Add(roomAwareObject);
RegisterRoomAwareObjectForUpdate(roomAwareObject);
}
public static void UnregisterRoomAwareObject(AkRoomAwareObject roomAwareObject)
{
m_RoomAwareObjects.Remove(roomAwareObject);
m_RoomAwareObjectToUpdate.Remove(roomAwareObject);
}
public static void RegisterRoomAwareObjectForUpdate(AkRoomAwareObject roomAwareObject)
{
m_RoomAwareObjectToUpdate.Add(roomAwareObject);
}
public static void ObjectEnteredRoom(UnityEngine.Collider collider, AkRoom room)
{
if (!collider)
{
return;
}
ObjectEnteredRoom(AkRoomAwareObject.GetAkRoomAwareObjectFromCollider(collider), room);
}
public static void ObjectEnteredRoom(AkRoomAwareObject roomAwareObject, AkRoom room)
{
if (!roomAwareObject || !room)
{
return;
}
var enteredRoom = room.TryEnter(roomAwareObject);
if (enteredRoom)
{
roomAwareObject.EnteredRoom(room);
RegisterRoomAwareObjectForUpdate(roomAwareObject);
}
}
public static void ObjectExitedRoom(UnityEngine.Collider collider, AkRoom room)
{
if (!collider)
{
return;
}
ObjectExitedRoom(AkRoomAwareObject.GetAkRoomAwareObjectFromCollider(collider), room);
}
public static void ObjectExitedRoom(AkRoomAwareObject roomAwareObject, AkRoom room)
{
if (!roomAwareObject || !room)
{
return;
}
room.Exit(roomAwareObject);
roomAwareObject.ExitedRoom(room);
RegisterRoomAwareObjectForUpdate(roomAwareObject);
}
public static void UpdateRoomAwareObjects()
{
foreach (var roomAwareObject in m_RoomAwareObjectToUpdate)
{
if (m_RoomAwareObjects.Contains(roomAwareObject))
{
roomAwareObject.SetGameObjectInHighestPriorityActiveAndEnabledRoom();
}
}
m_RoomAwareObjectToUpdate.Clear();
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0f31921d42049394280817298c1dc622
@@ -0,0 +1,107 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
/// <summary>
/// This component makes a GameObject aware of AkRoom components.
/// When using Spatial Audio rooms, all emitters and the spatial audio listener should have this component.
/// </summary>
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkRoomAwareObject")]
[UnityEngine.RequireComponent(typeof(AkGameObj))]
[UnityEngine.DisallowMultipleComponent]
public class AkRoomAwareObject : UnityEngine.MonoBehaviour
{
private static readonly System.Collections.Generic.Dictionary<UnityEngine.Collider, AkRoomAwareObject> ColliderToRoomAwareObjectMap = new System.Collections.Generic.Dictionary<UnityEngine.Collider, AkRoomAwareObject>();
public static AkRoomAwareObject GetAkRoomAwareObjectFromCollider(UnityEngine.Collider collider)
{
AkRoomAwareObject roomAwareObject = null;
return ColliderToRoomAwareObjectMap.TryGetValue(collider, out roomAwareObject) ? roomAwareObject : null;
}
public UnityEngine.Collider m_Collider;
private readonly AkRoom.PriorityList roomPriorityList = new AkRoom.PriorityList();
private void Awake()
{
m_Collider = GetComponent<UnityEngine.Collider>();
if (m_Collider != null)
{
ColliderToRoomAwareObjectMap.Add(m_Collider, this);
}
}
private void OnEnable()
{
AkRoomAwareManager.RegisterRoomAwareObject(this);
for (int i = 0; i < roomPriorityList.Count; ++i)
{
roomPriorityList[i].TryEnter(this);
}
}
private void OnDisable()
{
for (int i = 0; i < roomPriorityList.Count; ++i)
{
roomPriorityList[i].Exit(this);
}
roomPriorityList.Clear();
AkRoomAwareManager.UnregisterRoomAwareObject(this);
}
private void OnDestroy()
{
if (m_Collider)
{
ColliderToRoomAwareObjectMap.Remove(m_Collider);
}
}
public void SetGameObjectInHighestPriorityActiveAndEnabledRoom()
{
SetGameObjectInRoom(roomPriorityList.GetHighestPriorityActiveAndEnabledRoom());
}
private void SetGameObjectInRoom(AkRoom room)
{
AkUnitySoundEngine.SetGameObjectInRoom(gameObject, AkRoom.GetAkRoomID(room));
}
/// <summary>
/// Called when entering a room.
/// </summary>
/// <param name="room">The room.</param>
public void EnteredRoom(AkRoom room)
{
roomPriorityList.Add(room);
}
/// <summary>
/// Called when exiting a room.
/// </summary>
/// <param name="room">The room.</param>
public void ExitedRoom(AkRoom room)
{
roomPriorityList.Remove(room);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ac293711562f7704c9688ef699a612f3
@@ -0,0 +1,145 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
/// @brief This manager tracks AkRoomPortals and the rooms that they connect (front and back room).
/// @details At the end of the frame, the AkRoomPortals which rooms might have changed are updated and sent to Spatial Audio.
public class AkRoomManager
{
private readonly System.Collections.Generic.List<AkRoomPortal> m_Portals =
new System.Collections.Generic.List<AkRoomPortal>();
private readonly System.Collections.Generic.List<AkRoomPortal> m_PortalsToUpdate =
new System.Collections.Generic.List<AkRoomPortal>();
private readonly System.Collections.Generic.List<AkSurfaceReflector> m_Reflectors =
new System.Collections.Generic.List<AkSurfaceReflector>();
private readonly System.Collections.Generic.List<AkSurfaceReflector> m_ReflectorsToUpdate =
new System.Collections.Generic.List<AkSurfaceReflector>();
private static AkRoomManager m_Instance;
public static void Init()
{
if (m_Instance == null)
{
m_Instance = new AkRoomManager();
}
}
public static void Terminate()
{
if (m_Instance != null)
{
m_Instance = null;
}
}
public static void RegisterPortal(AkRoomPortal portal)
{
if (m_Instance != null)
{
if (!m_Instance.m_Portals.Contains(portal))
{
m_Instance.m_Portals.Add(portal);
}
if (!m_Instance.m_PortalsToUpdate.Contains(portal))
{
m_Instance.m_PortalsToUpdate.Add(portal);
}
}
}
public static void UnregisterPortal(AkRoomPortal portal)
{
if (m_Instance != null)
{
m_Instance.m_Portals.Remove(portal);
m_Instance.m_PortalsToUpdate.Remove(portal);
}
}
public static void RegisterReflector(AkSurfaceReflector reflector)
{
if (m_Instance != null)
{
if (!m_Instance.m_Reflectors.Contains(reflector))
{
m_Instance.m_Reflectors.Add(reflector);
}
if (!m_Instance.m_ReflectorsToUpdate.Contains(reflector))
{
m_Instance.m_ReflectorsToUpdate.Add(reflector);
}
}
}
public static void UnregisterReflector(AkSurfaceReflector reflector)
{
if (m_Instance != null)
{
m_Instance.m_Reflectors.Remove(reflector);
m_Instance.m_ReflectorsToUpdate.Remove(reflector);
}
}
public static void RegisterPortalUpdate(AkRoomPortal portal)
{
if (m_Instance != null)
{
if (m_Instance.m_Portals.Contains(portal) && !m_Instance.m_PortalsToUpdate.Contains(portal))
{
m_Instance.m_PortalsToUpdate.Add(portal);
}
}
}
public static void RegisterRoomUpdate(AkRoom room)
{
if (m_Instance != null)
{
for (var i = 0; i < m_Instance.m_Portals.Count; ++i)
{
var portal = m_Instance.m_Portals[i];
if (!m_Instance.m_PortalsToUpdate.Contains(portal) &&
(room == portal.frontRoom || room == portal.backRoom || portal.Overlaps(room)))
{
m_Instance.m_PortalsToUpdate.Add(portal);
}
}
}
}
public static void Update()
{
if (m_Instance != null)
{
for (var i = 0; i < m_Instance.m_PortalsToUpdate.Count; ++i)
{
m_Instance.m_PortalsToUpdate[i].UpdateRoomPortal();
}
m_Instance.m_PortalsToUpdate.Clear();
for (var i = 0; i < m_Instance.m_ReflectorsToUpdate.Count; ++i)
{
m_Instance.m_ReflectorsToUpdate[i].UpdateGeometry();
}
m_Instance.m_ReflectorsToUpdate.Clear();
}
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9659b0caec97e11499b90f3514f23a0f
@@ -0,0 +1,449 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkRoomPortal")]
[UnityEngine.RequireComponent(typeof(UnityEngine.BoxCollider))]
[UnityEngine.DisallowMultipleComponent]
/// @brief An AkRoomPortal can connect two AkRoom components together.
/// @details
public class AkRoomPortal : AkTriggerHandler
{
/// AkRoomPortals can only connect a maximum of 2 rooms.
public const int MAX_ROOMS_PER_PORTAL = 2;
public enum State
{
Closed,
Open
}
public State initialState = State.Closed;
private bool active = true;
public bool portalActive
{
get
{
return active;
}
set
{
active = value;
portalNeedsUpdate = true;
AkRoomManager.RegisterPortalUpdate(this);
}
}
public System.Collections.Generic.List<int> closePortalTriggerList = new System.Collections.Generic.List<int>();
private ulong frontRoomID { get { return IsRoomActive(frontRoom) ? frontRoom.GetID() : AkRoom.INVALID_ROOM_ID; } }
private ulong backRoomID { get { return IsRoomActive(backRoom) ? backRoom.GetID() : AkRoom.INVALID_ROOM_ID; } }
/// The front and back rooms connected by the portal.
/// The first room is on the negative side of the portal(opposite to the direction of the local Z axis)
/// The second room is on the positive side of the portal.
[UnityEngine.SerializeField]
private AkRoom[] rooms = new AkRoom[MAX_ROOMS_PER_PORTAL];
[UnityEngine.Tooltip("Set to true to set this portal as static: a portal that will not move during gameplay. A non-static portal will check the state of its transform each frame and update the portal in Wwise if there is a change.")]
/// Set to true to set this portal as static: a portal that will not move during gameplay. A non-static portal will check the state of its transform each frame and update the portal in Wwise if there is a change.
public bool isStatic = false;
/// The list of rooms sorted by priority in front and in the back of the portal
private AkRoom.PriorityList[] roomList = { new AkRoom.PriorityList(), new AkRoom.PriorityList() };
public AkRoom GetRoom(int index) { return rooms[index]; }
public AkRoom frontRoom { get { return rooms[1]; } }
public AkRoom backRoom { get { return rooms[0]; } }
public bool isSetInWwise() { return portalSet; }
private AkTransform portalTransform;
private UnityEngine.BoxCollider portalCollider;
private bool portalSet = false;
private bool portalNeedsUpdate = false;
private ulong[] previousRoomIDs = new ulong[MAX_ROOMS_PER_PORTAL];
private void SetRoomPortal()
{
if (!AkUnitySoundEngine.IsInitialized())
{
return;
}
if (!isActiveAndEnabled)
{
return;
}
if (IsValid)
{
portalTransform.Set(portalCollider.bounds.center, transform.forward, transform.up);
var extentVector = UnityEngine.Vector3.Scale(portalCollider.size, transform.lossyScale) / 2;
// in case extent is negative, get the absolute value
AkExtent extent = new AkExtent(
UnityEngine.Mathf.Abs(extentVector.x),
UnityEngine.Mathf.Abs(extentVector.y),
UnityEngine.Mathf.Abs(extentVector.z));
AkUnitySoundEngine.SetRoomPortal(GetID(), frontRoomID, backRoomID, portalTransform, extent, active, name);
portalSet = true;
portalNeedsUpdate = false;
}
else
{
WwiseLogger.Warning(name + " Portal placement is invalid. The portal is not set in the Spatial Audio engine. The front and back Rooms of the Portal cannot be the same or have a ReverbZone-parent relationship.");
if (portalSet)
{
AkUnitySoundEngine.RemovePortal(GetID());
portalSet = false;
}
}
}
public void UpdateRoomPortal()
{
bool roomsChanged = UpdateRooms();
if (roomsChanged || !portalSet || portalNeedsUpdate)
{
SetRoomPortal();
}
}
public bool Overlaps(AkRoom room)
{
FindOverlappingRooms(roomList);
for (int i = 0; i < MAX_ROOMS_PER_PORTAL; ++i)
{
if (roomList[i].Contains(room))
{
return true;
}
}
return false;
}
public bool IsValid
{
get
{
// portal is valid if its front and back rooms are different
bool isPortalValid = frontRoomID != backRoomID;
// portal is valid if its front and back room don't have a ReverbZone-parent relationship
if (isPortalValid && frontRoom && frontRoom.IsAReverbZoneInWwise)
{
isPortalValid = backRoomID != frontRoom.ParentRoomID;
}
if (isPortalValid && backRoom && backRoom.IsAReverbZoneInWwise)
{
isPortalValid = frontRoomID != backRoom.ParentRoomID;
}
#if UNITY_EDITOR
// check all reverb zone components
if (isPortalValid)
{
AkReverbZone[] reverbZoneComponents = UnityEngine.Resources.FindObjectsOfTypeAll<AkReverbZone>();
for (uint i = 0; i < reverbZoneComponents.Length; ++i)
{
if (reverbZoneComponents[i].isActiveAndEnabled && reverbZoneComponents[i].ReverbZone)
{
ulong reverbZoneID = reverbZoneComponents[i].ReverbZone.GetID();
ulong parentRoomID = AkRoom.INVALID_ROOM_ID;
if (reverbZoneComponents[i].ParentRoom != null)
{
parentRoomID = reverbZoneComponents[i].ParentRoom.GetID();
}
isPortalValid = !(frontRoomID == reverbZoneID && backRoomID == parentRoomID);
isPortalValid = isPortalValid && !(backRoomID == reverbZoneID && frontRoomID == parentRoomID);
}
}
}
#endif
return isPortalValid;
}
}
/// Access the portal's ID
public ulong GetID() { return (ulong)GetInstanceID(); }
protected override void Awake()
{
portalCollider = GetComponent<UnityEngine.BoxCollider>();
portalCollider.isTrigger = true;
portalTransform = new AkTransform();
// set portal in it's initial state
portalActive = initialState != State.Closed;
RegisterTriggers(closePortalTriggerList, ClosePortal);
// init update condition
transform.hasChanged = false;
// init previous room IDs
for (var i = 0; i < MAX_ROOMS_PER_PORTAL; ++i)
{
previousRoomIDs[i] = AkRoom.INVALID_ROOM_ID;
}
base.Awake();
}
protected override void Start()
{
base.Start();
//Call the ClosePortal function if registered to the Start Trigger
if (closePortalTriggerList.Contains(START_TRIGGER_ID))
{
ClosePortal(null);
}
}
/// Opens the portal on trigger event
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
Open();
}
/// Closes the portal on trigger event
public void ClosePortal(UnityEngine.GameObject in_gameObject)
{
Close();
}
protected override void OnDestroy()
{
base.OnDestroy();
UnregisterTriggers(closePortalTriggerList, ClosePortal);
}
public override void OnEnable()
{
AkRoomManager.RegisterPortal(this);
base.OnEnable();
}
private void OnDisable()
{
AkRoomManager.UnregisterPortal(this);
if (portalSet)
{
AkUnitySoundEngine.RemovePortal(GetID());
}
portalSet = false;
}
private void Update()
{
// don't update if is static
if (isStatic) return;
if (transform.hasChanged)
{
portalNeedsUpdate = true;
AkRoomManager.RegisterPortalUpdate(this);
transform.hasChanged = false;
}
}
private bool IsRoomActive(AkRoom in_room)
{
return in_room != null && in_room.isActiveAndEnabled;
}
public void Open()
{
portalActive = true;
}
public void Close()
{
portalActive = false;
}
public void FindOverlappingRooms(AkRoom.PriorityList[] roomList)
{
var portalCollider = gameObject.GetComponent<UnityEngine.BoxCollider>();
if (portalCollider == null)
{
return;
}
// compute halfExtents and divide the local z extent by 2
var halfExtentZ = portalCollider.size.z / 2;
// move the center backward
FillRoomList(UnityEngine.Vector3.forward * -halfExtentZ, roomList[0]);
// move the center forward
FillRoomList(UnityEngine.Vector3.forward * halfExtentZ, roomList[1]);
}
private void FillRoomList(UnityEngine.Vector3 position, AkRoom.PriorityList list)
{
list.Clear();
position = transform.TransformPoint(position);
var colliders = UnityEngine.Physics.OverlapSphere(position, 0, -1, UnityEngine.QueryTriggerInteraction.Collide);
foreach (var collider in colliders)
{
var room = collider.gameObject.GetComponent<AkRoom>();
if (room != null && !list.Contains(room))
{
list.Add(room);
}
}
}
public bool UpdateRooms()
{
FindOverlappingRooms(roomList);
bool wasUpdated = false;
for (var i = 0; i < MAX_ROOMS_PER_PORTAL; ++i)
{
var room = roomList[i].GetHighestPriorityActiveAndEnabledRoom();
var roomID = room != null ? room.GetID() : AkRoom.INVALID_ROOM_ID;
if (roomID != previousRoomIDs[i])
{
wasUpdated = true;
}
rooms[i] = room;
previousRoomIDs[i] = roomID;
}
return wasUpdated;
}
#if UNITY_EDITOR
private void OnDrawGizmos()
{
if (!enabled)
{
return;
}
UnityEngine.Gizmos.matrix = transform.localToWorldMatrix;
var centreOffset = UnityEngine.Vector3.zero;
var sizeMultiplier = UnityEngine.Vector3.one;
var collider = GetComponent<UnityEngine.BoxCollider>();
if (collider)
{
centreOffset = collider.center;
sizeMultiplier = collider.size;
}
// color faces
var faceCenterPos = new UnityEngine.Vector3[6];
faceCenterPos[0] = UnityEngine.Vector3.Scale(new UnityEngine.Vector3(0.5f, 0.0f, 0.0f), sizeMultiplier);
faceCenterPos[1] = UnityEngine.Vector3.Scale(new UnityEngine.Vector3(0.0f, 0.5f, 0.0f), sizeMultiplier);
faceCenterPos[2] = UnityEngine.Vector3.Scale(new UnityEngine.Vector3(-0.5f, 0.0f, 0.0f), sizeMultiplier);
faceCenterPos[3] = UnityEngine.Vector3.Scale(new UnityEngine.Vector3(0.0f, -0.5f, 0.0f), sizeMultiplier);
faceCenterPos[4] = UnityEngine.Vector3.Scale(new UnityEngine.Vector3(0.0f, 0.0f, 0.5f), sizeMultiplier);
faceCenterPos[5] = UnityEngine.Vector3.Scale(new UnityEngine.Vector3(0.0f, 0.0f, -0.5f), sizeMultiplier);
var faceSize = new UnityEngine.Vector3[6];
faceSize[0] = new UnityEngine.Vector3(0, 1, 1);
faceSize[1] = new UnityEngine.Vector3(1, 0, 1);
faceSize[2] = faceSize[0];
faceSize[3] = faceSize[1];
faceSize[4] = new UnityEngine.Vector3(1, 1, 0);
faceSize[5] = faceSize[4];
if (IsValid)
{
UnityEngine.Gizmos.color = new UnityEngine.Color32(255, 204, 0, 100);
}
else
{
UnityEngine.Gizmos.color = new UnityEngine.Color32(255, 0, 0, 100);
}
for (var i = 0; i < 4; i++)
{
UnityEngine.Gizmos.DrawCube(faceCenterPos[i] + centreOffset, UnityEngine.Vector3.Scale(faceSize[i], sizeMultiplier));
}
if (!portalActive)
{
UnityEngine.Gizmos.DrawCube(faceCenterPos[4] + centreOffset, UnityEngine.Vector3.Scale(faceSize[4], sizeMultiplier));
UnityEngine.Gizmos.DrawCube(faceCenterPos[5] + centreOffset, UnityEngine.Vector3.Scale(faceSize[5], sizeMultiplier));
}
// draw line in the center of the portal
var CornerCenterPos = faceCenterPos;
CornerCenterPos[0].y += 0.5f * sizeMultiplier.y;
CornerCenterPos[1].x -= 0.5f * sizeMultiplier.x;
CornerCenterPos[2].y -= 0.5f * sizeMultiplier.y;
CornerCenterPos[3].x += 0.5f * sizeMultiplier.x;
UnityEngine.Gizmos.color = UnityEngine.Color.green;
for (var i = 0; i < 4; i++)
{
UnityEngine.Gizmos.DrawLine(CornerCenterPos[i] + centreOffset, CornerCenterPos[(i + 1) % 4] + centreOffset);
}
}
#endif
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public void SetRoom(int in_roomIndex, AkRoom in_room)
{
WwiseLogger.LogFormat("SetRoom is deprecated. Highest priority, active and enabled room will be automatically chosen. Make sure room priorities and game object placements are correct.");
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public void SetFrontRoom(AkRoom room)
{
WwiseLogger.LogFormat("SetFrontRoom is deprecated. Highest priority, active and enabled room will be automatically chosen. Make sure room priorities and game object placements are correct.");
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public void SetBackRoom(AkRoom room)
{
WwiseLogger.LogFormat("SetBackRoom is deprecated. Highest priority, active and enabled room will be automatically chosen. Make sure room priorities and game object placements are correct.");
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public void UpdateSoundEngineRoomIDs()
{
UpdateRoomPortal();
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public void UpdateOverlappingRooms()
{
UpdateRooms();
}
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: d4230c3548361604fb2171a8afa3d75a
@@ -0,0 +1,47 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkRoomPortalObstruction")]
[UnityEngine.RequireComponent(typeof(AkRoomPortal))]
/// @brief Completely obstructs the spatial audio portal of the current game object from the spatial audio listener if at least one object is between them.
/// @details If no spatial audio listener has been registered, there will be no obstruction.
public class AkRoomPortalObstruction : AkObstructionOcclusion
{
private AkRoomPortal m_portal;
private void Awake()
{
InitIntervalsAndFadeRates();
m_portal = GetComponent<AkRoomPortal>();
}
protected override void UpdateCurrentListenerList()
{
currentListenerList.Add(AkSpatialAudioListener.TheSpatialAudioListener);
}
protected override void SetObstructionOcclusion(
System.Collections.Generic.KeyValuePair<AkAudioListener, ObstructionOcclusionValue> ObsOccPair)
{
if (m_portal.IsValid && m_portal.isSetInWwise())
{
AkUnitySoundEngine.SetPortalObstructionAndOcclusion(m_portal.GetID(), ObsOccPair.Value.currentValue, 0.0f);
}
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: def02084d9782ac4fa129ad43ed8e277
@@ -0,0 +1,393 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
using AK.Wwise.Unity.WwiseAddressables;
#endif
public class AkSoundEngineController
{
private static AkSoundEngineController ms_Instance;
public static AkSoundEngineController Instance
{
get
{
if (ms_Instance == null)
{
ms_Instance = new AkSoundEngineController();
}
return ms_Instance;
}
}
private AkSoundEngineController()
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.pauseStateChanged += OnPauseStateChanged;
UnityEditor.EditorApplication.playModeStateChanged += OnPlayModeStateChanged;
AkUnitySoundEngineInitialization.Instance.terminationDelegate += OnDisableEditorListener;
AkUnitySoundEngineInitialization.Instance.initializationDelegate += OnEnableEditorListener;
#endif
}
~AkSoundEngineController()
{
if (ms_Instance == this)
{
#if UNITY_EDITOR
UnityEditor.EditorApplication.pauseStateChanged -= OnPauseStateChanged;
UnityEditor.EditorApplication.playModeStateChanged -= OnPlayModeStateChanged;
AkUnitySoundEngineInitialization.Instance.terminationDelegate -= OnDisableEditorListener;
AkUnitySoundEngineInitialization.Instance.initializationDelegate -= OnEnableEditorListener;
DisableEditorLateUpdate();
#endif
ms_Instance = null;
}
}
#if UNITY_EDITOR
public void EnableEditorLateUpdate()
{
UnityEditor.EditorApplication.update += LateUpdate;
}
public void DisableEditorLateUpdate()
{
UnityEditor.EditorApplication.update -= LateUpdate;
}
#endif
public void LateUpdate()
{
//Execute callbacks that occurred in last frame (not the current update)
AkRoomManager.Update();
AkRoomAwareManager.UpdateRoomAwareObjects();
AkCallbackManager.PostCallbacks();
#if !(AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES)
AkBankManager.DoUnloadBanks();
#elif WWISE_ADDRESSABLES_24_1_OR_LATER
if (AkAddressableBankManager.Instance != null) ;
{
AkAddressableBankManager.Instance.DoUnloadBank();
}
#endif
#if UNITY_WEBGL && !UNITY_EDITOR
AkUnitySoundEngine.PerformStreamMgrIO();
#endif
AkUnitySoundEngine.RenderAudio();
}
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
private AkWwiseAddressablesInitializationSettings GetInitSettingsInstance()
{
return AkWwiseAddressablesInitializationSettings.Instance;
}
#else
private AkWwiseInitializationSettings GetInitSettingsInstance()
{
return AkWwiseInitializationSettings.Instance;
}
#endif
public void Init(AkInitializer akInitializer)
{
AkUnitySoundEngine.SetErrorLogger(AkLogger.WwiseInternalLogError);
#if UNITY_EDITOR
var arguments = System.Environment.GetCommandLineArgs();
if (UnityEngine.Application.isBatchMode && System.Array.IndexOf(arguments, "-wwiseEnableWithNoGraphics") < 0)
{
WwiseLogger.Log("Sound engine will not be initialized in batch/nographics mode. To override, specify -wwiseEnableWithNoGraphics");
return;
}
#endif
// Only initialize the room manager during play.
bool initRoomManager = true;
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying)
{
initRoomManager = false;
}
#endif
if (initRoomManager)
{
AkRoomManager.Init();
}
if (akInitializer == null)
{
WwiseLogger.Error("AkInitializer must not be null. Sound engine will not be initialized.");
return;
}
var isInitialized = AkUnitySoundEngine.IsInitialized();
if (isInitialized)
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying)
{
OnEnableEditorListener(akInitializer.gameObject);
}
if (AkUnitySoundEngineInitialization.Instance.ResetSoundEngine(UnityEngine.Application.isPlaying || UnityEditor.BuildPipeline.isBuildingPlayer))
{
EnableEditorLateUpdate();
}
if (UnityEditor.EditorApplication.isPaused && UnityEngine.Application.isPlaying)
{
AkUnitySoundEngine.Suspend(true);
}
#else
WwiseLogger.Error("Sound engine is already initialized.");
#endif
return;
}
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer)
{
return;
}
#endif
if (!AkUnitySoundEngineInitialization.Instance.InitializeSoundEngine())
{
return;
}
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying)
{
OnEnableEditorListener(akInitializer.gameObject);
}
EnableEditorLateUpdate();
#endif
}
public void OnDisable()
{
#if UNITY_EDITOR
if(UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode)
{
OnDisableEditorListener();
}
if(!AkUnitySoundEngineInitialization.Instance.ShouldKeepSoundEngineEnabled())
{
Terminate();
}
#endif
}
public void Terminate()
{
AkUnitySoundEngine.SetErrorLogger();
AkUnitySoundEngineInitialization.Instance.TerminateSoundEngine();
AkRoomManager.Terminate();
}
// In the Editor, the sound needs to keep playing when switching windows (remote debugging in Wwise, for example).
// On iOS, application interruptions are handled in the sound engine already.
#if UNITY_EDITOR || UNITY_IOS
public void OnApplicationPause(bool pauseStatus)
{
}
public void OnApplicationFocus(bool focus)
{
#if UNITY_EDITOR
ActivateAudio(focus,AkWwiseInitializationSettings.Instance.RenderDuringFocusLoss);
#endif
}
#elif UNITY_WEBGL
// On WebGL, allow background audio when browser is un-focused in development builds to make the Wwise Profiler usable.
public void OnApplicationPause(bool pauseStatus)
{
if (!UnityEngine.Debug.isDebugBuild)
{
ActivateAudio(!pauseStatus);
}
}
public void OnApplicationFocus(bool focus)
{
if (!UnityEngine.Debug.isDebugBuild)
{
ActivateAudio(focus, AkWwiseInitializationSettings.Instance.RenderDuringFocusLoss);
}
}
#else
public void OnApplicationPause(bool pauseStatus)
{
ActivateAudio(!pauseStatus);
}
public void OnApplicationFocus(bool focus)
{
#if !UNITY_ANDROID
ActivateAudio(focus,AkWwiseInitializationSettings.Instance.RenderDuringFocusLoss);
#endif
}
#endif
#if UNITY_EDITOR
// Enable/Disable the audio when pressing play/pause in the editor.
private void OnPauseStateChanged(UnityEditor.PauseState pauseState)
{
if (UnityEngine.Application.isPlaying)
{
ActivateAudio(pauseState != UnityEditor.PauseState.Paused);
}
}
private void OnPlayModeStateChanged(UnityEditor.PlayModeStateChange state)
{
if(state.HasFlag(UnityEditor.PlayModeStateChange.ExitingEditMode) || state.HasFlag(UnityEditor.PlayModeStateChange.ExitingPlayMode))
{
AkUnitySoundEngine.StopAll();
}
}
#endif
#if UNITY_EDITOR || !UNITY_IOS
private void ActivateAudio(bool activate, bool renderAnyway = false)
{
if (AkUnitySoundEngine.IsInitialized() && AkWwiseInitializationSettings.Instance.SuspendAudioDuringFocusLoss)
{
if (activate)
{
AkUnitySoundEngine.WakeupFromSuspend();
}
else
{
AkUnitySoundEngine.Suspend(renderAnyway);
}
AkUnitySoundEngine.RenderAudio();
}
}
#endif
#if UNITY_EDITOR
#region Editor Listener
private UnityEngine.GameObject editorListenerGameObject;
private bool IsPlayingOrIsNotInitialized
{
get { return UnityEngine.Application.isPlaying || !AkUnitySoundEngine.IsInitialized(); }
}
public bool EditorListenerIsInitialized()
{
return editorListenerGameObject != null;
}
private void OnEnableEditorListener()
{
OnEnableEditorListener(AkInitializer.GetAkInitializerGameObject());
}
private void OnEnableEditorListener(UnityEngine.GameObject gameObject)
{
if (editorListenerGameObject != null || IsPlayingOrIsNotInitialized)
{
return;
}
if(gameObject == null)
{
return;
}
editorListenerGameObject = gameObject;
AkUnitySoundEngine.RegisterGameObj(editorListenerGameObject, editorListenerGameObject.name);
// Do not create AkGameObj component when adding this listener
var id = AkUnitySoundEngine.GetAkGameObjectID(editorListenerGameObject);
AkUnitySoundEngine.AddDefaultListener(id);
UnityEditor.EditorApplication.update += UpdateEditorListenerPosition;
}
private void OnDisableEditorListener()
{
if (IsPlayingOrIsNotInitialized || editorListenerGameObject == null)
{
return;
}
UnityEditor.EditorApplication.update -= UpdateEditorListenerPosition;
var id = AkUnitySoundEngine.GetAkGameObjectID(editorListenerGameObject);
AkUnitySoundEngine.RemoveDefaultListener(id);
AkUnitySoundEngine.UnregisterGameObj(editorListenerGameObject);
editorListenerGameObject = null;
editorListenerForward = UnityEngine.Vector3.zero;
editorListenerPosition = UnityEngine.Vector3.zero;
editorListenerUp = UnityEngine.Vector3.zero;
}
private UnityEngine.Vector3 editorListenerPosition = UnityEngine.Vector3.zero;
private UnityEngine.Vector3 editorListenerForward = UnityEngine.Vector3.zero;
private UnityEngine.Vector3 editorListenerUp = UnityEngine.Vector3.zero;
private void UpdateEditorListenerPosition()
{
if (IsPlayingOrIsNotInitialized || editorListenerGameObject == null)
{
return;
}
if (UnityEditor.SceneView.lastActiveSceneView == null)
{
return;
}
var sceneViewCamera = UnityEditor.SceneView.lastActiveSceneView.camera;
if (sceneViewCamera == null)
{
return;
}
var sceneViewTransform = sceneViewCamera.transform;
if (sceneViewTransform == null)
{
return;
}
if (editorListenerPosition == sceneViewTransform.position &&
editorListenerForward == sceneViewTransform.forward &&
editorListenerUp == sceneViewTransform.up)
{
return;
}
AkUnitySoundEngine.SetObjectPosition(editorListenerGameObject, sceneViewTransform);
editorListenerPosition = sceneViewTransform.position;
editorListenerForward = sceneViewTransform.forward;
editorListenerUp = sceneViewTransform.up;
}
#endregion
#endif // UNITY_EDITOR
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a5c90627b69e8084585c8b9b904ec76c
@@ -0,0 +1,207 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkSpatialAudioDebugDraw")]
[UnityEngine.RequireComponent(typeof(AkGameObj))]
///@brief Add this script on a GameObject to print Spatial Audio paths.
public class AkSpatialAudioDebugDraw : UnityEngine.MonoBehaviour
{
#if UNITY_EDITOR
/// This allows you to visualize first order reflection sound paths.
public bool drawFirstOrderReflections = false;
/// This allows you to visualize second order reflection sound paths.
public bool drawSecondOrderReflections = false;
/// This allows you to visualize third or higher order reflection sound paths.
public bool drawHigherOrderReflections = false;
/// This allows you to visualize geometric diffraction sound paths between an obstructed emitter and the listener.
public bool drawDiffractionPaths = false;
private void OnDrawGizmos()
{
if (!UnityEngine.Application.isPlaying || !AkUnitySoundEngine.IsInitialized())
{
return;
}
if (debugDrawData == null)
{
debugDrawData = new DebugDrawData();
}
if (drawFirstOrderReflections || drawSecondOrderReflections || drawHigherOrderReflections)
{
debugDrawData.DebugDrawEarlyReflections(gameObject, drawFirstOrderReflections, drawSecondOrderReflections, drawHigherOrderReflections);
}
if (drawDiffractionPaths)
{
debugDrawData.DebugDrawDiffraction(gameObject);
}
}
private class DebugDrawData
{
// Constants
private const uint kMaxIndirectPaths = 64;
private const uint kMaxDiffractionPaths = 16;
private readonly UnityEngine.Color32 colorLightYellow = new UnityEngine.Color32(255, 255, 121, 255);
private readonly UnityEngine.Color32 colorDarkYellow = new UnityEngine.Color32(164, 164, 0, 255);
private readonly UnityEngine.Color32 colorLightOrange = new UnityEngine.Color32(255, 202, 79, 255);
private readonly UnityEngine.Color32 colorDarkOrange = new UnityEngine.Color32(164, 115, 0, 255);
private readonly UnityEngine.Color32 colorLightRed = new UnityEngine.Color32(252, 177, 162, 255);
private readonly UnityEngine.Color32 colorDarkRed = new UnityEngine.Color32(169, 62, 39, 255);
private readonly UnityEngine.Color32 colorLightGrey = new UnityEngine.Color32(75, 75, 75, 255);
private readonly UnityEngine.Color32 colorGreen = new UnityEngine.Color32(38, 113, 88, 255);
private const float radiusSphere = 0.25f;
// Calculated path info
private readonly AkReflectionPathInfoArray indirectPathInfoArray = new AkReflectionPathInfoArray((int)kMaxIndirectPaths);
private readonly AkDiffractionPathInfoArray diffractionPathInfoArray = new AkDiffractionPathInfoArray((int)kMaxDiffractionPaths);
public void DebugDrawEarlyReflections(UnityEngine.GameObject gameObject, bool firstOrder, bool secondOrder, bool higherOrder)
{
var listenerPosition = UnityEngine.Vector3.zero;
var emitterPosition = UnityEngine.Vector3.zero;
uint numValidPaths = (uint)indirectPathInfoArray.Count();
if (AkUnitySoundEngine.QueryReflectionPaths(gameObject, 0, ref listenerPosition, ref emitterPosition, indirectPathInfoArray, out numValidPaths) != AKRESULT.AK_Success)
{
return;
}
for (var idxPath = (int)numValidPaths - 1; idxPath >= 0; --idxPath)
{
var path = indirectPathInfoArray[idxPath];
var order = path.numReflections;
var colorLight = colorLightRed;
var colorDark = colorDarkRed;
if (order == 1)
{
if (!firstOrder)
{
continue;
}
colorLight = colorLightYellow;
colorDark = colorDarkYellow;
}
else if (order == 2)
{
if (!secondOrder)
{
continue;
}
colorLight = colorLightOrange;
colorDark = colorDarkOrange;
}
else if (order > 2 && !higherOrder)
{
continue;
}
var listenerPt = listenerPosition;
for (var idxSeg = (int)path.numPathPoints - 1; idxSeg >= 0; --idxSeg)
{
var pt = path.GetPathPoint((uint)idxSeg);
UnityEngine.Debug.DrawLine(listenerPt, pt, path.isOccluded ? colorLightGrey : colorLight);
UnityEngine.Gizmos.color = path.isOccluded ? colorLightGrey : colorLight;
UnityEngine.Gizmos.DrawWireSphere(pt, radiusSphere / 2 / order);
float dfrnAmount = path.GetDiffraction((uint)idxSeg);
if (dfrnAmount > 0)
{
string dfrnAmountStr = dfrnAmount.ToString("0.#%");
DrawLabelInFrontOfCam(pt, dfrnAmountStr, 100000, colorDark);
}
listenerPt = pt;
}
if (!path.isOccluded)
{
// Finally the last path segment towards the emitter.
UnityEngine.Debug.DrawLine(listenerPt, emitterPosition, path.isOccluded ? colorLightGrey : colorLight);
}
}
}
public void DebugDrawDiffraction(UnityEngine.GameObject gameObject)
{
var listenerPosition = UnityEngine.Vector3.zero;
var emitterPosition = UnityEngine.Vector3.zero;
uint numValidPaths = (uint)diffractionPathInfoArray.Count();
if (AkUnitySoundEngine.QueryDiffractionPaths(gameObject, 0, ref listenerPosition, ref emitterPosition, diffractionPathInfoArray, out numValidPaths) != AKRESULT.AK_Success)
{
return;
}
for (var idxPath = (int)numValidPaths - 1; idxPath >= 0; --idxPath)
{
var path = diffractionPathInfoArray[idxPath];
if (path.nodeCount <= 0)
{
continue;
}
var prevPt = listenerPosition;
for (var idxSeg = 0; idxSeg < (int)path.nodeCount; ++idxSeg)
{
var pt = path.GetNodes((uint)idxSeg);
UnityEngine.Debug.DrawLine(prevPt, pt, colorGreen);
float angle = path.GetAngles((uint)idxSeg) / UnityEngine.Mathf.PI;
if (angle > 0)
{
string angleStr = angle.ToString("0.#%");
DrawLabelInFrontOfCam(pt, angleStr, 100000, colorGreen);
}
prevPt = pt;
}
UnityEngine.Debug.DrawLine(prevPt, emitterPosition, colorGreen);
}
}
}
private static DebugDrawData debugDrawData = null;
private static void DrawLabelInFrontOfCam(UnityEngine.Vector3 position, string name, float distance, UnityEngine.Color c)
{
var style = new UnityEngine.GUIStyle();
var oncam = UnityEngine.Camera.current.WorldToScreenPoint(position);
if (oncam.x >= 0 && oncam.x <= UnityEngine.Camera.current.pixelWidth && oncam.y >= 0 &&
oncam.y <= UnityEngine.Camera.current.pixelHeight && oncam.z > 0 && oncam.z < distance)
{
style.normal.textColor = c;
UnityEditor.Handles.Label(position, name, style);
}
}
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 93fdc3da7b569ef49b521ff47a257da7
@@ -0,0 +1,227 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
///@brief (DEPRECATED) This script is deprecated as of 2019.2. Early reflections, Diffraction and Room Reverb can all be enabled per sound in the Sound Property Editor of the Authoring.
/// @details Some functionalities were moved to different components. See the AkEarlyReflections and AkSpatialAudioDebugDraw components for more details.
public class AkSpatialAudioEmitter : UnityEngine.MonoBehaviour
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
[UnityEngine.Header("Early Reflections")]
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, the early reflections auxiliary bus can be set per sound, in the Authoring tool, or per game object, with the AkEarlyReflections component.")]
/// (DEPRECATED) As of 2019.2, the early reflections auxiliary bus can be set per sound, in the Authoring tool, or per game object, with the AkEarlyReflections component.
public AK.Wwise.AuxBus reflectAuxBus = new AK.Wwise.AuxBus();
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, the Reflection Max Path Length is set by the sound's Attenuation Max Distance value in the Authoring tool.")]
/// (DEPRECATED) As of 2019.2, the Reflection Max Path Length is set by the sound's Attenuation Max Distance value in the Authoring tool.
public float reflectionMaxPathLength = 1000;
[UnityEngine.Range(0, 1)]
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, the early reflections send volume can be set per sound, in the Authoring tool, or for all sunds playing on a game object, with the AkEarlyReflections component.")]
/// (DEPRECATED) As of 2019.2, the early reflections send volume can be set per sound, in the Authoring tool, or for all sunds playing on a game object, with the AkEarlyReflections component.
public float reflectionsAuxBusGain = 1;
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, the Reflection Order is set in the Spatial Audio Initialization Settings.")]
/// (DEPRECATED) As of 2019.2, the Reflection Order is set in the Spatial Audio Initialization Settings.
public uint reflectionsOrder = 1;
[UnityEngine.Header("Rooms")]
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, the Room Reverb Aux Bus Gain is set by the Game-Defined Auxiliary Sends Volume in the Sound Property Editor in the Authoring tool.")]
/// (DEPRECATED) As of 2019.2, the Room Reverb Aux Bus Gain is set by the Game-Defined Auxiliary Sends Volume in the Sound Property Editor in the Authoring tool.
public float roomReverbAuxBusGain = 1;
[UnityEngine.Header("Geometric Diffraction")]
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool.")]
/// (DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool.
public uint diffractionMaxEdges = 0;
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool.")]
/// (DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool.
public uint diffractionMaxPaths = 0;
[UnityEngine.Tooltip("(DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool.")]
/// (DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool.
public uint diffractionMaxPathLength = 0;
#if UNITY_EDITOR
[UnityEngine.Header("Debug Draw")]
[UnityEngine.Tooltip("(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.")]
/// (DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.
public bool drawFirstOrderReflections = false;
[UnityEngine.Tooltip("(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.")]
/// (DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.
public bool drawSecondOrderReflections = false;
[UnityEngine.Tooltip("(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.")]
/// (DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.
public bool drawHigherOrderReflections = false;
[UnityEngine.Tooltip("(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.")]
/// (DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component.
public bool drawDiffractionPaths = false;
[UnityEditor.CustomEditor(typeof(AkSpatialAudioEmitter))]
[UnityEditor.CanEditMultipleObjects]
private class Editor : UnityEditor.Editor
{
private UnityEditor.SerializedProperty reflectAuxBus;
private UnityEditor.SerializedProperty reflectionMaxPathLength;
private UnityEditor.SerializedProperty reflectionsAuxBusGain;
private UnityEditor.SerializedProperty reflectionsOrder;
private UnityEditor.SerializedProperty roomReverbAuxBusGain;
private UnityEditor.SerializedProperty diffractionMaxEdges;
private UnityEditor.SerializedProperty diffractionMaxPaths;
private UnityEditor.SerializedProperty diffractionMaxPathLength;
private UnityEditor.SerializedProperty drawFirstOrderReflections;
private UnityEditor.SerializedProperty drawSecondOrderReflections;
private UnityEditor.SerializedProperty drawHigherOrderReflections;
private UnityEditor.SerializedProperty drawDiffractionPaths;
public void OnEnable()
{
reflectAuxBus = serializedObject.FindProperty("reflectAuxBus");
reflectionMaxPathLength = serializedObject.FindProperty("reflectionMaxPathLength");
reflectionsAuxBusGain = serializedObject.FindProperty("reflectionsAuxBusGain");
reflectionsOrder = serializedObject.FindProperty("reflectionsOrder");
roomReverbAuxBusGain = serializedObject.FindProperty("roomReverbAuxBusGain");
diffractionMaxEdges = serializedObject.FindProperty("diffractionMaxEdges");
diffractionMaxPaths = serializedObject.FindProperty("diffractionMaxPaths");
diffractionMaxPathLength = serializedObject.FindProperty("diffractionMaxPathLength");
drawFirstOrderReflections = serializedObject.FindProperty("drawFirstOrderReflections");
drawSecondOrderReflections = serializedObject.FindProperty("drawSecondOrderReflections");
drawHigherOrderReflections = serializedObject.FindProperty("drawHigherOrderReflections");
drawDiffractionPaths = serializedObject.FindProperty("drawDiffractionPaths");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
var wasEnabled = UnityEngine.GUI.enabled;
UnityEngine.GUI.enabled = false;
UnityEditor.EditorGUILayout.PropertyField(reflectAuxBus, new UnityEngine.GUIContent("Reflect Aux Bus", "(DEPRECATED) As of 2019.2, the early reflections auxiliary bus can be set per sound, in the Authoring tool, or per game object, with the AkEarlyReflections component."));
UnityEditor.EditorGUILayout.PropertyField(reflectionMaxPathLength, new UnityEngine.GUIContent("Reflection Max Path Length", "(DEPRECATED) As of 2019.2, the Reflection Max Path Length is set by the sound's Attenuation Max Distance value in the Authoring tool."));
UnityEditor.EditorGUILayout.PropertyField(reflectionsAuxBusGain, new UnityEngine.GUIContent("Reflections Aux Bus Gain", "(DEPRECATED) As of 2019.2, the early reflections send volume can be set per sound, in the Authoring tool, or for all sunds playing on a game object, with the AkEarlyReflections component."));
UnityEditor.EditorGUILayout.PropertyField(reflectionsOrder, new UnityEngine.GUIContent("Reflections Order", "(DEPRECATED) As of 2019.2, the Reflection Order is set in the Spatial Audio Initialization Settings."));
UnityEditor.EditorGUILayout.PropertyField(roomReverbAuxBusGain, new UnityEngine.GUIContent("Room Reverb Aux Bus Gain", "(DEPRECATED) As of 2019.2, the Room Reverb Aux Bus Gain is set by the Game-Defined Auxiliary Sends Volume in the Sound Property Editor in the Authoring tool."));
UnityEditor.EditorGUILayout.PropertyField(diffractionMaxEdges, new UnityEngine.GUIContent("Diffraction Max Edges", "(DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool."));
UnityEditor.EditorGUILayout.PropertyField(diffractionMaxPaths, new UnityEngine.GUIContent("Diffraction Max Paths", "(DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool."));
UnityEditor.EditorGUILayout.PropertyField(diffractionMaxPathLength, new UnityEngine.GUIContent("Diffraction Max Path Length", "(DEPRECATED) As of 2019.2, diffraction is enabled in the Sound Property Editor in the Authoring tool."));
UnityEditor.EditorGUILayout.PropertyField(drawFirstOrderReflections, new UnityEngine.GUIContent("Draw First Order Reflections", "(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component."));
UnityEditor.EditorGUILayout.PropertyField(drawSecondOrderReflections, new UnityEngine.GUIContent("Draw Second Order Reflections", "(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component."));
UnityEditor.EditorGUILayout.PropertyField(drawHigherOrderReflections, new UnityEngine.GUIContent("Draw Higher Order Reflections", "(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component."));
UnityEditor.EditorGUILayout.PropertyField(drawDiffractionPaths, new UnityEngine.GUIContent("Draw Diffraction Paths", "(DEPRECATED) Spatial Audio Debug Drawing were moved to the new AkSpatialAudioDebugDraw component."));
UnityEngine.GUI.enabled = wasEnabled;
// button to add AkEarlyReflections
bool bShowButton = false;
foreach (var obj in targets)
{
AkSpatialAudioEmitter spatialAudioEmitter = obj as AkSpatialAudioEmitter;
if (spatialAudioEmitter.gameObject.GetComponent<AkEarlyReflections>() == null)
bShowButton = true;
}
if (bShowButton)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"If you want to keep setting Early Reflections per game object, consider adding an AkEarlyReflections component.",
UnityEditor.MessageType.Warning);
if (UnityEngine.GUILayout.Button("Add AkEarlyReflections"))
{
foreach (var obj in targets)
{
AkSpatialAudioEmitter spatialAudioEmitter = obj as AkSpatialAudioEmitter;
if (spatialAudioEmitter.gameObject.GetComponent<AkEarlyReflections>() == null)
{
var er = UnityEditor.Undo.AddComponent<AkEarlyReflections>(spatialAudioEmitter.gameObject);
er.reflectionsAuxBus.ObjectReference = spatialAudioEmitter.reflectAuxBus.ObjectReference;
er.reflectionsVolume = spatialAudioEmitter.reflectionsAuxBusGain;
}
}
}
}
}
// button to add AkSpatialAudioDebugDraw
bShowButton = false;
foreach (var obj in targets)
{
AkSpatialAudioEmitter spatialAudioEmitter = obj as AkSpatialAudioEmitter;
if (spatialAudioEmitter.gameObject.GetComponent<AkSpatialAudioDebugDraw>() == null)
bShowButton = true;
}
if (bShowButton)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"For debugging purposes, early reflection and diffraction paths can be shown in the scene with the AkSpatialAudioDebugDraw component.",
UnityEditor.MessageType.Warning);
if (UnityEngine.GUILayout.Button("Add AkSpatialAudioDebugDraw"))
{
foreach (var obj in targets)
{
AkSpatialAudioEmitter spatialAudioEmitter = obj as AkSpatialAudioEmitter;
if (spatialAudioEmitter.gameObject.GetComponent<AkSpatialAudioDebugDraw>() == null)
{
var dd = UnityEditor.Undo.AddComponent<AkSpatialAudioDebugDraw>(spatialAudioEmitter.gameObject);
dd.drawFirstOrderReflections = spatialAudioEmitter.drawFirstOrderReflections;
dd.drawSecondOrderReflections = spatialAudioEmitter.drawSecondOrderReflections;
dd.drawHigherOrderReflections = spatialAudioEmitter.drawHigherOrderReflections;
dd.drawDiffractionPaths = spatialAudioEmitter.drawDiffractionPaths;
}
}
}
}
}
serializedObject.ApplyModifiedProperties();
}
}
#region WwiseMigration
bool AK.Wwise.IMigratable.Migrate(UnityEditor.SerializedObject obj)
{
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.NewScriptableObjectFolder_v2019_2_0))
return false;
UnityEditor.Undo.AddComponent<AkRoomAwareObject>(gameObject);
return true;
}
#endregion
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0b248f5d6b55fa74f93640507b5d58f5
@@ -0,0 +1,158 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkSpatialAudioListener")]
[UnityEngine.RequireComponent(typeof(AkAudioListener))]
[UnityEngine.RequireComponent(typeof(AkRoomAwareObject))]
[UnityEngine.DisallowMultipleComponent]
///@brief Add this script on the game object that represent a listener. This is normally added to the Camera object or the Player object, but can be added to any game object when implementing 3D busses. \c isDefaultListener determines whether the game object will be considered a default listener - a listener that automatically listens to all game objects that do not have listeners attached to their AkGameObjListenerList's.
/// \sa
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__listeners.html" target="_blank">Integrating Listeners</a> (Note: This is described in the Wwise SDK documentation.)
public class AkSpatialAudioListener : UnityEngine.MonoBehaviour
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
private static AkSpatialAudioListener s_SpatialAudioListener;
private static readonly SpatialAudioListenerList spatialAudioListeners = new SpatialAudioListenerList();
private AkAudioListener AkAudioListener;
/// <summary>
/// Returns the "single" spatial audio listener.
/// </summary>
public static AkAudioListener TheSpatialAudioListener
{
get { return s_SpatialAudioListener != null ? s_SpatialAudioListener.AkAudioListener : null; }
}
/// <summary>
/// Returns the list of active Unity Game Objects that are designated to be spatial audio listeners.
/// </summary>
public static SpatialAudioListenerList SpatialAudioListeners
{
get { return spatialAudioListeners; }
}
private void Awake()
{
AkAudioListener = GetComponent<AkAudioListener>();
}
private void OnEnable()
{
spatialAudioListeners.Add(this);
}
private void OnDisable()
{
spatialAudioListeners.Remove(this);
}
/// <summary>
/// This class represents the list of active Unity Game Objects that are designated to be spatial audio listeners.
/// Currently, only one spatial audio listener can be active at a time.
/// </summary>
public class SpatialAudioListenerList
{
private readonly System.Collections.Generic.List<AkSpatialAudioListener> listenerList =
new System.Collections.Generic.List<AkSpatialAudioListener>();
public System.Collections.Generic.List<AkSpatialAudioListener> ListenerList
{
get { return listenerList; }
}
/// <summary>
/// Uniquely adds listeners to the list
/// </summary>
/// <param name="listener"></param>
/// <returns></returns>
public bool Add(AkSpatialAudioListener listener)
{
if (listener == null)
{
return false;
}
if (listenerList.Contains(listener))
{
return false;
}
listenerList.Add(listener);
Refresh();
return true;
}
/// <summary>
/// Removes listeners from the list
/// </summary>
/// <param name="listener"></param>
/// <returns></returns>
public bool Remove(AkSpatialAudioListener listener)
{
if (listener == null)
{
return false;
}
if (!listenerList.Remove(listener))
{
return false;
}
Refresh();
return true;
}
private void Refresh()
{
if (ListenerList.Count == 1)
{
if (s_SpatialAudioListener != null)
{
AkUnitySoundEngine.UnregisterSpatialAudioListener(s_SpatialAudioListener.gameObject);
}
s_SpatialAudioListener = ListenerList[0];
AkUnitySoundEngine.RegisterSpatialAudioListener(s_SpatialAudioListener.gameObject);
}
else if (ListenerList.Count == 0 && s_SpatialAudioListener != null)
{
AkUnitySoundEngine.UnregisterSpatialAudioListener(s_SpatialAudioListener.gameObject);
s_SpatialAudioListener = null;
}
}
}
#if UNITY_EDITOR
#region WwiseMigration
bool AK.Wwise.IMigratable.Migrate(UnityEditor.SerializedObject obj)
{
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.NewScriptableObjectFolder_v2019_2_0))
return false;
UnityEditor.Undo.AddComponent<AkRoomAwareObject>(gameObject);
return true;
}
#endregion
#endif
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 976062e6c0f8cb944ad0f941852ec198
@@ -0,0 +1,120 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/AkState")]
[UnityEngine.ExecuteInEditMode]
[UnityEngine.DefaultExecutionOrder(-20)]
/// @brief This will call \c AkUnitySoundEngine.SetState() whenever the selected Unity event is triggered. For example this component could be set on a Unity collider to trigger when an object enters it.
/// \sa
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__states.html" target="_blank">Integration Details - States</a> (Note: This is described in the Wwise SDK documentation.)
public class AkState : AkDragDropTriggerHandler
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
public AK.Wwise.State data = new AK.Wwise.State();
protected override AK.Wwise.BaseType WwiseType { get { return data; } }
protected override void Awake()
{
base.Awake();
#if UNITY_EDITOR
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
data.ObjectReference = reference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
#endif
}
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
data.SetValue();
}
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public int valueID { get { return (int)(data == null ? AkUnitySoundEngine.AK_INVALID_UNIQUE_ID : data.Id); } }
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public int groupID { get { return (int)(data == null ? AkUnitySoundEngine.AK_INVALID_UNIQUE_ID : data.GroupId); } }
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public byte[] valueGuid
{
get
{
if (data == null)
return null;
var objRef = data.ObjectReference;
return !objRef ? null : objRef.Guid.ToByteArray();
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public byte[] groupGuid
{
get
{
if (data == null)
return null;
var objRef = data.GroupWwiseObjectReference;
return !objRef ? null : objRef.Guid.ToByteArray();
}
}
#endregion
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("valueID")]
private int valueIdInternal;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("groupID")]
private int groupIdInternal;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("valueGuid")]
private byte[] valueGuidInternal;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("groupGuid")]
private byte[] groupGuidInternal;
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
bool AK.Wwise.IMigratable.Migrate(UnityEditor.SerializedObject obj)
{
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
return false;
return AK.Wwise.TypeMigration.ProcessDoubleGuidType(obj.FindProperty("data.WwiseObjectReference"), WwiseObjectType.State,
obj.FindProperty("valueGuidInternal"), obj.FindProperty("valueIdInternal"),
obj.FindProperty("groupGuidInternal"), obj.FindProperty("groupIdInternal"));
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bd8db5355b7622f42b137a530652ef64
@@ -0,0 +1,783 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
using AK.Wwise.Unity.Logging;
[UnityEngine.AddComponentMenu("Wwise/Spatial Audio/AkSurfaceReflector")]
[UnityEngine.ExecuteInEditMode]
///@brief This component converts the provided mesh into Spatial Audio Geometry.
///@details This component takes a mesh as a parameter. The triangles of the mesh are sent to Spatial Audio by calling SpatialAudio::AddGeometrySet(). The triangles reflect sounds that have an associated early reflections bus. If diffraction is enabled on this component, spatial audio also finds edges on the provided mesh, which diffract sounds that are diffraction enabled.
public class AkSurfaceReflector : UnityEngine.MonoBehaviour
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
public static ulong INVALID_GEOMETRY_ID = unchecked((ulong)-1.0f);
[UnityEngine.Tooltip("The mesh to send to Spatial Audio as a Geometry Set. If this GameObject has a MeshFilter component, you can leave this parameter to None to use the same mesh for Spatial Audio. Otherwise, this parameter lets you import a different mesh for Spatial Audio purposes. We recommend using a simplified mesh.")]
/// The mesh to send to Spatial Audio as a Geometry Set. We recommend using a simplified mesh.
public UnityEngine.Mesh Mesh;
[UnityEngine.Tooltip("The acoustic texture per submesh. The acoustic texture represents the surface of the geometry. An acoustic texture is a set of absorption levels that will filter the sound reflected from the geometry.")]
/// The acoustic texture per submesh. The acoustic texture represents the surface of the geometry. An acoustic texture is a set of absorption levels that will filter the sound reflected from the geometry.
public AK.Wwise.AcousticTexture[] AcousticTextures = new AK.Wwise.AcousticTexture[1];
[UnityEngine.Tooltip("The transmission loss value per submesh. The transmission loss value is a control value used to adjust sound parameters. Typically, a value of 1.0 represents total sound loss, and a value of 0.0 indicates that sound can be transmitted through the geometry without any loss. Default value : 1.0.")]
[UnityEngine.Range(0, 1)]
/// The transmission loss value per submesh. The transmission loss value is a control value used to adjust sound parameters. Typically, a value of 1.0 represents total sound loss, and a value of 0.0 indicates that sound can be transmitted through the geometry without any loss. Default value : 1.0.
public float[] TransmissionLossValues = new[] { 1.0f };
[UnityEngine.Tooltip("Enable or disable geometric diffraction for this mesh.")]
/// Switch to enable or disable geometric diffraction for this mesh.
public bool EnableDiffraction = true;
[UnityEngine.Tooltip("Enable or disable geometric diffraction on boundary edges for this mesh. Boundary edges are edges that are connected to only one triangle.")]
/// Switch to enable or disable geometric diffraction on boundary edges for this mesh. Boundary edges are edges that are connected to only one triangle.
public bool EnableDiffractionOnBoundaryEdges = false;
[UnityEngine.Tooltip("[Experimental] Enable this to allow the geometry instance to be an obstacle to paths going into or through portal bounds.")]
/// [Experimental] Enable this to allow the geometry instance to be an obstacle to paths going into or through portal bounds. When set to false (default), the intersection of the geometry instance with any portal bounding box is subtracted from the geometry.In effect, an opening is created at the portal location through which sound can pass. When set to true, portals cannot create openings in the geometry instance.
public bool BypassPortalSubtraction = false;
[UnityEngine.Tooltip("A solid geometry instance applies transmission loss once, over its volume. A non-solid geometry instance is one where each surface is infinitely thin, applying transmission loss at each surface.")]
/// A solid geometry instance applies transmission loss once, over its volume. A non-solid geometry instance is one where each surface is infinitely thin, applying transmission loss at each surface.
public bool Solid = false;
[UnityEngine.Tooltip("Set to true to set this geometry as static: a geometry that will not move nor will its properties change during gameplay. A non-static geometry will check the state of its transform and the state of its properties each frame and update the geometry in Wwise if there is a change.")]
/// Set to true to set this geometry as static: a geometry that will not move nor will its properties change during gameplay. A non-static geometry will check the state of its transform and the state of its properties each frame and update the geometry in Wwise if there is a change.
public bool isStatic = false;
private int PreviousTransformState;
private int PreviousGeometryState;
private int PreviousGeometryInstanceState;
private bool isGeometrySetInWwise = false;
private int GetTransformState()
{
int[] hashCodes = new[] {
transform.position.GetHashCode(),
transform.lossyScale.GetHashCode(),
transform.rotation.GetHashCode()
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
private int GetGeometryState()
{
int[] hashCodes = new int[3 + AcousticTextures.Length + TransmissionLossValues.Length];
hashCodes[0] = Mesh.GetHashCode();
hashCodes[1] = EnableDiffraction.GetHashCode();
hashCodes[2] = EnableDiffractionOnBoundaryEdges.GetHashCode();
int idx = 3;
foreach (var AcousticTexture in AcousticTextures)
{
hashCodes[idx] = AcousticTexture.ObjectReference != null? AcousticTexture.GetHashCode() : 0;
idx++;
}
foreach (var TransmissionLossValue in TransmissionLossValues)
{
hashCodes[idx] = TransmissionLossValue.GetHashCode();
idx++;
}
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
private int GetGeometryInstanceState()
{
int[] hashCodes = new[] {
BypassPortalSubtraction.GetHashCode(),
Solid.GetHashCode(),
};
return AK.Wwise.BaseType.CombineHashCodes(hashCodes);
}
/// <summary>
/// The Spatial Audio Geometry Data. Can be used when calling AkUnitySoundEngine.SetGeometry()
/// </summary>
public struct GeometryData
{
public UnityEngine.Vector3[] vertices;
public AkTriangleArray triangles;
public AkAcousticSurfaceArray surfaces;
public uint numVertices;
public uint numTriangles;
public uint numSurfaces;
}
public ulong GetID()
{
return (ulong)GetInstanceID();
}
/// <summary>
/// Convert the mesh into a geometry consisting of vertices, triangles, surfaces, acoustic textures and transmission loss values.
/// Send it to Wwise with the rest of the AkGeometryParams to add or update a geometry in Spatial Audio.
/// It is necessary to create at least one geometry instance for each geometry set that is to be used for diffraction and reflection simulation. See SetGeometryInstance().
/// </summary>
/// <param name="mesh">The mesh representing the geometry to be sent to Spatial Audio.</param>
/// <param name="geometryID">A unique ID representing the geometry.</param>
/// <param name="enableDiffraction">Enable the edges of this geometry to become diffraction edges.</param>
/// <param name="enableDiffractionOnBoundaryEdges">Enable the boundary edges of this geometry to become diffraction edges. Boundary edges are edges that are connected to only one triangle.</param>
/// <param name="acousticTextures">The acoustic texture of each surface of the geometry. Acoustic textures describe the filtering when sound reflects on the surface.</param>
/// <param name="transmissionLossValues">The transmission loss value of each surface of the geometry. Transmission loss is the filtering when the sound goes through the surface.</param>
/// <param name="name">A name for the geometry.</param>
/// <returns>Returns true if the Geometry was sent to Wwise.</returns>
public static bool SetGeometryFromMesh(
UnityEngine.Mesh mesh,
ulong geometryID,
bool enableDiffraction,
bool enableDiffractionOnBoundaryEdges,
AK.Wwise.AcousticTexture[] acousticTextures = null,
float[] transmissionLossValues = null,
string name = "")
{
if (!AkUnitySoundEngine.IsInitialized())
{
return false;
}
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying) return false;
#endif
var geometryData = new GeometryData();
GetGeometryDataFromMesh(mesh, ref geometryData, acousticTextures, transmissionLossValues, name);
if (geometryData.numTriangles > 0)
{
var result = AkUnitySoundEngine.SetGeometry(
geometryID,
geometryData.triangles,
geometryData.numTriangles,
geometryData.vertices,
geometryData.numVertices,
geometryData.surfaces,
geometryData.numSurfaces,
enableDiffraction,
enableDiffractionOnBoundaryEdges);
return result == AKRESULT.AK_Success;
}
else
{
WwiseLogger.LogFormat("SetGeometry({0}): No valid triangle was found. Geometry was not set", mesh.name);
return false;
}
}
/// <summary>
/// Create Spatial Audio Geometry Data from a Unity mesh. The Geometry Data can be used later to call AkUnitySoundEngine.SetGeometry()
/// </summary>
/// <param name="mesh">The mesh representing the geometry to be sent to Spatial Audio.</param>
/// <param name="geometryData">(Output)The Spatial Audio Geometry Data created from the mesh.</param>
/// <param name="acousticTextures">The acoustic texture of each surface of the geometry. Acoustic textures describe the filtering when sound reflects on the surface.</param>
/// <param name="transmissionLossValues">The transmission loss value of each surface of the geometry. Transmission loss is the filtering when the sound goes through the surface.</param>
/// <param name="name">A name for the geometry.</param>
public static void GetGeometryDataFromMesh(
UnityEngine.Mesh mesh,
ref GeometryData geometryData,
AK.Wwise.AcousticTexture[] acousticTextures = null,
float[] transmissionLossValues = null,
string name = "")
{
var vertices = mesh.vertices;
// Remove duplicate vertices
var vertRemap = new int[vertices.Length];
var uniqueVerts = new System.Collections.Generic.List<UnityEngine.Vector3>();
var vertDict = new System.Collections.Generic.Dictionary<UnityEngine.Vector3, int>();
for (var v = 0; v < vertices.Length; ++v)
{
var vertex = vertices[v];
if (UnityEngine.Mathf.Abs(vertex.x) < float.MaxValue * UnityEngine.Vector3.kEpsilon)
{
vertex.x = UnityEngine.Mathf.Round(vertex.x / UnityEngine.Vector3.kEpsilon) * UnityEngine.Vector3.kEpsilon;
}
if (UnityEngine.Mathf.Abs(vertex.y) < float.MaxValue * UnityEngine.Vector3.kEpsilon)
{
vertex.y = UnityEngine.Mathf.Round(vertex.y / UnityEngine.Vector3.kEpsilon) * UnityEngine.Vector3.kEpsilon;
}
if (UnityEngine.Mathf.Abs(vertex.z) < float.MaxValue * UnityEngine.Vector3.kEpsilon)
{
vertex.z = UnityEngine.Mathf.Round(vertex.z / UnityEngine.Vector3.kEpsilon) * UnityEngine.Vector3.kEpsilon;
}
int vertIdx = 0;
if (!vertDict.TryGetValue(vertex, out vertIdx))
{
vertIdx = uniqueVerts.Count;
uniqueVerts.Add(vertex);
vertDict.Add(vertex, vertIdx);
}
vertRemap[v] = vertIdx;
}
int vertexCount = uniqueVerts.Count;
geometryData.vertices = new UnityEngine.Vector3[vertexCount];
for (var v = 0; v < vertexCount; ++v)
{
geometryData.vertices[v].x = uniqueVerts[v].x;
geometryData.vertices[v].y = uniqueVerts[v].y;
geometryData.vertices[v].z = uniqueVerts[v].z;
}
int surfaceCount = mesh.subMeshCount;
var numTriangles = mesh.triangles.Length / 3;
if ((mesh.triangles.Length % 3) != 0)
{
WwiseLogger.LogFormat("SetGeometryFromMesh({0}): Wrong number of triangles", mesh.name);
}
geometryData.surfaces = new AkAcousticSurfaceArray(surfaceCount);
geometryData.triangles = new AkTriangleArray(numTriangles);
int triangleArrayIdx = 0;
for (var s = 0; s < surfaceCount; ++s)
{
var surface = geometryData.surfaces[s];
var triangles = mesh.GetTriangles(s);
var triangleCount = triangles.Length / 3;
if ((triangles.Length % 3) != 0)
{
WwiseLogger.LogFormat("SetGeometryFromMesh({0}): Wrong number of triangles in submesh {1}", mesh.name, s);
}
AK.Wwise.AcousticTexture acousticTexture = null;
float occlusionValue = 1.0f;
if (acousticTextures != null && s < acousticTextures.Length)
{
acousticTexture = acousticTextures[s];
}
if (transmissionLossValues != null && s < transmissionLossValues.Length)
{
occlusionValue = transmissionLossValues[s];
}
surface.textureID = acousticTexture == null ? AK.Wwise.AcousticTexture.InvalidId : acousticTexture.Id;
surface.transmissionLoss = occlusionValue;
surface.strName = name + "_" + mesh.name + "_" + s;
for (var i = 0; i < triangleCount; ++i)
{
var triangle = geometryData.triangles[triangleArrayIdx];
triangle.point0 = (ushort)vertRemap[triangles[3 * i + 0]];
triangle.point1 = (ushort)vertRemap[triangles[3 * i + 1]];
triangle.point2 = (ushort)vertRemap[triangles[3 * i + 2]];
triangle.surface = (ushort)s;
if (triangle.point0 != triangle.point1 && triangle.point0 != triangle.point2 && triangle.point1 != triangle.point2)
{
++triangleArrayIdx;
}
else
{
WwiseLogger.LogFormat("SetGeometryFromMesh({0}): Skipped degenerate triangle({1}, {2}, {3}) in submesh {4}", mesh.name, 3 * i + 0, 3 * i + 1, 3 * i + 2, s);
}
}
}
geometryData.numVertices = (uint)geometryData.vertices.Length;
geometryData.numTriangles = (uint)triangleArrayIdx;
geometryData.numSurfaces = (uint)geometryData.surfaces.Count();
}
/// <summary>
/// Add or update an instance of the geometry by sending the transform of this component to Wwise.
/// A geometry instance is a unique instance of a geometry set with a specified transform (position, rotation and scale).
/// It is necessary to create at least one geometry instance for each geometry set that is to be used for diffraction and reflection simulation.
/// </summary>
/// <param name="geometryInstanceID">A unique ID to for the geometry instance. It must be unique amongst all geometry instances, including geometry instances referencing different geometries.</param>
/// <param name="geometryID">The ID of the geometry referenced by this instance.</param>
/// <param name="transform">The transform to be applied to the geometry to convert it in world positions.</param>
/// <param name="useForReflectionAndDiffraction">When enabled, the geometry instance triangles are used to compute reflection and diffraction. Set to false when using a geometry instance only to describe a room, and not for reflection and diffraction calculation.</param>
/// <param name="bypassPortalSubtraction">When set to false (default), the intersection of the geometry instance with any portal bounding box is subtracted from the geometry.In effect, an opening is created at the portal location through which sound can pass. When set to true, portals cannot create openings in the geometry instance.</param>
/// <param name="solid">A solid geometry instance applies transmission loss once, over its volume. A non-solid geometry instance is one where each surface is infinitely thin, applying transmission loss at each surface.</param>
public static void SetGeometryInstance(
ulong geometryInstanceID,
ulong geometryID,
UnityEngine.Transform transform,
bool useForReflectionAndDiffraction,
bool bypassPortalSubtraction,
bool solid)
{
if (!AkUnitySoundEngine.IsInitialized())
{
return;
}
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying) return;
#endif
AkTransform geometryTransform = new AkTransform();
geometryTransform.Set(transform.position, transform.forward, transform.up);
AkUnitySoundEngine.SetGeometryInstance(geometryInstanceID, geometryTransform, transform.lossyScale, geometryID, useForReflectionAndDiffraction, bypassPortalSubtraction, solid);
}
/// <summary>
/// Call AkSurfaceReflector::SetGeometryFromMesh() with this component's mesh.
/// </summary>
public void SetGeometry()
{
if (!AkUnitySoundEngine.IsInitialized())
{
return;
}
if (Mesh == null)
{
WwiseLogger.LogFormat("SetGeometry({0}): No mesh found!", gameObject.name);
return;
}
if (SetGeometryFromMesh(
Mesh,
GetID(),
EnableDiffraction,
EnableDiffractionOnBoundaryEdges,
AcousticTextures,
TransmissionLossValues,
name))
{
isGeometrySetInWwise = true;
}
}
/// <summary>
/// Call AkSurfaceReflector::SetGeometryInstance() with this component's tranform.
/// </summary>
public void SetGeometryInstance()
{
SetGeometryInstance(
GetID(),
GetID(),
transform,
true,
BypassPortalSubtraction,
Solid);
}
/// <summary>
/// Update this component's geometry instance
/// </summary>
public void UpdateGeometry()
{
SetGeometryInstance();
}
/// <summary>
/// Remove this component's geometry and corresponding instance from Spatial Audio.
/// </summary>
public void RemoveGeometry()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying) return;
#endif
if (AkUnitySoundEngine.RemoveGeometry(GetID()) == AKRESULT.AK_Success)
{
isGeometrySetInWwise = false;
}
}
/// <summary>
/// Remove this component's geometry instance from Spatial Audio.
/// </summary>
public void RemoveGeometryInstance()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying) return;
#endif
if (isGeometrySetInWwise)
{
AkUnitySoundEngine.RemoveGeometryInstance(GetID());
}
}
private void Awake()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating)
{
return;
}
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
if (AcousticTextures == null || AcousticTextures.Length < 1)
{
AcousticTextures = new AK.Wwise.AcousticTexture[1];
}
if (AcousticTextures[0] == null)
{
AcousticTextures[0] = new AK.Wwise.AcousticTexture();
}
AcousticTextures[0].ObjectReference = reference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
if (!UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
if (Mesh == null)
{
var meshFilter = GetComponent<UnityEngine.MeshFilter>();
if (meshFilter != null)
{
Mesh = meshFilter.sharedMesh;
}
}
}
private void OnEnable()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
// if the MeshFilter component was not available in Awake, check again here
if (Mesh == null)
{
var meshFilter = GetComponent<UnityEngine.MeshFilter>();
if (meshFilter != null)
{
Mesh = meshFilter.sharedMesh;
}
}
// init update conditions
PreviousTransformState = GetTransformState();
PreviousGeometryState = GetGeometryState();
PreviousGeometryInstanceState = GetGeometryInstanceState();
// need to call SetGeometry, even if it might have already been sent to wwise, in case something changed while the component was disabled.
SetGeometry();
if (isGeometrySetInWwise)
{
SetGeometryInstance();
AkRoom roomComponent = gameObject.GetComponent<AkRoom>();
if (roomComponent != null && roomComponent.isActiveAndEnabled && !roomComponent.UsesGeometry(GetID()))
{
roomComponent.SetRoom(GetID());
}
}
}
private void OnDisable()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
RemoveGeometryInstance();
AkRoomManager.UnregisterReflector(this);
AkRoom roomComponent = gameObject.GetComponent<AkRoom>();
if (roomComponent != null && roomComponent.isActiveAndEnabled && roomComponent.UsesGeometry(GetID()))
{
roomComponent.SetRoom(INVALID_GEOMETRY_ID);
}
}
private void OnDestroy()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
if (isGeometrySetInWwise)
{
RemoveGeometry();
}
}
private void Update()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying) return;
#endif
// don't update if is static
if (isStatic) return;
int CurrentGeometryState = GetGeometryState();
if (PreviousGeometryState != CurrentGeometryState)
{
SetGeometry();
PreviousGeometryState = CurrentGeometryState;
}
bool UpdateGeometryInstance = false;
int CurrentTransformState = GetTransformState();
if (PreviousTransformState != CurrentTransformState)
{
UpdateGeometryInstance = true;
PreviousTransformState = CurrentTransformState;
}
else
{
int CurrentGeometryInstanceState = GetGeometryInstanceState();
if (PreviousGeometryInstanceState != CurrentGeometryInstanceState)
{
UpdateGeometryInstance = true;
PreviousGeometryInstanceState = CurrentGeometryInstanceState;
}
}
if (UpdateGeometryInstance)
{
SetGeometryInstance();
}
}
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public static ulong GetAkGeometrySetID(UnityEngine.MeshFilter meshFilter)
{
return (ulong)meshFilter.GetInstanceID();
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public static void AddGeometrySet(
AK.Wwise.AcousticTexture acousticTexture,
UnityEngine.MeshFilter meshFilter,
bool enableDiffraction,
bool enableDiffractionOnBoundaryEdges,
bool enableTriangles)
{
if (!AkUnitySoundEngine.IsInitialized())
{
return;
}
if (meshFilter == null)
{
WwiseLogger.LogFormat("AddGeometrySet: No mesh found!");
return;
}
var AcousticTextures = new[] { acousticTexture };
var OcclusionValues = new[] { 1.0f };
SetGeometryFromMesh(
meshFilter.sharedMesh,
GetAkGeometrySetID(meshFilter),
enableDiffraction,
enableDiffractionOnBoundaryEdges,
AcousticTextures,
OcclusionValues,
meshFilter.name);
SetGeometryInstance(GetAkGeometrySetID(meshFilter), GetAkGeometrySetID(meshFilter), meshFilter.transform, enableTriangles, false, false);
}
// for migration purpose, have a single acoustic texture parameter as a setter
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public AK.Wwise.AcousticTexture AcousticTexture
{
get
{
return (AcousticTextures == null || AcousticTextures.Length < 1) ? null : AcousticTextures[0];
}
set
{
var numAcousticTextures = (Mesh == null) ? 1 : Mesh.subMeshCount;
if (AcousticTextures == null || AcousticTextures.Length < numAcousticTextures)
{
AcousticTextures = new AK.Wwise.AcousticTexture[numAcousticTextures];
}
for (int i = 0; i < numAcousticTextures; ++i)
{
AcousticTextures[i] = new AK.Wwise.AcousticTexture { WwiseObjectReference = value != null ? value.WwiseObjectReference : null };
}
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_0)]
public static void RemoveGeometrySet(UnityEngine.MeshFilter meshFilter)
{
if (meshFilter != null)
{
AkUnitySoundEngine.RemoveGeometry(GetAkGeometrySetID(meshFilter));
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2021_1_0)]
public float[] OcclusionValues
{
get
{
return TransmissionLossValues;
}
set
{
TransmissionLossValues = value;
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2022_1_0)]
public static void SetGeometryFromMesh(
UnityEngine.Mesh mesh,
UnityEngine.Transform transform,
ulong geometryID,
bool enableDiffraction,
bool enableDiffractionOnBoundaryEdges,
bool enableTriangles,
AK.Wwise.AcousticTexture[] acousticTextures = null,
float[] transmissionLossValues = null,
string name = "")
{
SetGeometryFromMesh(
mesh,
geometryID,
enableDiffraction,
enableDiffractionOnBoundaryEdges,
acousticTextures,
transmissionLossValues,
"");
SetGeometryInstance(geometryID, geometryID, transform, enableTriangles, false, false);
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2023_1_0)]
public static void SetGeometryFromMesh(
UnityEngine.Mesh mesh,
ulong geometryID,
bool enableDiffraction,
bool enableDiffractionOnBoundaryEdges,
bool enableTriangles,
AK.Wwise.AcousticTexture[] acousticTextures = null,
float[] transmissionLossValues = null,
string name = "")
{
SetGeometryFromMesh(mesh,
geometryID,
enableDiffraction,
enableDiffractionOnBoundaryEdges,
acousticTextures,
transmissionLossValues,
"");
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2023_1_0)]
public static void SetGeometryInstance(
ulong geometryInstanceID,
ulong geometryID,
UnityEngine.Transform transform)
{
SetGeometryInstance(
geometryInstanceID,
geometryID,
transform,
true,
false,
false);
}
#endregion
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("AcousticTexture")]
private AK.Wwise.AcousticTexture AcousticTextureInternal = new AK.Wwise.AcousticTexture();
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
bool AK.Wwise.IMigratable.Migrate(UnityEditor.SerializedObject obj)
{
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.NewScriptableObjectFolder_v2019_2_0))
{
return false;
}
var hasChanged = false;
var numAcousticTextures = 1;
var meshProperty = obj.FindProperty("Mesh");
if (meshProperty != null)
{
var meshFilter = GetComponent<UnityEngine.MeshFilter>();
if (meshFilter)
{
var sharedMesh = meshFilter.sharedMesh;
if (sharedMesh)
{
hasChanged = true;
meshProperty.objectReferenceValue = sharedMesh;
numAcousticTextures = sharedMesh.subMeshCount;
}
}
}
var oldwwiseObjRefProperty = obj.FindProperty("AcousticTextureInternal.WwiseObjectReference");
if (oldwwiseObjRefProperty != null)
{
var objectReferenceValue = oldwwiseObjRefProperty.objectReferenceValue;
if (objectReferenceValue != null)
{
hasChanged = true;
var acousticTextures = obj.FindProperty("AcousticTextures");
acousticTextures.arraySize = numAcousticTextures;
for (int i = 0; i < numAcousticTextures; ++i)
{
acousticTextures.GetArrayElementAtIndex(i).FindPropertyRelative("WwiseObjectReference").objectReferenceValue = objectReferenceValue;
}
}
}
return hasChanged;
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: ea72298970a30f14080ee7de1e89f6c6
@@ -0,0 +1,120 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/AkSwitch")]
[UnityEngine.ExecuteInEditMode]
[UnityEngine.DefaultExecutionOrder(-10)]
/// @brief This will call <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=namespace_a_k_1_1_sound_engine_a9c9d57ba7b3af2b896e26297a7657264.html" target="_blank">AkUnitySoundEngine.SetSwitch()</a> whenever the selected Unity event is triggered. For example, this component could be set on a Unity collider to trigger when an object enters it.
/// \sa
/// - <a href="https://www.audiokinetic.com/library/edge/?source=SDK&id=soundengine__switch.html" target="_blank">Integration Details - Switches</a> (Note: This is described in the Wwise SDK documentation.)
public class AkSwitch : AkDragDropTriggerHandler
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
public AK.Wwise.Switch data = new AK.Wwise.Switch();
protected override AK.Wwise.BaseType WwiseType { get { return data; } }
protected override void Awake()
{
base.Awake();
#if UNITY_EDITOR
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
data.ObjectReference = reference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
#endif
}
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
data.SetValue(useOtherObject && in_gameObject != null ? in_gameObject : gameObject);
}
#region Obsolete
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public int valueID { get { return (int)(data == null ? AkUnitySoundEngine.AK_INVALID_UNIQUE_ID : data.Id); } }
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public int groupID { get { return (int)(data == null ? AkUnitySoundEngine.AK_INVALID_UNIQUE_ID : data.GroupId); } }
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public byte[] valueGuid
{
get
{
if (data == null)
return null;
var objRef = data.ObjectReference;
return !objRef ? null : objRef.Guid.ToByteArray();
}
}
[System.Obsolete(AkUnitySoundEngine.Deprecation_2018_1_6)]
public byte[] groupGuid
{
get
{
if (data == null)
return null;
var objRef = data.GroupWwiseObjectReference;
return !objRef ? null : objRef.Guid.ToByteArray();
}
}
#endregion
#region WwiseMigration
#pragma warning disable 0414 // private field assigned but not used.
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("valueID")]
private int valueIdInternal = (int)AkUnitySoundEngine.AK_INVALID_UNIQUE_ID;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("groupID")]
private int groupIdInternal = (int)AkUnitySoundEngine.AK_INVALID_UNIQUE_ID;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("valueGuid")]
private byte[] valueGuidInternal;
[UnityEngine.HideInInspector]
[UnityEngine.SerializeField]
[UnityEngine.Serialization.FormerlySerializedAs("groupGuid")]
private byte[] groupGuidInternal;
#pragma warning restore 0414 // private field assigned but not used.
#if UNITY_EDITOR
bool AK.Wwise.IMigratable.Migrate(UnityEditor.SerializedObject obj)
{
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
return false;
return AK.Wwise.TypeMigration.ProcessDoubleGuidType(obj.FindProperty("data.WwiseObjectReference"), WwiseObjectType.Switch,
obj.FindProperty("valueGuidInternal"), obj.FindProperty("valueIdInternal"),
obj.FindProperty("groupGuidInternal"), obj.FindProperty("groupIdInternal"));
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 328e03a0aa8c79f43ad65e394f1805f8
@@ -0,0 +1,24 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[System.Obsolete(AkUnitySoundEngine.Deprecation_2024_1_0)]
[UnityEngine.DisallowMultipleComponent]
public class AkTerminator : UnityEngine.MonoBehaviour
{
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0d6277d1dfbc6124b9c228e004b2ca18
@@ -0,0 +1,59 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
/// @brief Base class for the generic triggering mechanism for Wwise Integration.
/// All Wwise components will use this mechanism to drive their behavior.
/// Derive from this class to add your own triggering condition, as described in \ref unity_add_triggers
public abstract class AkTriggerBase : UnityEngine.MonoBehaviour
{
/// Delegate declaration for all Wwise Triggers.
public delegate void Trigger(
UnityEngine.GameObject in_gameObject ///< in_gameObject is used to pass "Collidee" objects when Colliders are used. Some components have the option "Use other object", this is the object they'll use.
);
/// All components reacting to the trigger will be registered in this delegate.
public Trigger triggerDelegate = null;
public static System.Collections.Generic.Dictionary<uint, string> GetAllDerivedTypes()
{
var derivedTypes = new System.Collections.Generic.Dictionary<uint, string>();
var baseType = typeof(AkTriggerBase);
var types = baseType.Assembly.GetTypes();
for (var i = 0; i < types.Length; i++)
{
if (types[i].IsClass &&
(types[i].IsSubclassOf(baseType) || baseType.IsAssignableFrom(types[i]) && baseType != types[i]))
{
var typeName = types[i].Name;
derivedTypes.Add(AkUtilities.ShortIDGenerator.Compute(typeName), typeName);
}
}
//Add the Awake, Start and Destroy triggers and build the displayed list.
derivedTypes.Add(AkUtilities.ShortIDGenerator.Compute("Awake"), "Awake");
derivedTypes.Add(AkUtilities.ShortIDGenerator.Compute("Start"), "Start");
derivedTypes.Add(AkUtilities.ShortIDGenerator.Compute("Destroy"), "Destroy");
return derivedTypes;
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 22ffefc5e7ebbe041be105d200358015
@@ -0,0 +1,35 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerCollisionEnter : AkTriggerBase
{
public UnityEngine.GameObject triggerObject = null;
private void OnCollisionEnter(UnityEngine.Collision in_other)
{
if (triggerDelegate != null && (triggerObject == null || triggerObject == in_other.gameObject))
triggerDelegate(in_other.gameObject);
}
private void OnTriggerEnter(UnityEngine.Collider in_other)
{
if (triggerDelegate != null && (triggerObject == null || triggerObject == in_other.gameObject))
triggerDelegate(in_other.gameObject);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e373aeb0201d8a04f9db6db17c228f5b
@@ -0,0 +1,29 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerCollisionExit : AkTriggerBase
{
public UnityEngine.GameObject triggerObject = null;
private void OnCollisionExit(UnityEngine.Collision in_other)
{
if (triggerDelegate != null && (triggerObject == null || triggerObject == in_other.gameObject))
triggerDelegate(in_other.gameObject);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0c8f2c6ec88d6ed41a064c25ad2e6ad6
@@ -0,0 +1,28 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerDisable : AkTriggerBase
{
private void OnDisable()
{
if (triggerDelegate != null)
triggerDelegate(null);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c71c1b76ff02a5d4c9875c502faab649
@@ -0,0 +1,24 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[System.Obsolete(AkUnitySoundEngine.Deprecation_2019_2_2)]
public class AkTriggerEnable : AkTriggerBase
{
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 2ad874568d147134dbf1a9406d78fb27
@@ -0,0 +1,29 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerEnter : AkTriggerBase
{
public UnityEngine.GameObject triggerObject = null;
private void OnTriggerEnter(UnityEngine.Collider in_other)
{
if (triggerDelegate != null && (triggerObject == null || triggerObject == in_other.gameObject))
triggerDelegate(in_other.gameObject);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 95f7f15ab339643419a5ae4ced37bc4d
@@ -0,0 +1,29 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerExit : AkTriggerBase
{
public UnityEngine.GameObject triggerObject = null;
private void OnTriggerExit(UnityEngine.Collider in_other)
{
if (triggerDelegate != null && (triggerObject == null || triggerObject == in_other.gameObject))
triggerDelegate(in_other.gameObject);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: c3148f5568f4d064bb934bf5e051d221
@@ -0,0 +1,255 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public abstract class AkTriggerHandler : UnityEngine.MonoBehaviour
{
public const int AWAKE_TRIGGER_ID = 1151176110;
public const int START_TRIGGER_ID = 1281810935;
public const int DESTROY_TRIGGER_ID = unchecked((int)3936390293);
public const int ON_ENABLE_TRIGGER_ID = -320808462;
public const int ON_DISABLE_TRIGGER_ID = 716467161;
///Since our mask is a 32 bits integer, we can't have more than 32 triggers
public const int MAX_NB_TRIGGERS = 32;
///Will contain the types of all the triggers derived from AkTriggerBase at runtime
public static System.Collections.Generic.Dictionary<uint, string> triggerTypes = AkTriggerBase.GetAllDerivedTypes();
private bool didDestroy;
///List containing the enabled triggers.
public System.Collections.Generic.List<int> triggerList = new System.Collections.Generic.List<int> { START_TRIGGER_ID };
///This property is usefull only when used with colliders. When enabled, the target of the action will be the other colliding object. When disabled, it will be the current object.
public bool useOtherObject = false;
public abstract void HandleEvent(UnityEngine.GameObject in_gameObject);
#if UNITY_EDITOR
private bool pausedOnStart = false;
#endif
protected virtual void Awake()
{
RegisterTriggers(triggerList, HandleEvent);
}
#if UNITY_EDITOR
private void OnPause(UnityEditor.PauseState state)
{
if(pausedOnStart && state == UnityEditor.PauseState.Unpaused)
{
pausedOnStart = false;
UnityEditor.EditorApplication.pauseStateChanged -= OnPause;
if (UnityEditor.EditorApplication.isPlaying && (triggerList.Contains(START_TRIGGER_ID) || triggerList.Contains(AWAKE_TRIGGER_ID)))
{
HandleEvent(null);
}
}
}
#endif
protected virtual void Start()
{
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPaused)
{
UnityEditor.EditorApplication.pauseStateChanged += OnPause;
pausedOnStart = true;
}
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating || UnityEditor.EditorApplication.isPaused)
{
return;
}
#endif
if (triggerList.Contains(START_TRIGGER_ID))
{
HandleEvent(null);
}
}
protected virtual void OnDestroy()
{
if (!didDestroy)
{
DoDestroy();
}
#if UNITY_EDITOR
UnityEditor.EditorApplication.pauseStateChanged -= OnPause;
#endif
}
public void DoDestroy()
{
UnregisterTriggers(triggerList, HandleEvent);
didDestroy = true;
}
public virtual void OnEnable()
{
if (triggerList.Contains(ON_ENABLE_TRIGGER_ID))
{
HandleEvent(null);
}
}
protected void RegisterTriggers(System.Collections.Generic.List<int> in_triggerList, AkTriggerBase.Trigger in_delegate)
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating)
{
return;
}
#endif
foreach (uint triggerID in in_triggerList)
{
switch (triggerID)
{
case AWAKE_TRIGGER_ID:
case START_TRIGGER_ID:
case unchecked((uint)DESTROY_TRIGGER_ID):
case unchecked((uint)ON_ENABLE_TRIGGER_ID):
continue;
}
var triggerName = string.Empty;
if (triggerTypes.TryGetValue(triggerID, out triggerName))
{
var trigger = (AkTriggerBase)GetComponent(System.Type.GetType(triggerName));
if (trigger == null)
{
trigger = (AkTriggerBase)gameObject.AddComponent(System.Type.GetType(triggerName));
}
trigger.triggerDelegate += in_delegate;
}
}
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPaused)
{
UnityEditor.EditorApplication.pauseStateChanged += OnPause;
pausedOnStart = true;
return;
}
#endif
if (in_triggerList.Contains(AWAKE_TRIGGER_ID))
{
in_delegate(null);
}
}
protected void UnregisterTriggers(System.Collections.Generic.List<int> in_triggerList, AkTriggerBase.Trigger in_delegate)
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating)
{
return;
}
#endif
foreach (uint triggerID in in_triggerList)
{
switch (triggerID)
{
case AWAKE_TRIGGER_ID:
case START_TRIGGER_ID:
case unchecked((uint)DESTROY_TRIGGER_ID):
case unchecked((uint)ON_ENABLE_TRIGGER_ID):
continue;
}
var triggerName = string.Empty;
if (triggerTypes.TryGetValue(triggerID, out triggerName))
{
var trigger = (AkTriggerBase)GetComponent(System.Type.GetType(triggerName));
if (trigger != null)
{
trigger.triggerDelegate -= in_delegate;
if (trigger.triggerDelegate == null)
{
#if UNITY_EDITOR
if (UnityEditor.EditorApplication.isPlaying)
#endif
Destroy(trigger);
}
}
}
}
if (in_triggerList.Contains(DESTROY_TRIGGER_ID))
{
in_delegate(null);
}
}
}
public abstract class AkDragDropTriggerHandler : AkTriggerHandler
{
protected abstract AK.Wwise.BaseType WwiseType { get; }
protected override void Awake()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating)
{
return;
}
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
WwiseType.ObjectReference = reference;
}
if (!UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
base.Awake();
}
protected override void Start()
{
#if UNITY_EDITOR
if (!UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
base.Start();
}
protected override void OnDestroy()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
{
return;
}
#endif
base.OnDestroy();
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e90b598caaf315b4cad3c5c4a9d59827
@@ -0,0 +1,28 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerMouseDown : AkTriggerBase
{
private void OnMouseDown()
{
if (triggerDelegate != null)
triggerDelegate(null);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7b7bc22995464ef42b69495737cedb71
@@ -0,0 +1,28 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerMouseEnter : AkTriggerBase
{
private void OnMouseEnter()
{
if (triggerDelegate != null)
triggerDelegate(null);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f5db3276ceb515443bd3bad9d745bec8
@@ -0,0 +1,28 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerMouseExit : AkTriggerBase
{
private void OnMouseExit()
{
if (triggerDelegate != null)
triggerDelegate(null);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 94c44dda4497b974990c981c8b39950b
@@ -0,0 +1,28 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
public class AkTriggerMouseUp : AkTriggerBase
{
private void OnMouseUp()
{
if (triggerDelegate != null)
triggerDelegate(null);
}
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: f586fcabeec8df446bd6dcdb9657a670
@@ -0,0 +1,70 @@
#if !(UNITY_QNX) // Disable under unsupported platforms.
/*******************************************************************************
The content of this file includes portions of the proprietary AUDIOKINETIC Wwise
Technology released in source code form as part of the game integration package.
The content of this file may not be used without valid licenses to the
AUDIOKINETIC Wwise Technology.
Note that the use of the game engine is subject to the Unity(R) Terms of
Service at https://unity3d.com/legal/terms-of-service
License Usage
Licensees holding valid licenses to the AUDIOKINETIC Wwise Technology may use
this file in accordance with the end user license agreement provided with the
software or, alternatively, in accordance with the terms contained
in a written agreement between you and Audiokinetic Inc.
Copyright (c) 2026 Audiokinetic Inc.
*******************************************************************************/
[UnityEngine.AddComponentMenu("Wwise/AkWwiseTrigger")]
[UnityEngine.ExecuteInEditMode]
/// @brief This will call \c AkUnitySoundEngine.PostTrigger() whenever the selected Unity event is triggered. For example this component could be set on a Unity collider to trigger when an object enters it.
/// \sa
/// - <a href="https://www.audiokinetic.com/en/library/edge/?source=Help&id=working_with_triggers_overview" target="_blank">Working with Triggers > Overview</a> (Note: This is described in the Wwise SDK documentation.)
public class AkWwiseTrigger : AkDragDropTriggerHandler
#if UNITY_EDITOR
, AK.Wwise.IMigratable
#endif
{
public AK.Wwise.Trigger data = new AK.Wwise.Trigger();
protected override AK.Wwise.BaseType WwiseType { get { return data; } }
protected override void Awake()
{
base.Awake();
#if UNITY_EDITOR
var reference = AkWwiseTypes.DragAndDropObjectReference;
if (reference)
{
UnityEngine.GUIUtility.hotControl = 0;
data.ObjectReference = reference;
AkWwiseTypes.DragAndDropObjectReference = null;
}
#endif
}
protected override void Start()
{
#if UNITY_EDITOR
if (UnityEditor.BuildPipeline.isBuildingPlayer || AkUtilities.IsMigrating || !UnityEditor.EditorApplication.isPlaying)
return;
#endif
base.Start();
}
public override void HandleEvent(UnityEngine.GameObject in_gameObject)
{
var gameObj = useOtherObject && in_gameObject != null ? in_gameObject : gameObject;
data.Post(gameObj);
}
#region WwiseMigration
#if UNITY_EDITOR
public virtual bool Migrate(UnityEditor.SerializedObject obj)
{
//Didn't exist before, so no migration step as of yet
return true;
}
#endif
#endregion
}
#endif // #if !(UNITY_QNX) // Disable under unsupported platforms.
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: a08c95536c46fc348b9a68f22cc6ba6c