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,40 @@
{
"name": "AK.Wwise.Unity.MonoBehaviour.Editor",
"references": [
"AK.Wwise.Unity.API",
"AK.Wwise.Unity.API.Editor",
"AK.Wwise.Unity.MonoBehaviour",
"AK.Wwise.Unity.API.WwiseTypes",
"AK.Wwise.Unity.Addressables",
"AK.Wwise.Unity.ProjectDatabase",
"AK.Wwise.Unity.Utilities",
"AK.Wwise.Unity.Logging"
],
"includePlatforms": [
"Editor"
],
"excludePlatforms": [],
"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"
},
{
"name": "com.audiokinetic.wwise.addressables",
"expression": "2022.1.0",
"define": "WWISE_ADDRESABLES_2022_1_0_OR_NEWER"
}
],
"noEngineReferences": false
}
@@ -0,0 +1,7 @@
fileFormatVersion: 2
guid: 893d452fd51507e4189660dbd93aede0
AssemblyDefinitionImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,360 @@
using UnityEngine;
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkAmbient), true)]
public class AkAmbientInspector : AkEventInspector
{
public enum AttenuationSphereOptions
{
Dont_Show,
Current_Event_Only,
All_Events
}
public static System.Collections.Generic.Dictionary<UnityEngine.Object, AttenuationSphereOptions> attSphereProperties =
new System.Collections.Generic.Dictionary<UnityEngine.Object, AttenuationSphereOptions>();
public AttenuationSphereOptions currentAttSphereOp;
private AkAmbient m_AkAmbient;
private UnityEditor.SerializedProperty multiPositionTypeProperty;
private UnityEditor.SerializedProperty largeModePositionArrayProperty;
private UnityEditor.SerializedProperty sphereColorProperty;
private System.Collections.Generic.List<int> triggerList;
public new void OnEnable()
{
base.OnEnable();
m_AkAmbient = target as AkAmbient;
multiPositionTypeProperty = serializedObject.FindProperty("multiPositionTypeLabel");
largeModePositionArrayProperty = serializedObject.FindProperty("LargeModePositions");
sphereColorProperty = serializedObject.FindProperty("attenuationSphereColor");
if (!attSphereProperties.ContainsKey(target))
attSphereProperties.Add(target, AttenuationSphereOptions.Dont_Show);
currentAttSphereOp = attSphereProperties[target];
WwiseProjectDatabase.SoundBankDirectoryUpdated += PopulateMaxAttenuation;
}
public new void OnDisable()
{
base.OnDisable();
DefaultHandles.Hidden = false;
WwiseProjectDatabase.SoundBankDirectoryUpdated -= PopulateMaxAttenuation;
}
public override void OnChildInspectorGUI()
{
//Save trigger mask to know when it changes
triggerList = m_AkAmbient.triggerList;
base.OnChildInspectorGUI();
if (UnityEngine.Event.current.type == UnityEngine.EventType.ExecuteCommand
&& UnityEngine.Event.current.commandName == "ObjectSelectorClosed")
{
var pickedObject = UnityEditor.EditorGUIUtility.GetObjectPickerObject();
if (pickedObject != null)
{
int insertIndex = largeModePositionArrayProperty.arraySize;
largeModePositionArrayProperty.InsertArrayElementAtIndex(insertIndex);
var newElement = largeModePositionArrayProperty.GetArrayElementAtIndex(insertIndex);
newElement.objectReferenceValue = pickedObject;
return;
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(multiPositionTypeProperty, new UnityEngine.GUIContent("Position Type: ", "Simple Mode: Only one position is used.\nLarge Mode: Children of AkAmbient with AkAmbientLargeModePositioner component will be used as position source for multi-positioning.\nMultiple Position Mode: Every AkAmbient using the same event will be used as position source for multi-positioning."));
var multiPositionType = (MultiPositionTypeLabel)multiPositionTypeProperty.intValue;
if (multiPositionType == MultiPositionTypeLabel.Large_Mode || multiPositionType == MultiPositionTypeLabel.MultiPosition_Mode)
{
foreach (AkAmbient ambient in targets)
{
if (!ambient.gameObject.isStatic)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEditor.EditorGUILayout.HelpBox(string.Format("Position Type <{0}> requires an AkGameObj that does not move. Consider setting the associated GameObject to static.", multiPositionType), UnityEditor.MessageType.Warning);
break;
}
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
currentAttSphereOp = (AttenuationSphereOptions) UnityEditor.EditorGUILayout.EnumPopup("Show Attenuation Sphere: ", currentAttSphereOp);
attSphereProperties[target] = currentAttSphereOp;
UnityEditor.EditorGUI.BeginChangeCheck();
if (currentAttSphereOp != AttenuationSphereOptions.Dont_Show)
{
UnityEditor.EditorGUILayout.PropertyField(sphereColorProperty, new UnityEngine.GUIContent("Attenuation Sphere Color") );
}
if (UnityEditor.EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
if (multiPositionType == MultiPositionTypeLabel.Large_Mode)
{
UnityEngine.GUILayout.BeginHorizontal();
if (UnityEngine.GUILayout.Button("Add Large Mode position object"))
{
int insertIndex = largeModePositionArrayProperty.arraySize;
largeModePositionArrayProperty.InsertArrayElementAtIndex(insertIndex);
var newPoint = new UnityEngine.GameObject(string.Format("AkAmbientPoint{0}", insertIndex));
UnityEditor.Undo.RegisterCreatedObjectUndo(newPoint, "CreateNewLargeModePositionObject");
UnityEditor.Undo.AddComponent<AkAmbientLargeModePositioner>(newPoint);
UnityEditor.Undo.SetTransformParent(newPoint.transform, m_AkAmbient.transform, "CreateNewLargeModePositionObjectSetParent");
newPoint.transform.position = m_AkAmbient.transform.TransformPoint(UnityEngine.Vector3.zero);
newPoint.transform.localScale = new UnityEngine.Vector3(1f, 1f, 1f);
var newElement = largeModePositionArrayProperty.GetArrayElementAtIndex(insertIndex);
newElement.objectReferenceValue = newPoint.GetComponent<AkAmbientLargeModePositioner>();
}
if (UnityEngine.GUILayout.Button("Pick existing position object"))
{
int controlID = UnityEngine.GUIUtility.GetControlID(UnityEngine.FocusType.Passive);
UnityEditor.EditorGUIUtility.ShowObjectPicker<AkAmbientLargeModePositioner>(null, true, string.Empty, controlID);
}
UnityEngine.GUILayout.EndHorizontal();
++UnityEditor.EditorGUI.indentLevel;
UnityEditor.EditorGUI.BeginChangeCheck();
for (int i = 0; i < largeModePositionArrayProperty.arraySize; ++i)
{
UnityEditor.EditorGUILayout.PropertyField(largeModePositionArrayProperty.GetArrayElementAtIndex(i), true);
}
if (UnityEditor.EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
--UnityEditor.EditorGUI.indentLevel;
}
}
//Save multi-position type to know if it has changed
var multiPosType = m_AkAmbient.multiPositionTypeLabel;
if (m_AkAmbient.multiPositionTypeLabel == MultiPositionTypeLabel.MultiPosition_Mode)
{
UpdateTriggers(multiPosType);
}
}
private void UpdateTriggers(MultiPositionTypeLabel in_multiPosType)
{
//if we just switched to MultiPosition_Mode
if (in_multiPosType != m_AkAmbient.multiPositionTypeLabel)
{
//Get all AkAmbients in the scene
#if UNITY_6000_0_OR_NEWER
var akAmbients = FindObjectsByType<AkAmbient>(FindObjectsSortMode.None);
#else
var akAmbients = FindObjectsOfType<AkAmbient>();
#endif
//Find the first AkAmbient that is in multiPosition_Mode and that has the same event as the current AkAmbient
for (var i = 0; i < akAmbients.Length; i++)
{
if (akAmbients[i] != m_AkAmbient &&
akAmbients[i].multiPositionTypeLabel == MultiPositionTypeLabel.MultiPosition_Mode &&
akAmbients[i].data.Id == m_AkAmbient.data.Id)
{
//if the current AkAmbient doesn't have the same trigger as the others, we ask the user which one he wants to keep
if (!HasSameTriggers(akAmbients[i].triggerList))
{
if (UnityEditor.EditorUtility.DisplayDialog("AkAmbient Trigger Mismatch",
"All ambients in multi-position mode with the same event must have the same triggers.\n" +
"Which triggers would you like to keep?", "Current AkAmbient Triggers", "Other AkAmbients Triggers"))
SetMultiPosTrigger(akAmbients);
else
m_AkAmbient.triggerList = akAmbients[i].triggerList;
}
break;
}
}
}
//if the trigger changed or there was an undo/redo operation, we update the triggers of all the AkAmbients in the same group as the current one
else if (!HasSameTriggers(triggerList) || UnityEngine.Event.current.type == UnityEngine.EventType.ValidateCommand &&
UnityEngine.Event.current.commandName == "UndoRedoPerformed")
{
#if UNITY_6000_0_OR_NEWER
var akAmbients = FindObjectsByType<AkAmbient>(FindObjectsSortMode.None);
#else
var akAmbients = FindObjectsOfType<AkAmbient>();
#endif
SetMultiPosTrigger(akAmbients);
}
}
private bool HasSameTriggers(System.Collections.Generic.List<int> other)
{
return other.Count == m_AkAmbient.triggerList.Count &&
System.Linq.Enumerable.Count(System.Linq.Enumerable.Except(m_AkAmbient.triggerList, other)) == 0;
}
private void SetMultiPosTrigger(AkAmbient[] akAmbients)
{
for (var i = 0; i < akAmbients.Length; i++)
{
if (akAmbients[i].multiPositionTypeLabel == MultiPositionTypeLabel.MultiPosition_Mode &&
akAmbients[i].data.Id == m_AkAmbient.data.Id)
akAmbients[i].triggerList = m_AkAmbient.triggerList;
}
}
private void OnSceneGUI()
{
RenderAttenuationSpheres();
}
public void RenderAttenuationSpheres()
{
if (currentAttSphereOp == AttenuationSphereOptions.Dont_Show)
return;
if (currentAttSphereOp == AttenuationSphereOptions.Current_Event_Only)
{
// Get the max attenuation for the event (if available)
var radius = AkWwiseProjectInfo.GetData().GetEventMaxAttenuation(m_AkAmbient.data.Id) * m_AkAmbient.gameObject.GetComponent<AkGameObj>().ScalingFactor;
if (m_AkAmbient.multiPositionTypeLabel == MultiPositionTypeLabel.Simple_Mode)
{
DrawSphere(m_AkAmbient.gameObject.transform.position, radius, sphereColorProperty.colorValue);
}
else if (m_AkAmbient.multiPositionTypeLabel == MultiPositionTypeLabel.Large_Mode)
{
var positionComponents = m_AkAmbient.GetComponentsInChildren<AkAmbientLargeModePositioner>();
for (int i = 0; i < positionComponents.Length; i++)
{
DrawSphere(positionComponents[i].transform.position, radius, sphereColorProperty.colorValue);
}
}
else
{
#if UNITY_6000_0_OR_NEWER
var akAmbients = FindObjectsByType<AkAmbient>(FindObjectsSortMode.None);
#else
var akAmbients = FindObjectsOfType<AkAmbient>();
#endif
for (var i = 0; i < akAmbients.Length; i++)
{
if (akAmbients[i].multiPositionTypeLabel == MultiPositionTypeLabel.MultiPosition_Mode &&
akAmbients[i].data.Id == m_AkAmbient.data.Id)
{
DrawSphere(akAmbients[i].gameObject.transform.position, radius, akAmbients[i].attenuationSphereColor);
}
}
}
}
else
{
#if UNITY_6000_0_OR_NEWER
var akAmbients = FindObjectsByType<AkAmbient>(FindObjectsSortMode.None);
#else
var akAmbients = FindObjectsOfType<AkAmbient>();
#endif
for (var i = 0; i < akAmbients.Length; i++)
{
// Get the max attenuation for the event (if available)
var radius = AkWwiseProjectInfo.GetData().GetEventMaxAttenuation(akAmbients[i].data.Id);
if (akAmbients[i].multiPositionTypeLabel == MultiPositionTypeLabel.Large_Mode)
{
var positionComponents = m_AkAmbient.GetComponentsInChildren<AkAmbientLargeModePositioner>();
for (int j = 0; j < positionComponents.Length; j++)
{
DrawSphere(positionComponents[j].transform.position, radius, akAmbients[i].attenuationSphereColor);
}
}
else
{
DrawSphere(akAmbients[i].gameObject.transform.position, radius, akAmbients[i].attenuationSphereColor);
}
}
}
}
private void DrawSphere(UnityEngine.Vector3 in_position, float in_radius, UnityEngine.Color in_sphereColor)
{
UnityEngine.Color wireColor = in_sphereColor;
wireColor.a = 0.9f;
if ((UnityEditor.SceneView.lastActiveSceneView.camera.transform.position - in_position).sqrMagnitude > in_radius * in_radius)
{
UnityEditor.Handles.color = wireColor;
DrawWireDiscs(UnityEngine.Vector3.left, UnityEngine.Vector3.right, 2, in_position, in_radius);
UnityEditor.Handles.color = in_sphereColor;
UnityEditor.Handles.SphereHandleCap(0, in_position, UnityEngine.Quaternion.identity, in_radius * 2.0f, UnityEngine.EventType.Repaint);
}
else
{
UnityEditor.Handles.color = wireColor;
DrawWireDiscs(UnityEngine.Vector3.left, UnityEngine.Vector3.right, 6, in_position, in_radius);
UnityEditor.Handles.color = in_sphereColor;
UnityEditor.Handles.DrawSolidDisc(in_position, UnityEngine.Vector3.up, in_radius);
}
}
private void DrawWireDiscs(UnityEngine.Vector3 in_startNormal, UnityEngine.Vector3 in_endNormal, uint in_nbDiscs,
UnityEngine.Vector3 in_position, float in_radius)
{
var f = 1.0f / in_nbDiscs;
for (var i = 0; i < in_nbDiscs; i++)
{
UnityEditor.Handles.DrawWireDisc(in_position, UnityEngine.Vector3.Slerp(in_startNormal, in_endNormal, f * i), in_radius);
}
var orthogonalVector = UnityEngine.Vector3.Cross(in_startNormal, in_endNormal);
//Handle edge case where vectors are parallel
if (orthogonalVector.magnitude == 0.0f)
{
orthogonalVector = UnityEngine.Vector3.Cross(UnityEngine.Vector3.Slerp(in_startNormal, in_endNormal, 0.5f), in_startNormal);
}
UnityEditor.Handles.DrawWireDisc(in_position, orthogonalVector, in_radius);
}
public static void PopulateMaxAttenuation()
{
UnityEditor.SceneView.RepaintAll();
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6800f9db7948df84a8915cb75d9a9418
@@ -0,0 +1,68 @@
using UnityEditor;
using UnityEngine;
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkAudioListener), true)]
public class AkAudioListenerInspector : UnityEditor.Editor
{
private UnityEditor.SerializedProperty m_isDefaultListener;
private AkAudioListener m_Listener;
private void OnEnable()
{
m_isDefaultListener = serializedObject.FindProperty("isDefaultListener");
m_Listener = target as AkAudioListener;
}
public override void OnInspectorGUI()
{
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUI.BeginChangeCheck();
UnityEditor.EditorGUILayout.PropertyField(m_isDefaultListener);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
m_Listener.bOverrideScalingFactor = UnityEditor.EditorGUILayout.Toggle("Override Attenuation Scaling Factor:", m_Listener.bOverrideScalingFactor);
if (m_Listener.bOverrideScalingFactor)
{
m_Listener.ScalingFactor = UnityEditor.EditorGUILayout.FloatField("Attenuation Scaling Factor", m_Listener.ScalingFactor);
}
}
if (UnityEditor.EditorGUI.EndChangeCheck())
{
if (m_Listener.ScalingFactor <= 0)
{
m_Listener.ScalingFactor = 0;
}
else
{
AkAudioListener selectedTarget = (AkAudioListener)target;
if (selectedTarget.gameObject && selectedTarget.gameObject.activeInHierarchy)
{
AkUnitySoundEngine.SetScalingFactor(m_Listener.gameObject, m_Listener.ScalingFactor);
}
}
UnityEditor.EditorUtility.SetDirty(serializedObject.targetObject);
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 8ce9156dd335763459df339712bdaeab
@@ -0,0 +1,96 @@
using AK.Wwise.Unity.Logging;
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkBank), true)]
public class AkBankInspector : AkBaseInspector
{
private readonly AkUnityEventHandlerInspector m_LoadBankEventHandlerInspector = new AkUnityEventHandlerInspector();
private readonly AkUnityEventHandlerInspector m_UnloadBankEventHandlerInspector = new AkUnityEventHandlerInspector();
private UnityEditor.SerializedProperty loadAsync;
private UnityEditor.SerializedProperty decode;
private UnityEditor.SerializedProperty saveDecoded;
private UnityEditor.SerializedProperty overrideLoadAsync;
private void OnEnable()
{
m_LoadBankEventHandlerInspector.Init(serializedObject, "triggerList", "Load On: ", false);
m_UnloadBankEventHandlerInspector.Init(serializedObject, "unloadTriggerList", "Unload On: ", false);
decode = serializedObject.FindProperty("decodeBank");
saveDecoded = serializedObject.FindProperty("saveDecodedBank");
loadAsync = serializedObject.FindProperty("loadAsynchronous");
overrideLoadAsync = serializedObject.FindProperty("overrideLoadSetting");
}
public override void OnChildInspectorGUI()
{
m_LoadBankEventHandlerInspector.OnGUI();
m_UnloadBankEventHandlerInspector.OnGUI();
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(overrideLoadAsync, new UnityEngine.GUIContent("Override Load Setting:"));
if (overrideLoadAsync.boolValue)
{
UnityEditor.EditorGUILayout.PropertyField(loadAsync, new UnityEngine.GUIContent("Load Bank Asynchronously:"));
}
}
#if !(AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES)
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEngine.GUIStyle wrapLabelStyle = new UnityEngine.GUIStyle(UnityEditor.EditorStyles.label)
{
wordWrap = true
};
UnityEngine.GUILayout.Label("Decode compressed data (DEPRECATED):", wrapLabelStyle);
decode.boolValue = UnityEditor.EditorGUILayout.ToggleLeft(UnityEngine.GUIContent.none, decode.boolValue);
if (!decode.boolValue)
{
return;
}
var oldSaveDecodedValue = saveDecoded.boolValue;
UnityEditor.EditorGUILayout.PropertyField(saveDecoded, new UnityEngine.GUIContent("Save decoded bank:"));
if (!oldSaveDecodedValue || saveDecoded.boolValue)
{
return;
}
var bank = target as AkBank;
var decodedBankPath = System.IO.Path.Combine(AkBasePathGetter.Get().DecodedBankFullPath, bank.data.Name + ".bnk");
try
{
System.IO.File.Delete(decodedBankPath);
}
catch (System.Exception e)
{
WwiseLogger.Log("Could not delete existing decoded SoundBank. Please delete it manually. " + e);
}
}
#endif
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 4f14ded5987a6254699b017455eaee21
@@ -0,0 +1,42 @@
#if UNITY_EDITOR
/*******************************************************************************
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 AkBaseInspector : UnityEditor.Editor
{
public abstract void OnChildInspectorGUI();
public override void OnInspectorGUI()
{
serializedObject.Update();
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
OnChildInspectorGUI();
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEngine.GUILayout.HorizontalScope("box"))
UnityEditor.EditorGUILayout.PropertyField(serializedObject.FindProperty("data"), new UnityEngine.GUIContent("Name: "));
if (serializedObject.ApplyModifiedProperties() && UnityEngine.GUI.changed)
{
UnityEditor.EditorUtility.SetDirty(serializedObject.targetObject);
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: eeb1eaae19f0b9541b4e02bf49015c94
@@ -0,0 +1,83 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkEnvironment), true)]
public class AkEnvironmentInspector : AkBaseInspector
{
private AkEnvironment m_AkEnvironment;
private UnityEditor.SerializedProperty m_excludeOthers;
private UnityEditor.SerializedProperty m_isDefault;
private UnityEditor.SerializedProperty m_priority;
private void OnEnable()
{
m_AkEnvironment = target as AkEnvironment;
m_priority = serializedObject.FindProperty("priority");
m_isDefault = serializedObject.FindProperty("isDefault");
m_excludeOthers = serializedObject.FindProperty("excludeOthers");
//We move and replace the game object to trigger the OnTriggerStay function
ShakeEnvironment();
}
public override void OnChildInspectorGUI()
{
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
m_priority.intValue = UnityEditor.EditorGUILayout.IntField("Priority: ", m_priority.intValue);
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
m_isDefault.boolValue = UnityEditor.EditorGUILayout.Toggle("Default: ", m_isDefault.boolValue);
if (m_isDefault.boolValue)
m_excludeOthers.boolValue = false;
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
m_excludeOthers.boolValue = UnityEditor.EditorGUILayout.Toggle("Exclude Others: ", m_excludeOthers.boolValue);
if (m_excludeOthers.boolValue)
m_isDefault.boolValue = false;
}
AkGameObjectInspector.RigidbodyCheck(m_AkEnvironment.gameObject);
}
public void ShakeEnvironment()
{
var temp = m_AkEnvironment.transform.position;
temp.x *= 1.0000001f;
m_AkEnvironment.transform.position = temp;
UnityEditor.EditorApplication.update += ReplaceEnvironment;
}
private void ReplaceEnvironment()
{
UnityEditor.EditorApplication.update -= ReplaceEnvironment;
if (m_AkEnvironment && m_AkEnvironment.transform)
{
var temp = m_AkEnvironment.transform.position;
temp.x /= 1.0000001f;
m_AkEnvironment.transform.position = temp;
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 96326b16df198a34e84879de643b9930
@@ -0,0 +1,214 @@
using UnityEngine;
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CustomEditor(typeof(AkEnvironmentPortal), true)]
public class AkEnvironmentPortalInspector : UnityEditor.Editor
{
private readonly int[] m_selectedIndex = new int[AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL];
private AkEnvironmentPortal m_envPortal;
private UnityEditor.SerializedProperty m_environments;
private UnityEditor.SerializedProperty m_axis;
private UnityEditor.SerializedProperty m_envList;
[UnityEditor.MenuItem("GameObject/Wwise/Environment Portal", false, 1)]
public static void CreatePortal()
{
var portal = new UnityEngine.GameObject("EnvironmentPortal");
UnityEditor.Undo.AddComponent<AkEnvironmentPortal>(portal);
portal.GetComponent<UnityEngine.Collider>().isTrigger = true;
UnityEditor.Selection.objects = new UnityEngine.Object[] { portal };
}
private void OnEnable()
{
m_envPortal = target as AkEnvironmentPortal;
m_environments = serializedObject.FindProperty("environments");
m_axis = serializedObject.FindProperty("axis");
m_envList = serializedObject.FindProperty("envList");
FindOverlappingEnvironments();
for (var i = 0; i < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; i++)
{
m_selectedIndex[i] = 0;
var list = m_envList.GetArrayElementAtIndex(i).FindPropertyRelative("list");
for (var j = 0; j < list.arraySize; ++j)
{
if (list.GetArrayElementAtIndex(j).objectReferenceValue == m_environments.GetArrayElementAtIndex(i).objectReferenceValue)
{
m_selectedIndex[i] = j;
break;
}
}
}
}
public override void OnInspectorGUI()
{
serializedObject.Update();
using (new UnityEngine.GUILayout.VerticalScope("box"))
{
for (var i = 0; i < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; i++)
{
var list = m_envList.GetArrayElementAtIndex(i).FindPropertyRelative("list");
var labels = new string[list.arraySize];
for (var j = 0; j < list.arraySize; j++)
{
var environment = list.GetArrayElementAtIndex(j).objectReferenceValue as AkEnvironment;
if (environment != null)
{
labels[j] = j + 1 + ". " + GetEnvironmentName(environment) + " (" + environment.name + ")";
}
else
{
list.DeleteArrayElementAtIndex(j);
}
}
var index = UnityEditor.EditorGUILayout.Popup("Environment #" + (i + 1), m_selectedIndex[i], labels);
m_environments.GetArrayElementAtIndex(i).objectReferenceValue = index < 0 || index >= list.arraySize ? null : list.GetArrayElementAtIndex(index).objectReferenceValue;
m_selectedIndex[i] = index;
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
var axisLabels = new[]{ "X", "Y", "Z" };
var axes = new[] { UnityEngine.Vector3.right, UnityEngine.Vector3.up, UnityEngine.Vector3.forward };
var index = 0;
for (var i = 0; i < 3; i++)
{
if (m_axis.vector3Value == axes[i])
{
index = i;
break;
}
}
var newIndex = UnityEditor.EditorGUILayout.Popup("Axis", index, axisLabels);
m_axis.vector3Value = axes[newIndex];
if (index != newIndex)
{
for (var i = 0; i < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; i++)
m_envList.GetArrayElementAtIndex(i).FindPropertyRelative("list").ClearArray();
FindOverlappingEnvironments();
}
}
serializedObject.ApplyModifiedProperties();
AkGameObjectInspector.RigidbodyCheck(m_envPortal.gameObject);
}
private string GetEnvironmentName(AkEnvironment in_env)
{
foreach (var wwu in AkWwiseProjectInfo.GetData().BusRoot)
{
var found = wwu.Find(in_env.data.Id);
if (found != null)
{
return found.Name;
}
}
return string.Empty;
}
public void FindOverlappingEnvironments()
{
var myCollider = m_envPortal.gameObject.GetComponent<UnityEngine.Collider>();
if (myCollider == null)
return;
#if UNITY_6000_0_OR_NEWER
var environments = FindObjectsByType<AkEnvironment>(FindObjectsSortMode.None);
#else
var environments = FindObjectsOfType<AkEnvironment>();
#endif
foreach (var environment in environments)
{
var otherCollider = environment.gameObject.GetComponent<UnityEngine.Collider>();
if (otherCollider == null)
continue;
if (myCollider.bounds.Intersects(otherCollider.bounds))
{
//if index == 0 => the environment is on the negative side of the portal(opposite to the direction of the chosen axis)
//if index == 1 => the environment is on the positive side of the portal(same direction as the chosen axis)
var index = UnityEngine.Vector3.Dot(m_envPortal.transform.rotation * m_axis.vector3Value,
environment.transform.position - m_envPortal.transform.position) >= 0 ? 1 : 0;
var list = m_envList.GetArrayElementAtIndex(index).FindPropertyRelative("list");
var isFound = false;
var count = list.arraySize;
for (var j = 0; j < count; j++)
{
if (list.GetArrayElementAtIndex(j).objectReferenceValue == environment)
{
isFound = true;
break;
}
}
if (!isFound)
{
list.InsertArrayElementAtIndex(count);
list.GetArrayElementAtIndex(count).objectReferenceValue = environment;
var otherList = m_envList.GetArrayElementAtIndex(++index % AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL).FindPropertyRelative("list");
for (var j = 0; j < otherList.arraySize; j++)
{
if (otherList.GetArrayElementAtIndex(j).objectReferenceValue == environment)
{
otherList.DeleteArrayElementAtIndex(j);
break;
}
}
}
}
else
{
for (var i = 0; i < AkEnvironmentPortal.MAX_ENVIRONMENTS_PER_PORTAL; i++)
{
var list = m_envList.GetArrayElementAtIndex(i).FindPropertyRelative("list");
for (var j = 0; j < list.arraySize; j++)
{
if (list.GetArrayElementAtIndex(j).objectReferenceValue == environment)
{
list.DeleteArrayElementAtIndex(j);
break;
}
}
}
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 89ee80c35ad4f6f4e81f0d83074bc635
@@ -0,0 +1,325 @@
using AK.Wwise.Unity.Logging;
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkEvent), true)]
public class AkEventInspector : AkBaseInspector
{
private readonly AkUnityEventHandlerInspector m_UnityEventHandlerInspector = new AkUnityEventHandlerInspector();
private UnityEditor.SerializedProperty actionOnEventType;
private UnityEditor.SerializedProperty callbackData;
private UnityEditor.SerializedProperty curveInterpolation;
private UnityEditor.SerializedProperty enableActionOnEvent;
private UnityEditor.SerializedProperty transitionDuration;
private UnityEditor.SerializedProperty useCallbacks;
private UnityEditor.SerializedProperty stopSoundOnDestroy;
public void OnEnable()
{
m_UnityEventHandlerInspector.Init(serializedObject);
enableActionOnEvent = serializedObject.FindProperty("enableActionOnEvent");
actionOnEventType = serializedObject.FindProperty("actionOnEventType");
curveInterpolation = serializedObject.FindProperty("curveInterpolation");
transitionDuration = serializedObject.FindProperty("transitionDuration");
useCallbacks = serializedObject.FindProperty("useCallbacks");
callbackData = serializedObject.FindProperty("Callbacks");
stopSoundOnDestroy = serializedObject.FindProperty("stopSoundOnDestroy");
AkEditorEventPlayer.RefreshGUI += Repaint;
}
public void OnDisable()
{
AkEditorEventPlayer.RefreshGUI -= Repaint;
}
private void DisplayActionOnEvent()
{
if (useCallbacks.boolValue)
return;
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(enableActionOnEvent, new UnityEngine.GUIContent("Action On Event: "));
if (!enableActionOnEvent.boolValue)
return;
UnityEditor.EditorGUILayout.PropertyField(actionOnEventType, new UnityEngine.GUIContent("Action On EventType: "));
UnityEditor.EditorGUILayout.PropertyField(curveInterpolation, new UnityEngine.GUIContent("Curve Interpolation: "));
UnityEditor.EditorGUILayout.Slider(transitionDuration, 0.0f, 60.0f, new UnityEngine.GUIContent("Fade Time (secs): "));
}
}
private void DisplayCallbackInformation()
{
if (enableActionOnEvent.boolValue)
return;
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(useCallbacks, new UnityEngine.GUIContent("Use Callback: "));
if (useCallbacks.boolValue)
{
var emptyContent = new UnityEngine.GUIContent("");
// ensure that there is always at least one entry since we are "using" callbacks
if (callbackData.arraySize == 0)
callbackData.arraySize = 1;
const float callbackSpacerWidth = 4;
const float removeButtonWidth = 20;
var rect = UnityEditor.EditorGUILayout.GetControlRect();
var callbackFieldWidth = (rect.width - removeButtonWidth) / 3;
rect.width = callbackFieldWidth - callbackSpacerWidth;
UnityEngine.GUI.Label(rect, "Game Object");
rect.x += callbackFieldWidth;
UnityEngine.GUI.Label(rect, "Callback Function");
rect.x += callbackFieldWidth;
UnityEngine.GUI.Label(rect, "Callback Flags");
for (var i = 0; i < callbackData.arraySize; ++i)
{
var data = callbackData.GetArrayElementAtIndex(i);
rect = UnityEditor.EditorGUILayout.GetControlRect();
rect.width = callbackFieldWidth - callbackSpacerWidth;
UnityEditor.EditorGUI.PropertyField(rect, data.FindPropertyRelative("GameObject"), emptyContent);
rect.x += callbackFieldWidth;
UnityEditor.EditorGUI.PropertyField(rect, data.FindPropertyRelative("FunctionName"), emptyContent);
rect.x += callbackFieldWidth;
UnityEditor.EditorGUI.PropertyField(rect, data.FindPropertyRelative("Flags"), emptyContent);
rect.x += callbackFieldWidth;
rect.width = removeButtonWidth;
if (UnityEngine.GUI.Button(rect, "X"))
callbackData.DeleteArrayElementAtIndex(i);
}
if (UnityEngine.GUI.Button(UnityEditor.EditorGUILayout.GetControlRect(), "Add"))
{
var i = callbackData.arraySize++;
var data = callbackData.GetArrayElementAtIndex(i);
data.FindPropertyRelative("GameObject").objectReferenceValue = null;
data.FindPropertyRelative("FunctionName").stringValue = string.Empty;
data.FindPropertyRelative("Flags.value").intValue = 0;
}
}
else if (callbackData.arraySize == 1)
{
var data = callbackData.GetArrayElementAtIndex(0);
if (data.FindPropertyRelative("GameObject").objectReferenceValue == null)
if (string.IsNullOrEmpty(data.FindPropertyRelative("FunctionName").stringValue))
if (data.FindPropertyRelative("Flags.value").intValue == 0)
callbackData.arraySize = 0;
}
}
}
private void DisplayStopSoundOnDestroy()
{
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(stopSoundOnDestroy, new UnityEngine.GUIContent("Stop Sound On Destroy: "));
}
}
public override void OnChildInspectorGUI()
{
m_UnityEventHandlerInspector.OnGUI();
DisplayActionOnEvent();
DisplayCallbackInformation();
DisplayStopSoundOnDestroy();
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
if (targets.Length == 1)
{
PlayOrStopEvent();
}
else
{
var playingEventsSelected = false;
var stoppedEventsSelected = false;
for (var i = 0; i < targets.Length; ++i)
{
var akEventTarget = targets[i] as AkEvent;
if (akEventTarget != null)
{
if (AkEditorEventPlayer.IsEventPlaying(akEventTarget))
{
playingEventsSelected = true;
}
else
{
stoppedEventsSelected = true;
}
if (playingEventsSelected && stoppedEventsSelected)
{
break;
}
}
}
if (stoppedEventsSelected &&
UnityEngine.GUILayout.Button("Play Multiple"))
{
for (var i = 0; i < targets.Length; ++i)
{
var akEventTarget = targets[i] as AkEvent;
if (akEventTarget != null)
{
AkEditorEventPlayer.PlayEvent(akEventTarget);
}
}
}
if (playingEventsSelected &&
UnityEngine.GUILayout.Button("Stop Multiple"))
{
for (var i = 0; i < targets.Length; ++i)
{
var akEventTarget = targets[i] as AkEvent;
if (akEventTarget != null)
{
AkEditorEventPlayer.StopEvent(akEventTarget);
}
}
}
}
if (UnityEngine.GUILayout.Button("Stop All"))
{
UnityEngine.GUIUtility.hotControl = 0;
AkEditorEventPlayer.StopAll();
}
}
}
public void PlayEvent()
{
AkEditorEventPlayer.PlayEvent((AkEvent)target);
}
public void StopEvent()
{
AkEditorEventPlayer.StopEvent((AkEvent)target);
}
private void PlayOrStopEvent()
{
var akEvent = (AkEvent)target;
var eventPlaying = AkEditorEventPlayer.IsEventPlaying(akEvent);
if (eventPlaying)
{
if (UnityEngine.GUILayout.Button("Stop"))
{
UnityEngine.GUIUtility.hotControl = 0;
StopEvent();
}
}
else
{
if (UnityEngine.GUILayout.Button("Play"))
{
UnityEngine.GUIUtility.hotControl = 0;
PlayEvent();
}
}
}
private static class AkEditorEventPlayer
{
private static readonly System.Collections.Generic.List<AkEvent> akEvents = new System.Collections.Generic.List<AkEvent>();
public static event System.Action RefreshGUI;
private static void CallbackHandler(object in_cookie, AkCallbackType in_type, AkCallbackInfo in_info)
{
if (in_type == AkCallbackType.AK_EndOfEvent)
{
akEvents.Remove(in_cookie as AkEvent);
var refreshGUI = RefreshGUI;
if (refreshGUI != null)
{
refreshGUI.Invoke();
}
}
}
public static void PlayEvent(AkEvent akEvent)
{
if (!AkUnitySoundEngine.IsInitialized())
{
WwiseLogger.Warning("Sound Engine is not initialized. No sound will be heard.");
return;
}
if (!AkSoundEngineController.Instance.EditorListenerIsInitialized() && !UnityEditor.EditorApplication.isPlaying)
{
WwiseLogger.Warning("Editor Listener isn't initialized. No sound will be heard.");
return;
}
if (akEvents.Contains(akEvent))
{
return;
}
var playingID = akEvent.data.Post(akEvent.gameObject, (uint)AkCallbackType.AK_EndOfEvent, CallbackHandler, akEvent);
if (playingID != AkUnitySoundEngine.AK_INVALID_PLAYING_ID)
{
akEvents.Add(akEvent);
// In the case where objects are being placed in edit mode and then previewed, their positions won't yet be updated so we ensure they're updated here.
AkUnitySoundEngine.SetObjectPosition(akEvent.gameObject, akEvent.transform);
}
}
public static void StopEvent(AkEvent akEvent)
{
if (akEvents.Remove(akEvent))
{
akEvent.data.Stop(akEvent.gameObject);
}
}
public static bool IsEventPlaying(AkEvent akEvent)
{
return akEvents.Contains(akEvent);
}
public static void StopAll()
{
akEvents.Clear();
AkUnitySoundEngine.StopAll();
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0de2d1c16ee6d6841b0facd6d151b37c
@@ -0,0 +1,109 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CustomPropertyDrawer(typeof(AkGameObjListenerList))]
internal class AkGameObjListenerListDrawer : UnityEditor.PropertyDrawer
{
private const int listenerSpacerWidth = 4;
private const int removeButtonWidth = 20;
public override float GetPropertyHeight(UnityEditor.SerializedProperty property, UnityEngine.GUIContent label)
{
var height = (UnityEditor.EditorGUIUtility.singleLineHeight + UnityEditor.EditorGUIUtility.standardVerticalSpacing) *
2;
var listenerListProperty = property.FindPropertyRelative("initialListenerList");
if (listenerListProperty != null && listenerListProperty.isArray)
{
height += (UnityEditor.EditorGUIUtility.singleLineHeight + UnityEditor.EditorGUIUtility.standardVerticalSpacing) *
listenerListProperty.arraySize + UnityEditor.EditorGUIUtility.standardVerticalSpacing;
}
return height;
}
public override void OnGUI(UnityEngine.Rect position, UnityEditor.SerializedProperty property,
UnityEngine.GUIContent label)
{
// Using BeginProperty / EndProperty on the parent property means that
// prefab override logic works on the entire property.
UnityEditor.EditorGUI.BeginProperty(position, label, property);
var initialRect = position;
position = UnityEditor.EditorGUI.PrefixLabel(position,
UnityEngine.GUIUtility.GetControlID(UnityEngine.FocusType.Passive),
new UnityEngine.GUIContent("Use Default Listeners:"));
position.height = UnityEditor.EditorGUIUtility.singleLineHeight +
UnityEditor.EditorGUIUtility.standardVerticalSpacing;
var useDefaultListenersProperty = property.FindPropertyRelative("useDefaultListeners");
useDefaultListenersProperty.boolValue = UnityEngine.GUI.Toggle(position, useDefaultListenersProperty.boolValue, "");
var listenerListProperty = property.FindPropertyRelative("initialListenerList");
if (listenerListProperty.isArray)
{
position.height = UnityEditor.EditorGUIUtility.singleLineHeight +
UnityEditor.EditorGUIUtility.standardVerticalSpacing;
for (var ii = 0; ii < listenerListProperty.arraySize; ++ii)
{
var listenerFieldWidth = initialRect.width - removeButtonWidth;
position.y += UnityEditor.EditorGUIUtility.singleLineHeight + UnityEditor.EditorGUIUtility.standardVerticalSpacing;
position.x = initialRect.x;
position.width = listenerFieldWidth - listenerSpacerWidth;
var listenerProperty = listenerListProperty.GetArrayElementAtIndex(ii);
UnityEditor.EditorGUI.PropertyField(position, listenerProperty, new UnityEngine.GUIContent("Listener " + ii));
position.x = initialRect.x + listenerFieldWidth;
position.width = removeButtonWidth;
if (UnityEngine.GUI.Button(position, "X"))
{
UnityEngine.GUIUtility.keyboardControl = 0;
UnityEngine.GUIUtility.hotControl = 0;
listenerProperty.objectReferenceValue = null;
listenerListProperty.DeleteArrayElementAtIndex(ii);
--ii;
}
}
position.x = initialRect.x;
position.width = initialRect.width;
position.y += UnityEditor.EditorGUIUtility.singleLineHeight + UnityEditor.EditorGUIUtility.standardVerticalSpacing +
UnityEditor.EditorGUIUtility.standardVerticalSpacing;
if (UnityEngine.GUI.Button(position, "Add Listener"))
{
UnityEngine.GUIUtility.keyboardControl = 0;
UnityEngine.GUIUtility.hotControl = 0;
var lastPosition = listenerListProperty.arraySize;
listenerListProperty.arraySize = lastPosition + 1;
// Avoid copying the previous last array element into the newly added last position
var listenerProperty = listenerListProperty.GetArrayElementAtIndex(lastPosition);
listenerProperty.objectReferenceValue = null;
}
}
UnityEditor.EditorGUI.EndProperty();
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 0fbc29ab97cf9cb489c967a85b51d577
@@ -0,0 +1,220 @@
#if UNITY_EDITOR
/*******************************************************************************
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 DefaultHandles
{
public static bool Hidden
{
get
{
var type = typeof(UnityEditor.Tools);
var field = type.GetField("s_Hidden",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
return (bool) field.GetValue(null);
}
set
{
var type = typeof(UnityEditor.Tools);
var field = type.GetField("s_Hidden",
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
field.SetValue(null, value);
}
}
}
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkGameObj), true)]
public class AkGameObjectInspector : UnityEditor.Editor
{
private bool hideDefaultHandle;
private UnityEditor.SerializedProperty listeners;
private AkGameObj m_AkGameObject;
private UnityEditor.SerializedProperty usePositionOffsetData;
private void OnEnable()
{
m_AkGameObject = target as AkGameObj;
listeners = serializedObject.FindProperty("m_listeners");
usePositionOffsetData = serializedObject.FindProperty("usePositionOffsetData");
DefaultHandles.Hidden = hideDefaultHandle;
}
private void OnDisable()
{
DefaultHandles.Hidden = false;
}
public override void OnInspectorGUI()
{
var positionOffsetData = m_AkGameObject.m_positionOffsetData;
var positionOffset = UnityEngine.Vector3.zero;
UnityEditor.EditorGUI.BeginChangeCheck();
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(usePositionOffsetData, new UnityEngine.GUIContent("Apply Position Offset:"));
if (usePositionOffsetData.boolValue)
{
positionOffset = UnityEditor.EditorGUILayout.Vector3Field("Position Offset", positionOffsetData.positionOffset);
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
if (hideDefaultHandle)
{
if (UnityEngine.GUILayout.Button("Show Main Transform"))
{
hideDefaultHandle = false;
DefaultHandles.Hidden = hideDefaultHandle;
}
}
else if (UnityEngine.GUILayout.Button("Hide Main Transform"))
{
hideDefaultHandle = true;
DefaultHandles.Hidden = hideDefaultHandle;
}
}
else if (hideDefaultHandle)
{
hideDefaultHandle = false;
DefaultHandles.Hidden = hideDefaultHandle;
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
var isEnvironmentAware = m_AkGameObject.isEnvironmentAware;
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
isEnvironmentAware = UnityEditor.EditorGUILayout.Toggle("Environment Aware:", isEnvironmentAware);
}
if (m_AkGameObject.gameObject.GetComponent<AkRoomAwareObject>() == null)
{
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.LabelField("Room Aware: ", "");
if (UnityEngine.GUILayout.Button("Add AkRoomAwareObject"))
UnityEditor.Undo.AddComponent<AkRoomAwareObject>(m_AkGameObject.gameObject);
}
}
if (UnityEditor.EditorGUI.EndChangeCheck())
{
UnityEditor.Undo.RecordObject(target, "AkGameObj Parameter Change");
m_AkGameObject.m_positionOffsetData = positionOffsetData;
var posOffsetDataProperty = serializedObject.FindProperty("m_positionOffsetData");
var KeepMeProperty = posOffsetDataProperty.FindPropertyRelative("KeepMe");
KeepMeProperty.boolValue = (positionOffsetData != null);
if (positionOffsetData != null)
{
var posOffsetProperty = posOffsetDataProperty.FindPropertyRelative("positionOffset");
posOffsetProperty.vector3Value = positionOffset;
}
serializedObject.ApplyModifiedProperties();
m_AkGameObject.isEnvironmentAware = isEnvironmentAware;
}
if (isEnvironmentAware)
{
RigidbodyCheck(m_AkGameObject.gameObject);
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEditor.EditorGUI.BeginChangeCheck();
m_AkGameObject.ScalingFactor = UnityEditor.EditorGUILayout.FloatField("Attenuation Scaling Factor", m_AkGameObject.ScalingFactor);
if (UnityEditor.EditorGUI.EndChangeCheck())
{
if (m_AkGameObject.ScalingFactor <= 0)
{
m_AkGameObject.ScalingFactor = 0;
}
else
{
if (m_AkGameObject.gameObject.activeInHierarchy)
{
AkUnitySoundEngine.SetScalingFactor(m_AkGameObject.gameObject, m_AkGameObject.ScalingFactor);
}
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUI.BeginChangeCheck();
UnityEditor.EditorGUILayout.PropertyField(listeners);
if (UnityEditor.EditorGUI.EndChangeCheck())
{
serializedObject.ApplyModifiedProperties();
}
}
}
public static void RigidbodyCheck(UnityEngine.GameObject gameObject)
{
if (AkWwiseEditorSettings.Instance.ShowSpatialAudioWarningMsg && gameObject.GetComponent<UnityEngine.Rigidbody>() == null)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"Interactions between AkGameObj and AkEnvironment require a Rigidbody component on the object or the environment.",
UnityEditor.MessageType.Warning);
if (UnityEngine.GUILayout.Button("Add Rigidbody"))
{
var rb = UnityEditor.Undo.AddComponent<UnityEngine.Rigidbody>(gameObject);
rb.useGravity = false;
rb.isKinematic = true;
}
}
}
}
private void OnSceneGUI()
{
if (m_AkGameObject.m_positionOffsetData == null)
{
return;
}
UnityEditor.EditorGUI.BeginChangeCheck();
// Transform local offset to world coordinate
var pos = m_AkGameObject.transform.TransformPoint(m_AkGameObject.m_positionOffsetData.positionOffset);
// Get new handle position
pos = UnityEditor.Handles.PositionHandle(pos, UnityEngine.Quaternion.identity);
if (UnityEditor.EditorGUI.EndChangeCheck())
{
UnityEditor.Undo.RecordObject(target, "Position Offset Change");
// Transform world offset to local coordinate
m_AkGameObject.m_positionOffsetData.positionOffset = m_AkGameObject.transform.InverseTransformPoint(pos);
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1c9d43b9fb1745f46aedd34153ebaed0
@@ -0,0 +1,216 @@
#if UNITY_EDITOR
/*******************************************************************************
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;
[UnityEditor.InitializeOnLoad]
public class AkPortalManager
{
private static AkPortalManager s_portalManager;
public System.Collections.Generic.List<AkEnvironment> EnvironmentList =
new System.Collections.Generic.List<AkEnvironment>();
public System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<AkEnvironment>>[]
IntersectingEnvironments =
{
//All environments on the negative side of each portal(opposite to the direction of the chosen axis)
new System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<AkEnvironment>>(),
//All environments on the positive side of each portal(same direction as the chosen axis)
new System.Collections.Generic.Dictionary<int, System.Collections.Generic.List<AkEnvironment>>()
};
private float m_timeStamp = UnityEngine.Time.realtimeSinceStartup;
public System.Collections.Generic.List<AkEnvironmentPortal> PortalList =
new System.Collections.Generic.List<AkEnvironmentPortal>();
static AkPortalManager()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
//This constructor is called before any game object is created when there is a compilation which makes the 'FindObjectsOfType' function return null.
//So we register the init function to be called at hte first update.
UnityEditor.EditorApplication.update += Init;
}
public static void Init()
{
//Do nothing if Manager exists
if (s_portalManager == null)
{
s_portalManager = new AkPortalManager();
s_portalManager.Populate();
//Register the update function to be called at each frame
UnityEditor.EditorApplication.update += s_portalManager.UpdateEnvironments;
}
//Unregister in case we were registered
UnityEditor.EditorApplication.update -= Init;
}
public static AkPortalManager GetManager()
{
return s_portalManager;
}
public void Populate()
{
//Add all environments in the scene to the environment list
#if UNITY_6000_0_OR_NEWER
var akEnv = Object.FindObjectsByType<AkEnvironment>(FindObjectsSortMode.None);
#else
var akEnv = Object.FindObjectsOfType<AkEnvironment>();
#endif
s_portalManager.EnvironmentList.Clear();
s_portalManager.EnvironmentList.AddRange(akEnv);
//Add all portals in the scene to the portal list
#if UNITY_6000_0_OR_NEWER
var akPortals = Object.FindObjectsByType<AkEnvironmentPortal>(FindObjectsSortMode.None);
#else
var akPortals = Object.FindObjectsOfType<AkEnvironmentPortal>();
#endif
s_portalManager.PortalList.Clear();
s_portalManager.PortalList.AddRange(akPortals);
//check for portal-environment intersections and populate the IntersectingEnvironments dictionary
for (var i = 0; i < s_portalManager.PortalList.Count; i++)
s_portalManager.UpdatePortal(s_portalManager.PortalList[i]);
}
public void UpdatePortal(AkEnvironmentPortal in_portal)
{
var envList = new System.Collections.Generic.List<AkEnvironment>[2];
for (var i = 0; i < 2; i++)
{
if (!IntersectingEnvironments[i].TryGetValue(in_portal.GetInstanceID(), out envList[i]))
{
envList[i] = new System.Collections.Generic.List<AkEnvironment>();
IntersectingEnvironments[i][in_portal.GetInstanceID()] = envList[i];
}
else
envList[i].Clear();
}
//We check if a portal intersects any environment
//Iterate in reverse order for safe removal form list while iterating
for (var i = EnvironmentList.Count - 1; i >= 0; i--)
{
if (EnvironmentList[i] != null)
{
//if there is an intersection
if (in_portal.GetComponent<UnityEngine.Collider>().bounds
.Intersects(EnvironmentList[i].GetComponent<UnityEngine.Collider>().bounds))
{
if (UnityEngine.Vector3.Dot(in_portal.transform.rotation * in_portal.axis,
EnvironmentList[i].transform.position - in_portal.transform.position) >= 0)
envList[1].Add(EnvironmentList[i]);
else
envList[0].Add(EnvironmentList[i]);
}
}
else
EnvironmentList.RemoveAt(i);
}
}
private void UpdateEnvironment(AkEnvironment in_env)
{
for (var i = PortalList.Count - 1; i >= 0; i--) //Iterate in reverse order for safe removal form list while iterating
{
if (PortalList[i] != null)
{
if (in_env.GetComponent<UnityEngine.Collider>().bounds
.Intersects(PortalList[i].GetComponent<UnityEngine.Collider>().bounds))
{
System.Collections.Generic.List<AkEnvironment> envList = null;
//Get index of the list that should contain this environment
//Index = 0 means that the enviroment is on the negative side of the portal (opposite to the direction of the chosen axis)
//Index = 1 means that the enviroment is on the positive side of the portal (same direction as the chosen axis)
var index = UnityEngine.Vector3.Dot(PortalList[i].transform.rotation * PortalList[i].axis,
in_env.transform.position - PortalList[i].transform.position) >= 0
? 1
: 0;
if (!IntersectingEnvironments[index].TryGetValue(PortalList[i].GetInstanceID(), out envList))
{
envList = new System.Collections.Generic.List<AkEnvironment>();
envList.Add(in_env);
IntersectingEnvironments[index][PortalList[i].GetInstanceID()] = envList;
}
else if (!envList.Contains(in_env))
envList.Add(in_env);
}
}
else
PortalList.RemoveAt(i);
}
}
public void UpdateEnvironments()
{
//Timer is reset when starting play mode and when coming back to editor mode
if (UnityEngine.Time.realtimeSinceStartup < m_timeStamp)
{
m_timeStamp = UnityEngine.Time.realtimeSinceStartup;
//The PortalManager object doesn't get destroyed but all game objects in our lists become null
//So we populate
Populate();
return;
}
//The update is done once every second
if (UnityEngine.Time.realtimeSinceStartup - m_timeStamp < 1.0f)
return;
m_timeStamp = UnityEngine.Time.realtimeSinceStartup;
var portals = UnityEditor.Selection.GetFiltered(typeof(AkEnvironmentPortal), UnityEditor.SelectionMode.Unfiltered);
if (portals != null)
{
for (var i = 0; i < portals.Length; i++)
{
if (!PortalList.Contains((AkEnvironmentPortal) portals[i]))
PortalList.Add((AkEnvironmentPortal) portals[i]);
UpdatePortal((AkEnvironmentPortal) portals[i]);
}
}
var envs = UnityEditor.Selection.GetFiltered(typeof(AkEnvironment), UnityEditor.SelectionMode.Unfiltered);
if (envs != null)
{
for (var i = 0; i < envs.Length; i++)
{
if (!EnvironmentList.Contains((AkEnvironment) envs[i]))
EnvironmentList.Add((AkEnvironment) envs[i]);
UpdateEnvironment((AkEnvironment) envs[i]);
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 60b0f9687d4d90043ae39382594ebc52
@@ -0,0 +1,75 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CustomEditor(typeof(AkRadialEmitter), true)]
public class AkRadialEmitterInspector : UnityEditor.Editor
{
private AkRadialEmitter m_AkRadialEmitter;
private UnityEditor.SerializedProperty outerRadius;
private UnityEditor.SerializedProperty innerRadius;
private void OnEnable()
{
m_AkRadialEmitter = target as AkRadialEmitter;
outerRadius = serializedObject.FindProperty("outerRadius");
innerRadius = serializedObject.FindProperty("innerRadius");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
if (m_AkRadialEmitter.outerRadius < 0.0f)
m_AkRadialEmitter.outerRadius = 0.0f;
if (m_AkRadialEmitter.innerRadius < 0.0f)
m_AkRadialEmitter.innerRadius = 0.0f;
if (m_AkRadialEmitter.innerRadius > m_AkRadialEmitter.outerRadius)
m_AkRadialEmitter.innerRadius = m_AkRadialEmitter.outerRadius;
UnityEditor.EditorGUILayout.PropertyField(outerRadius);
UnityEditor.EditorGUILayout.PropertyField(innerRadius);
EventCheck(m_AkRadialEmitter.gameObject);
serializedObject.ApplyModifiedProperties();
}
public static void EventCheck(UnityEngine.GameObject gameObject)
{
if (AkWwiseEditorSettings.Instance.ShowSpatialAudioWarningMsg && gameObject.GetComponent<AkEvent>() == null)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"Radial emitters are expected to emit sound. Add an AkEvent or an AkAmbient component to this game object.",
UnityEditor.MessageType.Warning);
if (UnityEngine.GUILayout.Button("Add AkEvent"))
UnityEditor.Undo.AddComponent<AkEvent>(gameObject);
if (UnityEngine.GUILayout.Button("Add AkAmbient"))
UnityEditor.Undo.AddComponent<AkAmbient>(gameObject);
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1fbe197aa6aa1af45b2a6cd5910de6ff
@@ -0,0 +1,78 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CustomEditor(typeof(AkRoomAwareObject), true)]
public class AkRoomAwareObjectInspector : UnityEditor.Editor
{
private bool hideDefaultHandle;
private UnityEditor.SerializedProperty listeners;
private AkRoomAwareObject m_AkRoomAwareObject;
private void OnEnable()
{
m_AkRoomAwareObject = target as AkRoomAwareObject;
}
public override void OnInspectorGUI()
{
RigidbodyCheck(m_AkRoomAwareObject.gameObject);
ColliderCheck(m_AkRoomAwareObject.gameObject);
}
public static void ColliderCheck(UnityEngine.GameObject gameObject)
{
if (AkWwiseEditorSettings.Instance.ShowSpatialAudioWarningMsg)
{
var collider = gameObject.GetComponent<UnityEngine.Collider>();
if (collider == null || !collider.enabled)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"Interactions between AkRoomAwareObject and AkRoom require a Collider component on the object.",
UnityEditor.MessageType.Error);
}
}
}
}
public static void RigidbodyCheck(UnityEngine.GameObject gameObject)
{
if (AkWwiseEditorSettings.Instance.ShowSpatialAudioWarningMsg && gameObject.GetComponent<UnityEngine.Rigidbody>() == null)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"Interactions between AkRoomAwareObject and AkRoom require a Rigidbody component on the object or the room.",
UnityEditor.MessageType.Warning);
if (UnityEngine.GUILayout.Button("Add Rigidbody"))
{
var rb = UnityEditor.Undo.AddComponent<UnityEngine.Rigidbody>(gameObject);
rb.useGravity = false;
rb.isKinematic = true;
}
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: bf09946363d6f1746be03843cdd1e73e
@@ -0,0 +1,129 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CustomEditor(typeof(AkRoom), true)]
public class AkRoomInspector : UnityEditor.Editor
{
private readonly AkUnityEventHandlerInspector m_PostEventHandlerInspector = new AkUnityEventHandlerInspector();
private AkRoom m_AkRoom;
private UnityEditor.SerializedProperty priority;
private UnityEditor.SerializedProperty reverbAuxBus;
private UnityEditor.SerializedProperty reverbLevel;
private UnityEditor.SerializedProperty transmissionLoss;
private UnityEditor.SerializedProperty distanceBehavior;
private UnityEditor.SerializedProperty roomToneEvent;
private UnityEditor.SerializedProperty roomToneAuxSend;
private UnityEditor.SerializedProperty isStatic;
private void OnEnable()
{
m_PostEventHandlerInspector.Init(serializedObject, "triggerList", "Trigger On: ", false);
m_AkRoom = target as AkRoom;
reverbAuxBus = serializedObject.FindProperty("reverbAuxBus");
reverbLevel = serializedObject.FindProperty("reverbLevel");
transmissionLoss = serializedObject.FindProperty("transmissionLoss");
distanceBehavior = serializedObject.FindProperty("distanceBehavior");
priority = serializedObject.FindProperty("priority");
roomToneEvent = serializedObject.FindProperty("roomToneEvent");
roomToneAuxSend = serializedObject.FindProperty("roomToneAuxSend");
isStatic = serializedObject.FindProperty("isStatic");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
UnityEditor.EditorGUILayout.PropertyField(isStatic);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(reverbAuxBus);
UnityEditor.EditorGUILayout.PropertyField(reverbLevel);
UnityEditor.EditorGUILayout.PropertyField(transmissionLoss);
UnityEditor.EditorGUILayout.PropertyField(distanceBehavior);
UnityEditor.EditorGUILayout.PropertyField(priority);
WetTransmissionCheck(m_AkRoom.gameObject);
}
UnityEditor.EditorGUILayout.LabelField("Room Tone", UnityEditor.EditorStyles.boldLabel);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
m_PostEventHandlerInspector.OnGUI();
UnityEditor.EditorGUILayout.PropertyField(roomToneEvent);
UnityEditor.EditorGUILayout.PropertyField(roomToneAuxSend);
TriggerCheck(m_AkRoom);
}
AkRoomAwareObjectInspector.RigidbodyCheck(m_AkRoom.gameObject);
serializedObject.ApplyModifiedProperties();
}
public static void WetTransmissionCheck(UnityEngine.GameObject gameObject)
{
if (AkWwiseEditorSettings.Instance.ShowSpatialAudioWarningMsg &&
gameObject.GetComponent<AkSurfaceReflector>() == null &&
gameObject.GetComponent<UnityEngine.Mesh>() == null)
{
// wet transmission supports box, sphere, capsule and mesh colliders
bool bSupported = false;
if (gameObject.GetComponent<UnityEngine.BoxCollider>() != null ||
gameObject.GetComponent<UnityEngine.SphereCollider>() != null ||
gameObject.GetComponent<UnityEngine.CapsuleCollider>() != null ||
gameObject.GetComponent<UnityEngine.MeshCollider>() != null ||
(gameObject.GetComponent<AkSurfaceReflector>() != null && gameObject.GetComponent<AkSurfaceReflector>().enabled))
{
bSupported = true;
}
if (bSupported == false)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"Associating a geometry with this room for wet transmission is currently only supported with box, sphere, capsule and mesh colliders, or if the game object also has an enabled AkSurfaceReflector component.",
UnityEditor.MessageType.Warning);
}
}
}
}
public static void TriggerCheck(AkRoom room)
{
if (room.triggerList.Contains(AkTriggerHandler.DESTROY_TRIGGER_ID) ||
room.triggerList.Contains(AkTriggerHandler.ON_DISABLE_TRIGGER_ID))
{
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"Room tones will only be posted on active and enabled gameobjects; it is not possible to post room tones on disable and on destroy.",
UnityEditor.MessageType.Warning);
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1f789937f5310a54886157807c75c61e
@@ -0,0 +1,102 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkRoomPortal), true)]
public class AkRoomPortalInspector : UnityEditor.Editor
{
private UnityEditor.SerializedProperty initialState;
private UnityEditor.SerializedProperty rooms;
private UnityEditor.SerializedProperty isStatic;
private readonly AkUnityEventHandlerInspector m_ClosePortalEventHandlerInspector = new AkUnityEventHandlerInspector();
private readonly AkUnityEventHandlerInspector m_OpenPortalEventHandlerInspector = new AkUnityEventHandlerInspector();
private AkRoomPortal m_roomPortal;
[UnityEditor.MenuItem("GameObject/Wwise/Room Portal", false, 1)]
public static void CreatePortal()
{
var portal = new UnityEngine.GameObject("RoomPortal");
UnityEditor.Undo.AddComponent<AkRoomPortal>(portal);
portal.GetComponent<UnityEngine.Collider>().isTrigger = true;
UnityEditor.Selection.objects = new UnityEngine.Object[] { portal };
}
private void OnEnable()
{
initialState = serializedObject.FindProperty("initialState");
rooms = serializedObject.FindProperty("rooms");
isStatic = serializedObject.FindProperty("isStatic");
m_OpenPortalEventHandlerInspector.Init(serializedObject, "triggerList", "Open On: ", false);
m_ClosePortalEventHandlerInspector.Init(serializedObject, "closePortalTriggerList", "Close On: ", false);
m_roomPortal = target as AkRoomPortal;
}
public override void OnInspectorGUI()
{
serializedObject.Update();
UnityEditor.EditorGUILayout.PropertyField(isStatic);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(initialState);
m_OpenPortalEventHandlerInspector.OnGUI();
m_ClosePortalEventHandlerInspector.OnGUI();
}
m_roomPortal.UpdateRooms();
var labels = new[] { "Back Room", "Front Room" };
var tooltips = new[] { "The highest priority, active and enabled AkRoom component overlapping the back surface of this AkRoomPortal.",
"The highest priority, active and enabled AkRoom component overlapping the front surface of this AkRoomPortal." };
var wasEnabled = UnityEngine.GUI.enabled;
UnityEngine.GUI.enabled = false;
for (var i = 0; i < AkRoomPortal.MAX_ROOMS_PER_PORTAL; i++)
UnityEditor.EditorGUILayout.PropertyField(rooms.GetArrayElementAtIndex(i), new UnityEngine.GUIContent(labels[i], tooltips[i]), true);
UnityEngine.GUI.enabled = wasEnabled;
RoomCheck(m_roomPortal);
serializedObject.ApplyModifiedProperties();
}
public static void RoomCheck(AkRoomPortal portal)
{
if (AkWwiseEditorSettings.Instance.ShowSpatialAudioWarningMsg)
{
if (!portal.IsValid)
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
UnityEditor.EditorGUILayout.HelpBox(
"Portal placement is invalid. It will not be set in the Spatial Audio engine. The front and back Rooms of the Portal cannot be the same or have a ReverbZone-parent relationship.",
UnityEditor.MessageType.Warning);
}
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 7bdd28aaf4add69428d1b3149688ec8d
@@ -0,0 +1,29 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CustomEditor(typeof(AkSpatialAudioListener), true)]
public class AkSpatialAudioListenerInspector : UnityEditor.Editor
{
public override void OnInspectorGUI()
{
UnityEditor.EditorGUILayout.HelpBox(
"The current version of Spatial Audio only supports one listener. Make sure to only have one AkSpatialAudioListener active at a time.",
UnityEditor.MessageType.Info);
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 335cff85d4897d74bba27db0bd5a5684
@@ -0,0 +1,35 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkState), true)]
public class AkStateInspector : AkBaseInspector
{
private readonly AkUnityEventHandlerInspector m_UnityEventHandlerInspector = new AkUnityEventHandlerInspector();
private void OnEnable()
{
m_UnityEventHandlerInspector.Init(serializedObject);
}
public override void OnChildInspectorGUI()
{
m_UnityEventHandlerInspector.OnGUI();
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 39955d24bad7d8548bafb60ea0874dda
@@ -0,0 +1,100 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CustomEditor(typeof(AkSurfaceReflector), true)]
[UnityEditor.CanEditMultipleObjects]
public class AkSurfaceReflectorInspector : UnityEditor.Editor
{
private AkSurfaceReflector m_AkSurfaceReflector;
private UnityEditor.SerializedProperty Mesh;
private UnityEditor.SerializedProperty AcousticTextures;
private UnityEditor.SerializedProperty TransmissionLossValues;
private UnityEditor.SerializedProperty EnableDiffraction;
private UnityEditor.SerializedProperty EnableDiffractionOnBoundaryEdges;
private UnityEditor.SerializedProperty BypassPortalSubtraction;
private UnityEditor.SerializedProperty Solid;
private UnityEditor.SerializedProperty isStatic;
public void OnEnable()
{
m_AkSurfaceReflector = target as AkSurfaceReflector;
Mesh = serializedObject.FindProperty("Mesh");
AcousticTextures = serializedObject.FindProperty("AcousticTextures");
TransmissionLossValues = serializedObject.FindProperty("TransmissionLossValues");
EnableDiffraction = serializedObject.FindProperty("EnableDiffraction");
EnableDiffractionOnBoundaryEdges = serializedObject.FindProperty("EnableDiffractionOnBoundaryEdges");
Solid = serializedObject.FindProperty("Solid");
BypassPortalSubtraction = serializedObject.FindProperty("BypassPortalSubtraction");
isStatic = serializedObject.FindProperty("isStatic");
}
public override void OnInspectorGUI()
{
serializedObject.Update();
UnityEditor.EditorGUILayout.PropertyField(isStatic);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.PropertyField(Mesh);
UnityEditor.EditorGUILayout.PropertyField(AcousticTextures, true);
CheckArraySize(m_AkSurfaceReflector, m_AkSurfaceReflector.AcousticTextures.Length, "acoustic textures");
UnityEditor.EditorGUILayout.PropertyField(TransmissionLossValues, true);
CheckArraySize(m_AkSurfaceReflector, m_AkSurfaceReflector.TransmissionLossValues.Length, "transmission loss values");
}
UnityEditor.EditorGUILayout.PropertyField(EnableDiffraction);
if (EnableDiffraction.boolValue)
{
UnityEditor.EditorGUILayout.PropertyField(EnableDiffractionOnBoundaryEdges);
}
UnityEditor.EditorGUILayout.PropertyField(BypassPortalSubtraction);
UnityEditor.EditorGUILayout.PropertyField(Solid);
serializedObject.ApplyModifiedProperties();
}
public static void CheckArraySize(AkSurfaceReflector surfaceReflector, int length, string name)
{
if (surfaceReflector == null || surfaceReflector.Mesh == null)
{
return;
}
int maxSize = surfaceReflector.Mesh.subMeshCount;
if (length <= maxSize)
{
return;
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
UnityEditor.EditorGUILayout.HelpBox(
"There are more " + name + " than the Mesh has submeshes. Additional ones will be ignored.",
UnityEditor.MessageType.Warning);
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 1bac1f7c5c021bd47b130b9991a9ecde
@@ -0,0 +1,35 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkSwitch), true)]
public class AkSwitchInspector : AkBaseInspector
{
private readonly AkUnityEventHandlerInspector m_UnityEventHandlerInspector = new AkUnityEventHandlerInspector();
private void OnEnable()
{
m_UnityEventHandlerInspector.Init(serializedObject);
}
public override void OnChildInspectorGUI()
{
m_UnityEventHandlerInspector.OnGUI();
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 261f4e1fa38cc09439250c00da2adb80
@@ -0,0 +1,158 @@
#if UNITY_EDITOR
/*******************************************************************************
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 AkUnityEventHandlerInspector
{
private static string[] m_triggerTypeNames;
private static uint[] m_triggerTypeIDs;
private static System.Collections.Generic.Dictionary<uint, string> m_triggerTypes;
///Defines the triggers that make use of useOtherObjectMask
private static readonly string[] useOtherObjectTriggers =
{ "AkTriggerEnter", "AkTriggerExit", "AkTriggerCollisionEnter", "AkTriggerCollisionExit" };
private string m_label = "Trigger On: ";
private bool m_showUseOtherToggle = true;
private UnityEditor.SerializedProperty m_triggerList;
private UnityEditor.SerializedProperty m_useOtherObject;
public void Init(UnityEditor.SerializedObject in_serializedObject, string in_listName = "triggerList",
string in_label = "Trigger On: ", bool in_showUseOtherToggle = true)
{
m_label = in_label;
m_showUseOtherToggle = in_showUseOtherToggle;
m_triggerList = in_serializedObject.FindProperty(in_listName);
m_useOtherObject = in_serializedObject.FindProperty("useOtherObject");
//Get the updated list of all triggers
if (m_triggerTypes == null)
{
m_triggerTypes = AkTriggerBase.GetAllDerivedTypes();
m_triggerTypeNames = new string[m_triggerTypes.Count];
m_triggerTypes.Values.CopyTo(m_triggerTypeNames, 0);
m_triggerTypeIDs = new uint[m_triggerTypes.Count];
m_triggerTypes.Keys.CopyTo(m_triggerTypeIDs, 0);
}
}
public void OnGUI()
{
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
using (new UnityEditor.EditorGUILayout.VerticalScope("box"))
{
var currentTriggers = GetCurrentTriggers();
var oldMask = BuildCurrentMaskValue(currentTriggers);
var newMask = UnityEditor.EditorGUILayout.MaskField(m_label, oldMask, m_triggerTypeNames);
if (oldMask != newMask)
{
currentTriggers.Clear();
for (var i = 0; i < m_triggerTypeNames.Length; i++)
{
var curTriggerID = AkUtilities.ShortIDGenerator.Compute(m_triggerTypeNames[i]);
if ((newMask & (1 << i)) != 0 && !currentTriggers.Contains(curTriggerID))
currentTriggers.Add(curTriggerID);
}
SaveNewTriggers(currentTriggers);
}
if (m_showUseOtherToggle)
{
var toggleWasDisplayed = false;
for (var i = 0; i < m_triggerTypeNames.Length; i++)
{
if ((newMask & (1 << i)) != 0 && Contain(useOtherObjectTriggers, m_triggerTypeNames[i]))
{
UnityEditor.EditorGUILayout.PropertyField(m_useOtherObject, new UnityEngine.GUIContent("Use Other Object: "));
toggleWasDisplayed = true;
break;
}
}
if (!toggleWasDisplayed)
m_useOtherObject.boolValue = false;
}
}
UnityEngine.GUILayout.Space(UnityEditor.EditorGUIUtility.standardVerticalSpacing);
}
private System.Collections.Generic.List<uint> GetCurrentTriggers()
{
var newList = new System.Collections.Generic.List<uint>();
for (var i = 0; i < m_triggerList.arraySize; i++)
newList.Add((uint)m_triggerList.GetArrayElementAtIndex(i).intValue);
return newList;
}
private int GetIdIndex(uint in_ID)
{
var index = -1;
for (var i = 0; i < m_triggerTypeIDs.Length; i++)
{
if (m_triggerTypeIDs[i] == in_ID)
{
index = i;
break;
}
}
return index;
}
private int BuildCurrentMaskValue(System.Collections.Generic.List<uint> currentTriggers)
{
var maskToReturn = 0;
for (var i = 0; i < currentTriggers.Count; i++)
{
var idIndex = GetIdIndex(currentTriggers[i]);
if (idIndex != -1)
maskToReturn |= 1 << idIndex;
}
return maskToReturn;
}
private void SaveNewTriggers(System.Collections.Generic.List<uint> currentTriggers)
{
m_triggerList.ClearArray();
for (var i = 0; i < currentTriggers.Count; i++)
{
m_triggerList.InsertArrayElementAtIndex(i);
m_triggerList.GetArrayElementAtIndex(i).intValue = (int) currentTriggers[i];
}
}
private bool Contain(string[] in_array, string in_value)
{
for (var i = 0; i < in_array.Length; i++)
{
if (in_array[i].Equals(in_value))
return true;
}
return false;
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 092de7bd13bdfa54fb68789e5f42fd39
@@ -0,0 +1,35 @@
#if UNITY_EDITOR
/*******************************************************************************
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.
*******************************************************************************/
[UnityEditor.CanEditMultipleObjects]
[UnityEditor.CustomEditor(typeof(AkWwiseTrigger), true)]
public class AkWwiseTriggerInspector : AkBaseInspector
{
private readonly AkUnityEventHandlerInspector m_UnityEventHandlerInspector = new AkUnityEventHandlerInspector();
private void OnEnable()
{
m_UnityEventHandlerInspector.Init(serializedObject);
}
public override void OnChildInspectorGUI()
{
m_UnityEventHandlerInspector.OnGUI();
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 25215f45dc767c74d9735014cb41f2c7
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 0f8828073c0dd8e4ca1dc42e88357dce
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 9e1f8e0d67ca03b4c9673b30f3a1eb86
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,34 @@
/*******************************************************************************
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 UNITY_EDITOR
[UnityEditor.InitializeOnLoad]
public class AkMacBuildPreprocessor
{
static AkMacBuildPreprocessor()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
WwiseSetupWizard.AddBuildTargetGroup(UnityEditor.BuildTargetGroup.Standalone);
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 392f44b722eebf9409adb5d5aa59907c
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: 77675ff2dc9f8a54aaaa0d8d046795b0
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,32 @@
/*******************************************************************************
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 UNITY_EDITOR
[UnityEditor.InitializeOnLoad]
public class AkWindowsBuildPreprocessor
{
static AkWindowsBuildPreprocessor()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
WwiseSetupWizard.AddBuildTargetGroup(UnityEditor.BuildTargetGroup.Standalone);
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 9923482a8945cec4ab705fe400c5c8ee
@@ -0,0 +1,8 @@
fileFormatVersion: 2
guid: d4442a4e865c1104d96fc272b2472fbf
folderAsset: yes
DefaultImporter:
externalObjects: {}
userData:
assetBundleName:
assetBundleVariant:
@@ -0,0 +1,204 @@
/*******************************************************************************
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 UNITY_EDITOR
using System.Collections.Generic;
using System.IO;
using AK.Wwise.Unity.Logging;
public partial class AkBuildPreprocessor
{
/// <summary>
/// User hook called to retrieve the custom platform name used to determine the base path. Do not modify platformName
/// to use default platform names.
/// </summary>
/// <param name="platformName">The custom platform name.</param>
public delegate void CustomPlatformNameGetter(ref string platformName, UnityEditor.BuildTarget target);
public static CustomPlatformNameGetter GetCustomPlatformName;
public delegate void OnBuildCallback(string path);
public static void BuildCallbackNoOp(string path)
{
// No-op
}
public class PlatformConfiguration
{
public string WwisePlatformName;
public OnBuildCallback OnPreprocessBuild = BuildCallbackNoOp;
public OnBuildCallback OnPostprocessBuild = BuildCallbackNoOp;
}
private static Dictionary<UnityEditor.BuildTarget, PlatformConfiguration> PlatformConfigurations = new Dictionary<UnityEditor.BuildTarget, PlatformConfiguration>();
public static void RegisterBuildTarget(UnityEditor.BuildTarget target, PlatformConfiguration config)
{
PlatformConfigurations.Add(target, config);
}
public static string GetPlatformName(UnityEditor.BuildTarget target)
{
var platformSubDir = string.Empty;
GetCustomPlatformName?.Invoke(ref platformSubDir, target);
if (!string.IsNullOrEmpty(platformSubDir))
return platformSubDir;
//New way to access target platform name
string platformName = AkBasePathGetter.GetTargetPlatformName(target);
if (platformName != string.Empty)
{
return platformName;
}
//For legacy code compatibility. Should maybe remove in 26.1 or 27.1 to give time to adjust
if (PlatformConfigurations.ContainsKey(target))
{
if (platformName == string.Empty)
{
platformName = PlatformConfigurations[target].WwisePlatformName;
}
return platformName;
}
//Keeping the old fallback of using the Unity target name.
return target.ToString();
}
}
#if UNITY_2018_1_OR_NEWER
public partial class AkBuildPreprocessor : UnityEditor.Build.IPreprocessBuildWithReport, UnityEditor.Build.IPostprocessBuildWithReport
#else
public partial class AkBuildPreprocessor : UnityEditor.Build.IPreprocessBuild, UnityEditor.Build.IPostprocessBuild
#endif
{
public int callbackOrder
{
get { return 0; }
}
private string destinationSoundBankFolder = string.Empty;
public static bool CopySoundbanks(bool generate, string platformName, ref string destinationFolder)
{
if (string.IsNullOrEmpty(platformName))
{
WwiseLogger.ErrorFormat("Could not determine platform name for <{0}> platform", platformName);
return false;
}
if (generate)
{
var platforms = new System.Collections.Generic.List<string> { platformName };
string wwiseInstallationPath = "";
#if UNITY_EDITOR_WIN
wwiseInstallationPath = AkWwiseEditorSettings.Instance.WwiseInstallationPathWindows;
#elif UNITY_EDITOR_OSX
wwiseInstallationPath = AkWwiseEditorSettings.Instance.WwiseInstallationPathMac;
#endif
AkUtilities.GenerateSoundbanks(wwiseInstallationPath, AkWwiseEditorSettings.WwiseProjectAbsolutePath, platforms);
}
string sourceFolder;
if (!AkBasePathGetter.GetSoundBankPaths(platformName, out sourceFolder, out destinationFolder))
return false;
if (!AkUtilities.DirectoryCopy(sourceFolder, destinationFolder, true))
{
destinationFolder = null;
WwiseLogger.ErrorFormat("Could not copy SoundBank folder for <{0}> platform", platformName);
return false;
}
WwiseLogger.Log($"Copied SoundBank folder from <{sourceFolder}> to streaming assets folder <{destinationFolder}> for <{platformName}> platform build");
return true;
}
public static void DeleteSoundbanks(string destinationFolder)
{
if (string.IsNullOrEmpty(destinationFolder))
return;
System.IO.Directory.Delete(destinationFolder, true);
WwiseLogger.LogFormat("Deleting streaming assets folder <{0}>", destinationFolder);
}
public void OnPreprocessBuildInternal(UnityEditor.BuildTarget target, string path)
{
var platformName = GetPlatformName(target);
#if !(AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES)
if (AkWwiseEditorSettings.Instance.CopySoundBanksAsPreBuildStep)
{
if (!CopySoundbanks(AkWwiseEditorSettings.Instance.GenerateSoundBanksAsPreBuildStep, platformName, ref destinationSoundBankFolder))
{
WwiseLogger.ErrorFormat("SoundBank folder has not been copied for <{0}> target at <{1}>. This will likely result in a build without sound!!!", target, path);
}
}
#endif
if (PlatformConfigurations.TryGetValue(target, out var config))
{
config.OnPreprocessBuild(path);
}
// Init ProjectDB for platform being built
WwiseProjectDatabase.Init(AkWwiseEditorSettings.GetRootOutputPath(), platformName);
AkPluginActivator.ForceUpdate();
AkPluginActivator.ActivatePluginsForDeployment(target, true);
}
public void OnPostprocessBuildInternal(UnityEditor.BuildTarget target, string path)
{
AkPluginActivator.ActivatePluginsForDeployment(target, false);
if (PlatformConfigurations.TryGetValue(target, out var config))
{
config.OnPostprocessBuild(path);
}
#if !(AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES)
DeleteSoundbanks(destinationSoundBankFolder);
#endif
destinationSoundBankFolder = string.Empty;
// Point the ProjectDB back on the current editor platform
WwiseProjectDatabase.Init(AkWwiseEditorSettings.GetRootOutputPath(), AkBasePathGetter.GetPlatformName());
}
#if UNITY_2018_1_OR_NEWER
public void OnPreprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
OnPreprocessBuildInternal(report.summary.platform, report.summary.outputPath);
}
public void OnPostprocessBuild(UnityEditor.Build.Reporting.BuildReport report)
{
OnPostprocessBuildInternal(report.summary.platform, report.summary.outputPath);
}
#else
public void OnPreprocessBuild(UnityEditor.BuildTarget target, string path)
{
OnPreprocessBuildInternal(target, path);
}
public void OnPostprocessBuild(UnityEditor.BuildTarget target, string path)
{
OnPostprocessBuildInternal(target, path);
}
#endif
}
#endif // #if UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 5cf5d16f083391b4a8681b007ca2f85c
@@ -0,0 +1,142 @@
/*******************************************************************************
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 UNITY_EDITOR
// Note, this code was only written to parse the AudioManager.asset file.
// It has been written to try to be as generic as possible, but might not
// work on other .asset settings files.
public class AkUnitySettingsParser
{
public static bool SetBoolValue(string ValueName, bool ValueToSet, string ConfigFileName)
{
try
{
var SettingsPath = UnityEngine.Application.dataPath.Remove(UnityEngine.Application.dataPath.LastIndexOf("/")) +
"/ProjectSettings/" + ConfigFileName + ".asset";
System.IO.FileStream fs;
System.IO.BinaryReader br;
fs = System.IO.File.Open(SettingsPath, System.IO.FileMode.Open);
br = new System.IO.BinaryReader(fs);
// Read the unsigned int at offset 0x0C in the file.
// This contains the offset at which the setting's numerical values are stored.
br.BaseStream.Seek(0x0C, System.IO.SeekOrigin.Begin);
// For some reason, the offset is Big Endian in the file.
var SettingsOffset = GetBigEndianIntFromBinaryReader(br);
// In the file, we start with 0x14 bytes, then a string containing the unity version,
// then 0x0C bytes, then a string containing the base class name, followed by a string containing "base".
string tempStr;
br.BaseStream.Seek(0x14, System.IO.SeekOrigin.Begin);
tempStr = GetStringFromBinaryReader(br); // Unity Version
br.BaseStream.Seek(0x0C, System.IO.SeekOrigin.Current);
tempStr = GetStringFromBinaryReader(br); // Config file Name
if (tempStr != ConfigFileName)
return false;
tempStr = GetStringFromBinaryReader(br); // "Base"
if (tempStr != "Base")
return false;
// This string is then followed by 24 bytes
br.BaseStream.Seek(24, System.IO.SeekOrigin.Current);
// We then have a series of String (type), String (variable name), and 24 bytes
// We can use the type of the settings before the field we are looking for to
// find its offset after SettingsOffset.
while (br.BaseStream.Position < br.BaseStream.Length)
{
var SettingType = GetStringFromBinaryReader(br);
var SettingName = GetStringFromBinaryReader(br);
if (SettingName == ValueName)
break;
br.BaseStream.Seek(24, System.IO.SeekOrigin.Current);
if (GetSizeofTypeByString(SettingType) == -1)
return false;
SettingsOffset += GetSizeofTypeByString(SettingType);
}
// Set the setting in the file
var bw = new System.IO.BinaryWriter(fs);
bw.Seek(SettingsOffset, System.IO.SeekOrigin.Begin);
bw.Write(ValueToSet ? (byte) 1 : (byte) 0);
bw.Close();
fs.Close();
}
catch (System.Exception)
{
// Error happened
return false;
}
// Success!
return true;
}
// Read a big endian Int, and advances the BinaryReader's position
private static int GetBigEndianIntFromBinaryReader(System.IO.BinaryReader br)
{
var tempBytes = new byte[4];
tempBytes = br.ReadBytes(4);
return (tempBytes[0] << 24) | (tempBytes[1] << 16) | (tempBytes[2] << 8) | tempBytes[3];
}
// Reads a zero-terminated string at the BinaryReader's current position, and advances position
private static string GetStringFromBinaryReader(System.IO.BinaryReader br)
{
var list = new System.Collections.Generic.List<byte>();
// Do not add the \0 in the string, because comparison won't work
var currentByte = br.ReadByte();
while (currentByte != 0)
{
list.Add(currentByte);
currentByte = br.ReadByte();
}
return System.Text.Encoding.Default.GetString(list.ToArray());
}
// Returns the size in bytes of a type, as specified in the .asset file
// NOTE: this function only supports types found in AudioManager.asset.
private static int GetSizeofTypeByString(string typeStr)
{
switch (typeStr)
{
case "int":
case "unsigned int":
case "float":
case "UInt32":
case "SInt32":
return 4;
case "bool":
return 1;
default:
return -1;
}
}
}
#endif // UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: e0e5c350f4eb2c541afb59c6c7203386
@@ -0,0 +1,403 @@
/*******************************************************************************
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 UNITY_EDITOR
using UnityEditor;
using UnityEngine;
using AK.Wwise.Unity.Logging;
[UnityEditor.InitializeOnLoad]
public class AkWwisePostImportCallbackSetup
{
private static int m_scheduledMigrationStart;
private static bool m_scheduledReturnToLauncher;
private static bool m_pendingExecuteMethodCalled;
private static string s_CurrentScene;
static AkWwisePostImportCallbackSetup()
{
if (UnityEditor.AssetDatabase.IsAssetImportWorkerProcess())
{
return;
}
var arguments = System.Environment.GetCommandLineArgs();
if (UnityEngine.Application.isBatchMode
&& System.Array.IndexOf(arguments, "-wwiseEnableWithNoGraphics") == -1)
return;
UnityEditor.EditorApplication.delayCall += CheckMigrationStatus;
AkUtilities.GetEventDurations = (uint eventID, ref float maximum, ref float minimum) =>
{
var eventInfo = AkWwiseProjectInfo.GetData().GetEventInfo(eventID);
if (eventInfo != null)
{
minimum = eventInfo.minDuration;
maximum = eventInfo.maxDuration;
}
};
}
private static void CheckMigrationStatus()
{
try
{
int migrationStart;
bool returnToLauncher;
if (IsMigrationPending(out migrationStart, out returnToLauncher))
{
m_scheduledMigrationStart = migrationStart;
m_scheduledReturnToLauncher = returnToLauncher;
ScheduleMigration();
}
else
{
RefreshCallback();
}
}
catch (System.Exception e)
{
WwiseLogger.Error("Error during migration: " + e);
}
}
private static void ScheduleMigration()
{
// TODO: Is delayCall wiped out during a script reload?
// If not, guard against having a delayCall from a previously loaded code being run after the new loading.
if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || UnityEditor.EditorApplication.isCompiling)
{
// Skip if not in the right mode, wait for the next callback to see if we can proceed then.
UnityEditor.EditorApplication.delayCall += ScheduleMigration;
return;
}
try
{
WwiseSetupWizard.PerformMigration(m_scheduledMigrationStart);
// Force the user to return to the launcher to perform the post-installation process if necessary
if (m_scheduledReturnToLauncher)
{
if (UnityEditor.EditorUtility.DisplayDialog("Wwise Migration Successful!",
"Please close Unity and go back to the Wwise Launcher to complete the installation.", "Quit"))
UnityEditor.EditorApplication.Exit(0);
}
else
UnityEditor.EditorApplication.delayCall += RefreshCallback;
}
catch (System.Exception e)
{
WwiseLogger.Error("Error during migration: " + e);
}
}
private static bool IsMigrationPending(out int migrationStart, out bool returnToLauncher)
{
migrationStart = 0;
returnToLauncher = false;
var filename = UnityEngine.Application.dataPath + "/../.WwiseLauncherLockFile";
if (!System.IO.File.Exists(filename))
return false;
var fileContent = System.IO.File.ReadAllText(filename);
// Instantiate the regular expression object.
var r = new System.Text.RegularExpressions.Regex(
"{\"migrateStart\":(\\d+),\"migrateStop\":(\\d+)(,\"returnToLauncher\":(true|false))?,.*}",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
// Match the regular expression pattern against a text string.
var m = r.Match(fileContent);
if (!m.Success || m.Groups.Count < 2 || m.Groups[1].Captures.Count < 1 || m.Groups[2].Captures.Count < 1 ||
!int.TryParse(m.Groups[1].Captures[0].ToString(), out migrationStart))
throw new System.Exception("Error in the file format of .WwiseLauncherLockFile.");
// Handle optional properties
if (m.Groups.Count > 3 && m.Groups[4].Captures.Count > 0)
bool.TryParse(m.Groups[4].Captures[0].ToString(), out returnToLauncher);
return true;
}
private static void RefreshCallback()
{
PostImportFunction();
if (WwiseSettings.Exists)
{
AkPluginActivator.Update();
AkPluginActivator.ActivatePluginsForEditor();
}
}
private static void PostImportFunction()
{
#if UNITY_2018_1_OR_NEWER
UnityEditor.EditorApplication.hierarchyChanged += CheckWwiseGlobalExistance;
#else
UnityEditor.EditorApplication.hierarchyWindowChanged += CheckWwiseGlobalExistance;
#endif
UnityEditor.EditorApplication.delayCall += CheckPicker;
if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || UnityEditor.EditorApplication.isCompiling)
return;
try
{
if (!string.IsNullOrEmpty(AkWwiseEditorSettings.Instance.WwiseProjectPath))
{
AkWwiseBrowser.Refresh(ignoreIfWaapi: true);
}
}
catch (System.Exception e)
{
WwiseLogger.Log(e.ToString());
}
//Check if a WwiseGlobal object exists in the current scene
CheckWwiseGlobalExistance();
}
private static void RefreshPlugins()
{
if (string.IsNullOrEmpty(AkWwiseProjectInfo.GetData().CurrentPluginConfig))
AkWwiseProjectInfo.GetData().CurrentPluginConfig = AkPluginActivatorConstants.CONFIG_PROFILE;
AkPluginActivator.ActivatePluginsForEditor();
}
public static void CheckPicker()
{
if (UnityEditor.EditorApplication.isPlayingOrWillChangePlaymode || UnityEditor.EditorApplication.isCompiling)
{
// Skip if not in the right mode, wait for the next callback to see if we can proceed then.
UnityEditor.EditorApplication.delayCall += CheckPicker;
return;
}
var settings = AkWwiseEditorSettings.Instance;
if (!settings.CreatedPicker)
{
// Delete all the ghost tabs (Failed to load).
var windows = UnityEngine.Resources.FindObjectsOfTypeAll<UnityEditor.EditorWindow>();
if (windows != null && windows.Length > 0)
{
foreach (var window in windows)
{
var windowTitle = window.titleContent.text;
if (windowTitle.Equals("Failed to load") || windowTitle.Equals("AkWwisePicker"))
{
try
{
window.Close();
}
catch
{
// Do nothing here, this shouldn't cause any problem, however there has been
// occurrences of Unity crashing on a null reference inside that method.
}
}
}
}
// TODO: If no scene is loaded and we are using the demo scene, automatically load it to display it.
// Populate the picker
AkWwiseProjectInfo.GetData(); // Load data
if (!string.IsNullOrEmpty(settings.WwiseProjectPath))
{
AkWwiseProjectInfo.Populate();
AkWwiseBrowser.InitBrowserWindow();
settings.CreatedPicker = true;
settings.SaveSettings();
}
}
UnityEditor.EditorApplication.delayCall += CheckPendingExecuteMethod;
}
// TODO: Put this in AkUtilities?
private static void ExecuteMethod(string method)
{
string className = null;
string methodName = null;
var regex = new System.Text.RegularExpressions.Regex("(.+)\\.(.+)",
System.Text.RegularExpressions.RegexOptions.IgnoreCase);
var regexMatchResult = regex.Match(method);
if (!regexMatchResult.Success || regexMatchResult.Groups.Count < 3 || regexMatchResult.Groups[1].Captures.Count < 1 || regexMatchResult.Groups[2].Captures.Count < 1)
{
WwiseLogger.Error("Error parsing wwiseExecuteMethod parameter: " + method);
return;
}
className = regexMatchResult.Groups[1].Captures[0].ToString();
methodName = regexMatchResult.Groups[2].Captures[0].ToString();
try
{
System.Reflection.MethodInfo methodToExecute = null;
if (className == "AkTestUtilities")
{
var assembly = System.Reflection.Assembly.Load("Ak.Wwise.IntegrationTestsEditor");
methodToExecute = assembly.GetType(className).GetMethod(methodName,
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
}
else
{
var type = System.Type.GetType(className);
if (type == null)
{
type = System.Type.GetType(className + ", Assembly-CSharp-Editor");
}
methodToExecute = type.GetMethod(methodName,
System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);
}
if (methodToExecute == null)
{
WwiseLogger.Error("Error in AkWwisePostImportCallbackSetup::ExecuteMethod(): Could not find method: " + method);
return;
}
methodToExecute.Invoke(null, null);
}
catch (System.Exception e)
{
WwiseLogger.Error("Exception caught when calling " + method + ": " + e);
}
}
private static void CheckPendingExecuteMethod()
{
var arguments = System.Environment.GetCommandLineArgs();
var indexOfCommand = System.Array.IndexOf(arguments, "-wwiseExecuteMethod");
if (!m_pendingExecuteMethodCalled && indexOfCommand != -1 && arguments.Length > indexOfCommand + 1)
{
var methodToExecute = arguments[indexOfCommand + 1];
ExecuteMethod(methodToExecute);
m_pendingExecuteMethodCalled = true;
}
}
// Called when changes are made to the scene and when a new scene is created.
public static void CheckWwiseGlobalExistance()
{
var activeSceneName = UnityEngine.SceneManagement.SceneManager.GetActiveScene().name;
if (!string.IsNullOrEmpty(s_CurrentScene) && s_CurrentScene.Equals(activeSceneName))
return;
var settings = AkWwiseEditorSettings.Instance;
// Look for a game object which has the initializer component
#if UNITY_6000_0_OR_NEWER
var AkInitializers = Object.FindObjectsByType<AkInitializer>(FindObjectsSortMode.None);
#else
var AkInitializers = Object.FindObjectsOfType<AkInitializer>();
#endif
if (AkInitializers.Length == 0)
{
if (settings.CreateWwiseGlobal)
{
WwiseLogger.LogFormat("No Wwise object in the scene ({0}), creating one.", s_CurrentScene);
//No Wwise object in this scene, create one so that the sound engine is initialized and terminated properly even if the scenes are loaded
//in the wrong order.
var objWwise = new UnityEngine.GameObject("WwiseGlobal");
//Attach initializer and terminator components
AkInitializer akInitializer;
if (AkUtilities.IsRunningTest())
{
akInitializer = objWwise.AddComponent<AkInitializer>();
}
else
{
akInitializer = UnityEditor.Undo.AddComponent<AkInitializer>(objWwise);
}
akInitializer.InitializeInitializationSettings();
}
}
else if (AkInitializers.Length > 0)
{
foreach(AkInitializer Initializer in AkInitializers)
{
if (!Initializer.InitializationSettings)
{
WwiseLogger.LogFormat("Initializing {0} (GO {1}).", Initializer.name, Initializer.gameObject.name);
Initializer.InitializeInitializationSettings();
}
}
}
else if (settings.CreateWwiseGlobal == false && AkInitializers[0].gameObject.name == "WwiseGlobal")
{
WwiseLogger.LogFormat("CreateWwiseGlobal is false. Removing the AkInitializer in scene ({0}).", s_CurrentScene);
UnityEditor.Undo.DestroyObjectImmediate(AkInitializers[0].gameObject);
}
#if AK_WWISE_ADDRESSABLES && UNITY_ADDRESSABLES
var bankHolder = UnityEngine.Object.FindObjectOfType<AK.Wwise.Unity.WwiseAddressables.InitBankHolder>();
if (bankHolder == null)
{
UnityEngine.GameObject wwiseGlobalObject = UnityEngine.GameObject.Find("WwiseGlobal");
if (wwiseGlobalObject != null)
{
bankHolder = UnityEditor.Undo.AddComponent<AK.Wwise.Unity.WwiseAddressables.InitBankHolder>(wwiseGlobalObject);
}
}
if (bankHolder!=null && bankHolder.InitBank == null)
{
#if WWISE_ADDRESABLES_2022_1_0_OR_NEWER
var initBankPath = System.IO.Path.Combine(AkWwiseEditorSettings.WwiseScriptableObjectRelativePath, "InitBank.asset");
var initbank = UnityEditor.AssetDatabase.LoadAssetAtPath<AK.Wwise.Unity.WwiseAddressables.WwiseInitBankReference>(initBankPath);
if (initbank)
{
bankHolder.InitBank = initbank;
EditorUtility.SetDirty(bankHolder);
}
#else
var initBankPath = System.IO.Path.Combine("Assets",settings.RootOutputPath,"Init.asset");
var initbank = UnityEditor.AssetDatabase.LoadAssetAtPath<AK.Wwise.Unity.WwiseAddressables.WwiseAddressableSoundBank>(initBankPath);
bankHolder.InitBank = initbank;
EditorUtility.SetDirty(bankHolder);
#endif
}
#endif
if (settings.CreateWwiseListener)
{
WwiseSetupWizard.AddAkAudioListenerToMainCamera(true);
}
s_CurrentScene = activeSceneName;
}
}
#endif // UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 159bb4fd4c40a30499af5da93084cf22
@@ -0,0 +1,858 @@
/*******************************************************************************
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 UNITY_EDITOR
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text.RegularExpressions;
using UnityEditor;
using UnityEditor.PackageManager;
using UnityEngine;
public class WwiseSetupWizard
{
static Dictionary<int, string> WwiseAddressableDefines = new Dictionary<int, string>()
{
{2023, "WWISE_ADDRESSABLES_23_1_OR_LATER"},
{2024, "WWISE_ADDRESSABLES_24_1_OR_LATER"}
};
static Dictionary<int, string> WwiseVersionDefines = new Dictionary<int, string>()
{
{2024, "WWISE_2024_OR_LATER"}
};
//Change this when an API change is introduced that would break older version of the addrerssables package
private static string WwiseAddressableAPIDefine = "ADDRESSABLES_API_BROWSER_TREE_VIEW";
public static void RunModify()
{
try
{
UnityEngine.Debug.Log("WwiseUnity: Running modify setup...");
UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects);
ModifySetup();
UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database.");
UnityEditor.AssetDatabase.Refresh();
// IMPORTANT: This log line is parsed by the Launcher. Do not modify it.
UnityEngine.Debug.Log("WwiseUnity: End of setup, exiting Unity.");
}
catch (System.Exception e)
{
UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e);
}
}
public static void RunSetup()
{
try
{
UnityEngine.Debug.Log("WwiseUnity: Running install setup...");
Setup();
UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database.");
UnityEditor.AssetDatabase.Refresh();
// IMPORTANT: This log line is parsed by the Launcher. Do not modify it.
UnityEngine.Debug.Log("WwiseUnity: End of setup, exiting Unity.");
}
catch (System.Exception e)
{
UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e);
}
}
public static void RunDemoSceneSetup()
{
try
{
UnityEngine.Debug.Log("WwiseUnity: Running demo scene setup...");
Setup();
UnityEditor.SceneManagement.EditorSceneManager.OpenScene("Assets/WwiseDemoScene/WwiseDemoScene.unity");
UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database.");
UnityEditor.AssetDatabase.Refresh();
UnityEngine.Debug.Log("WwiseUnity: End of demo scene setup, exiting Unity.");
}
catch (System.Exception e)
{
UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e);
}
}
private static int TotalNumberOfSections = 3;
private static void UpdateProgressBar(int sectionIndex, int subSectionIndex = 0, int totalSubSections = 1)
{
subSectionIndex = UnityEngine.Mathf.Clamp(subSectionIndex, 0, totalSubSections);
sectionIndex = UnityEngine.Mathf.Clamp(sectionIndex, 0, TotalNumberOfSections);
float progress = ((float)subSectionIndex / totalSubSections + sectionIndex) / TotalNumberOfSections;
UnityEditor.EditorUtility.DisplayProgressBar("Wwise Integration", "Migration in progress - Please wait...", progress);
}
public static void RunMigrate()
{
try
{
UnityEngine.Debug.Log("WwiseUnity: Running migration setup...");
UnityEngine.Debug.Log("WwiseUnity: Reading parameters...");
var arguments = System.Environment.GetCommandLineArgs();
string migrateStartString = null;
var indexMigrateStart = System.Array.IndexOf(arguments, "-wwiseInstallMigrateStart");
if (indexMigrateStart != -1)
migrateStartString = arguments[indexMigrateStart + 1];
else
{
UnityEngine.Debug.LogError("WwiseUnity: ERROR: Missing parameter wwiseInstallMigrateStart.");
return;
}
int migrateStart;
if (!int.TryParse(migrateStartString, out migrateStart))
{
UnityEngine.Debug.LogError("WwiseUnity: ERROR: wwiseInstallMigrateStart is not a number.");
return;
}
PerformMigration(migrateStart - 1);
UnityEditor.AssetDatabase.SaveAssets();
UnityEngine.Debug.Log("WwiseUnity: Refreshing asset database.");
UnityEditor.AssetDatabase.Refresh();
// IMPORTANT: This log line is parsed by the Launcher. Do not modify it.
UnityEngine.Debug.Log("WwiseUnity: End of setup, exiting Unity.");
}
catch (System.Exception e)
{
UnityEngine.Debug.LogError("WwiseUnity: Exception caught: " + e);
}
}
private static void MigrateCurrentScene(System.Type[] wwiseComponentTypes)
{
var objectTypeMap = new System.Collections.Generic.Dictionary<System.Type, UnityEngine.Object[]>();
foreach (var objectType in wwiseComponentTypes)
{
// Get all objects in the scene with the specified type.
#if UNITY_6000_0_OR_NEWER
var objects = UnityEngine.Object.FindObjectsByType(objectType, FindObjectsSortMode.None);
#else
var objects = UnityEngine.Object.FindObjectsOfType(objectType);
#endif
if (objects != null && objects.Length > 0)
objectTypeMap[objectType] = objects;
}
for (var ii = AkUtilities.MigrationStartIndex; ii < AkUtilities.MigrationStopIndex; ++ii)
{
var migrationMethodName = "Migrate" + ii;
var preMigrationMethodName = "PreMigration" + ii;
var postMigrationMethodName = "PostMigration" + ii;
foreach (var objectTypePair in objectTypeMap)
{
var objectType = objectTypePair.Key;
var objects = objectTypePair.Value;
var className = objectType.Name;
var preMigrationMethodInfo = objectType.GetMethod(preMigrationMethodName,
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
if (preMigrationMethodInfo != null)
{
UnityEngine.Debug.Log("WwiseUnity: PreMigration step <" + ii + "> for class <" + className + ">");
preMigrationMethodInfo.Invoke(null, null);
}
var migrationMethodInfo = objectType.GetMethod(migrationMethodName,
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance);
if (migrationMethodInfo != null)
{
UnityEngine.Debug.Log("WwiseUnity: Migration step <" + ii + "> for class <" + className + ">");
// Call the migration method of each object.
foreach (var currentObject in objects)
migrationMethodInfo.Invoke(currentObject, null);
}
var postMigrationMethodInfo = objectType.GetMethod(postMigrationMethodName,
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static);
if (postMigrationMethodInfo != null)
{
UnityEngine.Debug.Log("WwiseUnity: PostMigration step <" + ii + "> for class <" + className + ">");
postMigrationMethodInfo.Invoke(null, null);
}
}
}
}
private static System.Type[] GetWwiseComponentTypes()
{
var wwiseComponentTypes = new System.Collections.Generic.List<System.Type>();
var wwiseComponentFolder = UnityEngine.Application.dataPath + "/Wwise/MonoBehaviour/Runtime";
if (System.IO.Directory.Exists(wwiseComponentFolder))
{
var files = new System.IO.DirectoryInfo(wwiseComponentFolder).GetFiles("*.cs", System.IO.SearchOption.AllDirectories);
foreach (var file in files)
{
var className = System.IO.Path.GetFileNameWithoutExtension(file.Name);
var objectType = System.Type.GetType(className + ", AK.Wwise.Unity.MonoBehaviour");
if (objectType != null && objectType.IsSubclassOf(typeof(UnityEngine.Object)))
{
wwiseComponentTypes.Add(objectType);
}
}
}
return wwiseComponentTypes.ToArray();
}
private static void MigrateObject(UnityEngine.Object obj)
{
if (obj == null)
{
UnityEngine.Debug.LogWarning("WwiseUnity: Missing script! Please consider resolving the missing scripts before migrating your Unity project. Any WwiseType on this object will NOT be migrated!");
return;
}
var migratable = obj as AK.Wwise.IMigratable;
if (migratable == null && !AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
return;
var hasChanged = false;
var serializedObject = new UnityEditor.SerializedObject(obj);
if (migratable != null)
hasChanged = migratable.Migrate(serializedObject);
else
hasChanged = AK.Wwise.TypeMigration.SearchAndProcessWwiseTypes(serializedObject.GetIterator());
if (hasChanged)
serializedObject.ApplyModifiedPropertiesWithoutUndo();
}
private static void MigratePrefabs()
{
// The only migration operation done in this method is to call MigrateObject on MonoBehaviours attached to prefabs.
// MigrateObject only runs if a migration is required for the "WwiseTypes_v2018_1_6" migration step.
// Add an early return here to avoid lots of potentially slow code if we are in a case where MigrateObject would
// do nothing.
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
{
return;
}
var guids = UnityEditor.AssetDatabase.FindAssets("t:Prefab", new[] { "Assets" });
for (var i = 0; i < guids.Length; i++)
{
UpdateProgressBar(0, i, guids.Length);
var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
UnityEngine.Debug.Log("WwiseUnity: Migrating prefab: " + path);
var prefabObject = UnityEditor.AssetDatabase.LoadAssetAtPath<UnityEngine.GameObject>(path);
if (prefabObject == null)
{
UnityEngine.Debug.LogWarning("WwiseUnity: Failed to migrate prefab: " + path);
continue;
}
var objects = prefabObject.GetComponents<UnityEngine.MonoBehaviour>();
// The rather convoluted way of iterating through all objects here has a very specific reason.
// The call to MigrateObject ends up calling SerializedObject.ApplyModifiedPropertiesWithoutUndo.
// This function call will invalidate all references that are held by the code that is running
// (the objects array here).
// In order to iterate properly on all MonoBehaviours available, we get their instance IDs,
// which do not change when Applying modified properties. Then, for each iteration of the
// migration loop, we need to get a valid array of MonoBehaviours again, because it might
// have been invalidated by the call to MigrateObject. We then migrate the objects that
// need migration by making sure their InstanceID is in the list of unmigrated MonoBehaviours.
var instanceIds = new System.Collections.Generic.List<int>();
foreach (var obj in objects)
{
if (obj == null)
continue;
var id = obj.GetInstanceID();
if (!instanceIds.Contains(id))
instanceIds.Add(id);
}
for (; instanceIds.Count > 0; instanceIds.RemoveAt(0))
{
var id = instanceIds[0];
var obj = UnityEditor.EditorUtility.InstanceIDToObject(id);
if (obj && obj.GetInstanceID() == id)
{
MigrateObject(obj);
}
}
}
}
private static string[] ScriptableObjectGuids = null;
private static bool ShouldProcessScriptableObject(UnityEngine.Object obj)
{
if (obj == null)
return true;
if (!(obj is UnityEngine.ScriptableObject))
return false;
if (obj is UnityEngine.GUISkin)
return false;
if (obj is AkWwiseInitializationSettings)
return false;
if (obj is AkCommonPlatformSettings)
return false;
if (AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.AutoDefinedSoundBanks_v2023_1_0) &&
obj is WwiseEventReference)
return true;
if (obj is WwiseObjectReference)
return false;
return true;
}
private static void MigrateScriptableObjects()
{
var guids = ScriptableObjectGuids;
if (guids == null)
return;
var processedGuids = new System.Collections.Generic.HashSet<string>();
for (var i = 0; i < guids.Length; i++)
{
UpdateProgressBar(2, i, guids.Length);
var guid = guids[i];
if (processedGuids.Contains(guid))
continue;
processedGuids.Add(guid);
var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guid);
var objects = UnityEditor.AssetDatabase.LoadAllAssetsAtPath(path);
foreach (var obj in objects)
{
if (ShouldProcessScriptableObject(obj))
{
UnityEngine.Debug.Log("WwiseUnity: Migrating ScriptableObject: " + path);
MigrateObject(obj);
}
}
}
}
private static void MigrateScenes()
{
var wwiseComponentTypes = GetWwiseComponentTypes();
var guids = UnityEditor.AssetDatabase.FindAssets("t:Scene", new[] { "Assets" });
for (var i = 0; i < guids.Length; i++)
{
UpdateProgressBar(1, i, guids.Length);
var path = UnityEditor.AssetDatabase.GUIDToAssetPath(guids[i]);
UnityEngine.Debug.Log("WwiseUnity: Migrating scene: " + path);
UnityEditor.EditorUtility.UnloadUnusedAssetsImmediate();
var scene = UnityEditor.SceneManagement.EditorSceneManager.OpenScene(path);
MigrateCurrentScene(wwiseComponentTypes);
// From this point on, the only migration operation done in this loop is to call MigrateObject on MonoBehaviours.
// MigrateObject only runs if a migration is required for the "WwiseTypes_v2018_1_6" migration step. Simply
// continue the loop here to avoid lots of potentially slow code if we are in a case where MigrateObject would
// do nothing.
if (!AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.WwiseTypes_v2018_1_6))
{
continue;
}
var objects = UnityEngine.Resources.FindObjectsOfTypeAll<UnityEngine.MonoBehaviour>();
// The rather convoluted way of iterating through all objects here has a very specific reason.
// The call to MigrateObject ends up calling SerializedObject.ApplyModifiedPropertiesWithoutUndo.
// This function call will invalidate all references that are held by the code that is running
// (the objects array here).
// In order to iterate properly on all MonoBehaviours available, we get their instance IDs,
// which do not change when Applying modified properties. Then, for each iteration of the
// migration loop, we need to get a valid array of MonoBehaviours again, because it might
// have been invalidated by the call to MigrateObject. We then migrate the objects that
// need migration by making sure their InstanceID is in the list of unmigrated MonoBehaviours.
var instanceIds = new System.Collections.Generic.List<int>();
foreach (var obj in objects)
{
if (obj == null)
continue;
var id = obj.GetInstanceID();
if (!instanceIds.Contains(id))
instanceIds.Add(id);
}
for (; instanceIds.Count > 0; instanceIds.RemoveAt(0))
{
var id = instanceIds[0];
var obj = UnityEditor.EditorUtility.InstanceIDToObject(id);
if (obj && obj.GetInstanceID() == id)
{
MigrateObject(obj);
}
}
if (UnityEditor.SceneManagement.EditorSceneManager.MarkSceneDirty(scene))
if (!UnityEditor.SceneManagement.EditorSceneManager.SaveScene(scene))
throw new System.Exception("Error occurred while saving migrated scenes.");
UnityEditor.SceneManagement.EditorSceneManager.CloseScene(scene, true);
}
}
public static void PerformMigration(int migrateStart)
{
AkUtilities.BeginMigration(migrateStart);
UpdateProgressBar(0);
UnityEngine.Debug.Log("WwiseUnity: Migrating from Unity Integration Version " + migrateStart + " to " + AkUtilities.MigrationStopIndex);
AkPluginActivator.DeactivateAllPlugins();
AkPluginActivator.Update();
AkPluginActivator.ActivatePluginsForEditor();
// Get the name of the currently opened scene.
var activeScene = UnityEngine.SceneManagement.SceneManager.GetActiveScene();
var loadedScenePath = activeScene.path;
if (!string.IsNullOrEmpty(loadedScenePath))
AkUtilities.FixSlashes(ref loadedScenePath, '\\', '/', false);
UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects);
// obtain a list of ScriptableObjects before any migration is performed
ScriptableObjectGuids = UnityEditor.AssetDatabase.FindAssets("t:ScriptableObject", new[] { "Assets" });
if (AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.NewScriptableObjectFolder_v2019_2_0))
{
var oldScriptableObjectPath = System.IO.Path.Combine(System.IO.Path.Combine("Assets", "Wwise"), "Resources");
AkUtilities.MoveFolder(oldScriptableObjectPath, AkWwiseEditorSettings.WwiseScriptableObjectRelativePath);
}
if (!UnityEditor.AssetDatabase.IsValidFolder(AkWwiseEditorSettings.WwiseScriptableObjectRelativePath))
{
UnityEngine.Debug.LogFormat("WwiseUnity: Creating ScriptableObjects folder at <{0}>", AkWwiseEditorSettings.WwiseScriptableObjectRelativePath);
AkUtilities.CreateFolder(AkWwiseEditorSettings.WwiseScriptableObjectRelativePath);
}
AkWwiseEditorSettings.GetRootOutputPath();
UnityEngine.Debug.LogFormat("WwiseUnity: Migrating Prefabs...");
MigratePrefabs();
UnityEngine.Debug.LogFormat("WwiseUnity: Done migrating Prefabs");
UnityEngine.Debug.LogFormat("WwiseUnity: Migrating Scenes...");
MigrateScenes();
UnityEngine.Debug.LogFormat("WwiseUnity: Done migrating Scenes");
UnityEngine.Debug.LogFormat("WwiseUnity: Migrating ScriptableObjects...");
MigrateScriptableObjects();
UnityEngine.Debug.LogFormat("WwiseUnity: Done migrating ScriptableObjects");
UnityEditor.EditorUtility.UnloadUnusedAssetsImmediate();
UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects);
AkUtilities.EndMigration();
UpdateProgressBar(TotalNumberOfSections);
// Reopen the scene that was opened before the migration process started.
if (!string.IsNullOrEmpty(loadedScenePath))
{
UnityEditor.SceneManagement.EditorSceneManager.OpenScene(loadedScenePath);
}
SetWwiseVersionDefines(WwiseAddressableDefines, true, "com.audiokinetic.wwise.addressables");
SetWwiseVersionDefines(WwiseVersionDefines);
SetSoundbankSettings();
UnityEngine.Debug.Log("WwiseUnity: Removing lock for launcher.");
// TODO: Moving one folder up is not nice at all. How to find the current project path?
try
{
System.IO.File.Delete(UnityEngine.Application.dataPath + "/../.WwiseLauncherLockFile");
}
catch
{
// Ignore if not present.
}
UnityEditor.EditorUtility.ClearProgressBar();
}
public static void ModifySetup()
{
var currentConfig = AkPluginActivator.GetCurrentConfig();
if (string.IsNullOrEmpty(currentConfig))
currentConfig = AkPluginActivatorConstants.CONFIG_PROFILE;
AkPluginActivator.DeactivateAllPlugins();
AkPluginActivator.Update();
AkPluginActivator.ActivatePluginsForEditor();
SetWwiseVersionDefines(WwiseAddressableDefines, true, "com.audiokinetic.wwise.addressables");
SetWwiseVersionDefines(WwiseVersionDefines);
}
// Perform all necessary steps to use the Wwise Unity integration.
private static void Setup()
{
UnityEditor.SceneManagement.EditorSceneManager.NewScene(UnityEditor.SceneManagement.NewSceneSetup.DefaultGameObjects);
UnityEngine.Debug.Log("WwiseUnity: Deactivating all plugins...");
AkPluginActivator.DeactivateAllPlugins();
// 0. Make sure the SoundBank directory exists
var sbPath = AkWwiseEditorSettings.GetRootOutputPath();
if (!System.IO.Directory.Exists(sbPath))
System.IO.Directory.CreateDirectory(sbPath);
// 1. Disable built-in audio
if (!DisableBuiltInAudio())
{
UnityEngine.Debug.LogWarning(
"WwiseUnity: Could not disable built-in audio. Please disable built-in audio by going to Project->Project Settings->Audio, and check \"Disable Audio\".");
}
// 2. Create a "WwiseGlobal" game object and set the AkSoundEngineInitializer and terminator scripts
// 3. Set the SoundBank path property on AkSoundEngineInitializer
CreateWwiseGlobalObject();
// 5. Disable the built-in audio listener, and add AkAudioListener component to camera
if (AkWwiseEditorSettings.Instance.CreateWwiseListener)
{
AddAkAudioListenerToMainCamera();
}
// 6. Enable "Run In Background" in PlayerSettings (PlayerSettings.runInbackground property)
UnityEditor.PlayerSettings.runInBackground = true;
UnityEngine.Debug.Log("WwiseUnity: Updating PluginActivator...");
AkPluginActivator.Update();
UnityEngine.Debug.Log("WwiseUnity: Activating plugins for editor...");
AkPluginActivator.ActivatePluginsForEditor();
// 9. Activate WwiseIDs file generation, and point Wwise to the Assets/Wwise folder
// 10. Change the SoundBanks options so it adds Max Radius information in the Wwise project
if (!SetSoundbankSettings())
UnityEngine.Debug.LogWarning("WwiseUnity: Could not modify Wwise Project to generate the header file!");
#if !UNITY_2021_1_OR_NEWER
// 11. Activate XboxOne network sockets.
AkXboxOneUtils.EnableXboxOneNetworkSockets();
#endif
// 12. Add addressables version define
SetWwiseVersionDefines(WwiseAddressableDefines, true, "com.audiokinetic.wwise.addressables");
// 13. Set Wwise version defines
SetWwiseVersionDefines(WwiseVersionDefines);
}
private static HashSet<BuildTargetGroup> AvailableBuildTargetGroups = new HashSet<BuildTargetGroup>();
public static void AddBuildTargetGroup(BuildTargetGroup NewGroup)
{
AvailableBuildTargetGroups.Add(NewGroup);
}
private static void SetWwiseVersionDefines(Dictionary<int,string> versionDefines, bool isPackageDependent = false, string packageName ="")
{
string wwiseVersion = AkUnitySoundEngine.WwiseVersion;
string shortWwiseVersion = wwiseVersion.Substring(0, 4);
int wwiseVersionAsInteger = int.Parse(shortWwiseVersion);
int minimalVersion = wwiseVersionAsInteger;
if (isPackageDependent)
{
var listRequest = Client.List();
while (!listRequest.IsCompleted) { }
if (listRequest.Status == StatusCode.Success)
{
foreach (var package in listRequest.Result)
{
if (package.name == packageName)
{
string[] versionParts = package.version.Split('.');
int.TryParse(versionParts[0], out int packageMajorVersion);
if (packageMajorVersion < minimalVersion)
{
minimalVersion = packageMajorVersion;
}
}
}
}
}
//Add version defines with the wwise version as key if a new define is needed.
if (wwiseVersionAsInteger >= 2023)
{
foreach (BuildTargetGroup targetGroup in GetNonObsoleteTargetGroups())
{
#if UNITY_5_4_OR_NEWER
if (targetGroup == BuildTargetGroup.Unknown)
{
continue;
}
#endif
var namedTarget = UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(targetGroup);
string defines = PlayerSettings.GetScriptingDefineSymbols(namedTarget);
for (int i = 2023; i <= minimalVersion; ++i)
{
if (versionDefines.ContainsKey(i))
{
Match match = Regex.Match(defines, versionDefines[i]);
if (!match.Success)
{
defines += ";" + versionDefines[i];
}
}
}
PlayerSettings.SetScriptingDefineSymbols(namedTarget, defines);
}
}
SetAddressableAdapterSymbol();
}
// Create a Wwise Global object containing the initializer and terminator scripts. Set the SoundBank path of the initializer script.
// This game object will live for the whole project; there is no need to instanciate one per scene.
private static void CreateWwiseGlobalObject()
{
// Look for a game object which has the initializer component
#if UNITY_6000_0_OR_NEWER
var AkInitializers = UnityEngine.Object.FindObjectsByType<AkInitializer>(FindObjectsSortMode.None);
#else
var AkInitializers = UnityEngine.Object.FindObjectsOfType<AkInitializer>();
#endif
if (AkInitializers.Length > 0)
UnityEditor.Undo.DestroyObjectImmediate(AkInitializers[0].gameObject);
var WwiseGlobalGameObject = new UnityEngine.GameObject("WwiseGlobal");
// attach initializer component
UnityEditor.Undo.AddComponent<AkInitializer>(WwiseGlobalGameObject);
}
private static bool DisableBuiltInAudio()
{
UnityEditor.SerializedObject audioSettingsAsset = null;
UnityEditor.SerializedProperty disableAudioProperty = null;
var assets = UnityEditor.AssetDatabase.LoadAllAssetsAtPath("ProjectSettings/AudioManager.asset");
if (assets.Length > 0)
audioSettingsAsset = new UnityEditor.SerializedObject(assets[0]);
if (audioSettingsAsset != null)
disableAudioProperty = audioSettingsAsset.FindProperty("m_DisableAudio");
if (disableAudioProperty == null)
return false;
disableAudioProperty.boolValue = true;
audioSettingsAsset.ApplyModifiedProperties();
return true;
}
private static void MigrateRootOutputPath(string wprojPath)
{
if (string.IsNullOrEmpty(AkWwiseEditorSettings.Instance.RootOutputPath))
{
var defaultRootOutputPath = AkBasePathGetter.GetDefaultRootOutputPath();
var pathRelativeToApplicationDataPath = AkUtilities.MakeRelativePath(UnityEngine.Application.dataPath, defaultRootOutputPath);
AkWwiseEditorSettings.Instance.RootOutputPath = pathRelativeToApplicationDataPath;
AkWwiseEditorSettings.Instance.SaveSettings();
}
if (AkUtilities.IsMigrationRequired(AkUtilities.MigrationStep.RootOutputPath_v2025_1_0))
{
AkWwiseEditorSettings.MigrateRootOutputPath(wprojPath);
}
}
// Modify the .wproj file to set needed SoundBank settings
private static bool SetSoundbankSettings()
{
var settings = AkWwiseEditorSettings.Instance;
if (string.IsNullOrEmpty(settings.WwiseProjectPath))
return true;
var SoundbankPath = AkBasePathGetter.GetDefaultRootOutputPath();
if (AkWwiseEditorSettings.Instance.RootOutputPath != null)
{
var rootOutputPath = AkWwiseEditorSettings.GetRootOutputPath();
var r = new Regex(Regex.Escape("_WwiseIntegrationTemp"));
SoundbankPath = r.Replace(rootOutputPath, "", 1);
}
if (SoundbankPath == null)
{
Debug.LogWarning("Could not get Default Root Output Path.");
return false;
}
var WprojPath = AkUtilities.GetFullPath(UnityEngine.Application.dataPath, settings.WwiseProjectPath);
#if UNITY_EDITOR_OSX
SoundbankPath = "Z:" + SoundbankPath;
#endif
MigrateRootOutputPath(WprojPath);
string[] settingsToDisable = {"GenerateSoundBankXML"};
string[] settingsToEnable = {"SoundBankGenerateHeaderFile", "SoundBankGenerateMaxAttenuationInfo", "GenerateSoundBankJSON", "SoundBankGeneratePrintGUID", "SoundBankGeneratePrintPath", "AutoSoundBankEnabled"};
if (AkUtilities.SetSoundbankHeaderFilePath(WprojPath, SoundbankPath))
if (AkUtilities.ToggleBoolSoundbankSettingInWproj(settingsToDisable, WprojPath, false))
return AkUtilities.ToggleBoolSoundbankSettingInWproj(settingsToEnable, WprojPath, true);
return false;
}
public static void AddAkAudioListenerToMainCamera(bool logWarning = false)
{
UnityEngine.Camera camera = UnityEngine.Camera.main;
// Workaround for some versions of Unity not setting properly the MainCamera tag
// on the first scene of a new project
if (camera == null)
{
#if UNITY_6000_0_OR_NEWER
var cameraArray = UnityEngine.Object.FindObjectsByType<UnityEngine.Camera>(FindObjectsSortMode.None);
#else
var cameraArray = UnityEngine.Object.FindObjectsOfType<UnityEngine.Camera>();
#endif
if (cameraArray.Length > 0)
{
foreach (var entry in cameraArray)
{
if (entry.name == "Main Camera")
{
camera = entry;
break;
}
}
}
if (camera == null)
{
return;
}
}
if (camera.GetComponentInChildren<AkAudioListener>())
{
return;
}
var oldListener = camera.gameObject.GetComponent<UnityEngine.AudioListener>();
if (oldListener != null)
{
UnityEditor.Undo.DestroyObjectImmediate(oldListener);
}
var akAudioListener = UnityEditor.Undo.AddComponent<AkAudioListener>(camera.gameObject);
if (!akAudioListener)
{
return;
}
var akGameObj = akAudioListener.GetComponentInChildren<AkGameObj>();
if (akGameObj)
{
akGameObj.isEnvironmentAware = false;
}
if (logWarning)
{
UnityEngine.Debug.Log("Automatically added AkAudioListener to Main Camera. Go to \"Edit > Wwise Settings...\" to disable this functionality.");
}
}
public static BuildTargetGroup[] GetNonObsoleteTargetGroups()
{
System.Type enumType = typeof(BuildTargetGroup);
return System.Enum.GetValues(enumType).Cast<BuildTargetGroup>().Where(targetGroup =>
{
string name = targetGroup.ToString();
MemberInfo member = enumType.GetMember(name).FirstOrDefault();
if (member == null) return false;
return member.GetCustomAttribute<System.ObsoleteAttribute>() == null;
}).ToArray();
}
private static void SetAddressableAdapterSymbol()
{
foreach (BuildTargetGroup targetGroup in GetNonObsoleteTargetGroups())
{
#if UNITY_5_4_OR_NEWER
if (targetGroup == BuildTargetGroup.Unknown)
{
continue;
}
#endif
var namedTarget = UnityEditor.Build.NamedBuildTarget.FromBuildTargetGroup(targetGroup);
if (PlayerSettings.GetScriptingDefineSymbols(namedTarget).Contains(WwiseAddressableAPIDefine))
{
continue;
}
string currentDefines = PlayerSettings.GetScriptingDefineSymbols(namedTarget);
var currentDefineList = currentDefines.Split(';').ToList();
const string wwiseAddressablePrefix = "ADDRESSABLES_API";
currentDefineList.RemoveAll(define => define.StartsWith(wwiseAddressablePrefix));
currentDefineList.Add(WwiseAddressableAPIDefine);
string newDefinesString = string.Join(";", currentDefineList.Distinct());
PlayerSettings.SetScriptingDefineSymbols(namedTarget, newDefinesString);
}
}
}
#endif // UNITY_EDITOR
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 90f5790a76fd1f4449499e336513354d
@@ -0,0 +1,56 @@
/*******************************************************************************
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 !UNITY_2021_1_OR_NEWER
public static class AkXboxOneUtils
{
private static readonly int[] Usages = { 0, 1, 4, 7 };
private static readonly int SessionRequirement = 0;
private static readonly int[] DeviceUsages = { 0 };
[UnityEditor.MenuItem("Assets/Wwise/Xbox One/Enable Network Sockets")]
public static void EnableXboxOneNetworkSockets()
{
var definitions = new[]
{
new SocketDefinition("WwiseDiscoverySocket", "24024", 1, "WwiseDiscovery"),
new SocketDefinition("WwiseCommandSocket", "24025", 0, "WwiseCommand")
};
foreach (var def in definitions)
{
UnityEditor.PlayerSettings.XboxOne.SetSocketDefinition(def.Name, def.Port, def.Protocol, Usages, def.TemplateName,
SessionRequirement, DeviceUsages);
}
}
private class SocketDefinition
{
public readonly string Name;
public readonly string Port;
public readonly int Protocol;
public readonly string TemplateName;
public SocketDefinition(string name, string port, int protocol, string templateName)
{
Name = name;
Port = port;
Protocol = protocol;
TemplateName = templateName;
}
}
}
#endif
@@ -0,0 +1,2 @@
fileFormatVersion: 2
guid: 6ff0287eef1770945b7f6cc88ed7ce3e