2026-03-14 03:13:10 -04:00
using UnityEngine ;
2025-06-03 02:42:28 -04:00
#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 .
2026-03-14 03:13:10 -04:00
Copyright ( c ) 2025 Audiokinetic Inc .
2025-06-03 02:42:28 -04:00
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * /
[UnityEditor.CanEditMultipleObjects]
2026-03-14 03:13:10 -04:00
[UnityEditor.CustomEditor(typeof(AkAmbient), true)]
2025-06-03 02:42:28 -04:00
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 ] ;
2026-03-14 03:13:10 -04:00
WwiseProjectDatabase . SoundBankDirectoryUpdated + = PopulateMaxAttenuation ;
2025-06-03 02:42:28 -04:00
}
public new void OnDisable ( )
{
base . OnDisable ( ) ;
DefaultHandles . Hidden = false ;
2026-03-14 03:13:10 -04:00
WwiseProjectDatabase . SoundBankDirectoryUpdated - = PopulateMaxAttenuation ;
2025-06-03 02:42:28 -04:00
}
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
2026-03-14 03:13:10 -04:00
#if UNITY_6000_0_OR_NEWER
var akAmbients = FindObjectsByType < AkAmbient > ( FindObjectsSortMode . None ) ;
#else
2025-06-03 02:42:28 -04:00
var akAmbients = FindObjectsOfType < AkAmbient > ( ) ;
2026-03-14 03:13:10 -04:00
#endif
2025-06-03 02:42:28 -04:00
//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" )
{
2026-03-14 03:13:10 -04:00
#if UNITY_6000_0_OR_NEWER
var akAmbients = FindObjectsByType < AkAmbient > ( FindObjectsSortMode . None ) ;
#else
2025-06-03 02:42:28 -04:00
var akAmbients = FindObjectsOfType < AkAmbient > ( ) ;
2026-03-14 03:13:10 -04:00
#endif
2025-06-03 02:42:28 -04:00
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)
2026-03-14 03:13:10 -04:00
var radius = AkWwiseProjectInfo . GetData ( ) . GetEventMaxAttenuation ( m_AkAmbient . data . Id ) * m_AkAmbient . gameObject . GetComponent < AkGameObj > ( ) . ScalingFactor ;
2025-06-03 02:42:28 -04:00
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
{
2026-03-14 03:13:10 -04:00
#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 + + )
2025-06-03 02:42:28 -04:00
{
2026-03-14 03:13:10 -04:00
if ( akAmbients [ i ] . multiPositionTypeLabel = = MultiPositionTypeLabel . MultiPosition_Mode & &
akAmbients [ i ] . data . Id = = m_AkAmbient . data . Id )
2025-06-03 02:42:28 -04:00
{
2026-03-14 03:13:10 -04:00
DrawSphere ( akAmbients [ i ] . gameObject . transform . position , radius , akAmbients [ i ] . attenuationSphereColor ) ;
2025-06-03 02:42:28 -04:00
}
}
}
}
else
{
2026-03-14 03:13:10 -04:00
#if UNITY_6000_0_OR_NEWER
var akAmbients = FindObjectsByType < AkAmbient > ( FindObjectsSortMode . None ) ;
#else
var akAmbients = FindObjectsOfType < AkAmbient > ( ) ;
#endif
2025-06-03 02:42:28 -04:00
2026-03-14 03:13:10 -04:00
for ( var i = 0 ; i < akAmbients . Length ; i + + )
2025-06-03 02:42:28 -04:00
{
// Get the max attenuation for the event (if available)
2026-03-14 03:13:10 -04:00
var radius = AkWwiseProjectInfo . GetData ( ) . GetEventMaxAttenuation ( akAmbients [ i ] . data . Id ) ;
2025-06-03 02:42:28 -04:00
2026-03-14 03:13:10 -04:00
if ( akAmbients [ i ] . multiPositionTypeLabel = = MultiPositionTypeLabel . Large_Mode )
2025-06-03 02:42:28 -04:00
{
var positionComponents = m_AkAmbient . GetComponentsInChildren < AkAmbientLargeModePositioner > ( ) ;
for ( int j = 0 ; j < positionComponents . Length ; j + + )
{
2026-03-14 03:13:10 -04:00
DrawSphere ( positionComponents [ j ] . transform . position , radius , akAmbients [ i ] . attenuationSphereColor ) ;
2025-06-03 02:42:28 -04:00
}
}
else
{
2026-03-14 03:13:10 -04:00
DrawSphere ( akAmbients [ i ] . gameObject . transform . position , radius , akAmbients [ i ] . attenuationSphereColor ) ;
2025-06-03 02:42:28 -04:00
}
}
}
}
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