Files
AppleHillsProduction/Assets/Scripts/Sound/AudioManager.cs

294 lines
11 KiB
C#
Raw Normal View History

2025-10-17 14:38:42 +02:00
using UnityEngine;
2025-10-28 13:19:33 +01:00
using UnityEngine.Audio;
using AppleHills.Core;
using AppleHills.Core.Interfaces;
2025-10-29 17:01:02 +01:00
using System.Collections.Generic;
using AudioSourceEvents;
using System;
Refactor interactions, introduce template-method lifecycle management, work on save-load system (#51) # Lifecycle Management & Save System Revamp ## Overview Complete overhaul of game lifecycle management, interactable system, and save/load architecture. Introduces centralized `ManagedBehaviour` base class for consistent initialization ordering and lifecycle hooks across all systems. ## Core Architecture ### New Lifecycle System - **`LifecycleManager`**: Centralized coordinator for all managed objects - **`ManagedBehaviour`**: Base class replacing ad-hoc initialization patterns - `OnManagedAwake()`: Priority-based initialization (0-100, lower = earlier) - `OnSceneReady()`: Scene-specific setup after managers ready - Replaces `BootCompletionService` (deleted) - **Priority groups**: Infrastructure (0-20) → Game Systems (30-50) → Data (60-80) → UI/Gameplay (90-100) - **Editor support**: `EditorLifecycleBootstrap` ensures lifecycle works in editor mode ### Unified SaveID System - Consistent format: `{ParentName}_{ComponentType}` - Auto-registration via `AutoRegisterForSave = true` - New `DebugSaveIds` editor tool for inspection ## Save/Load Improvements ### Enhanced State Management - **Extended SaveLoadData**: Unlocked minigames, card collection states, combination items, slot occupancy - **Async loading**: `ApplyCardCollectionState()` waits for card definitions before restoring - **New `SaveablePlayableDirector`**: Timeline sequences save/restore playback state - **Fixed race conditions**: Proper initialization ordering prevents data corruption ## Interactable & Pickup System - Migrated to `OnManagedAwake()` for consistent initialization - Template method pattern for state restoration (`RestoreInteractionState()`) - Fixed combination item save/load bugs (items in slots vs. follower hand) - Dynamic spawning support for combined items on load - **Breaking**: `Interactable.Awake()` now sealed, use `OnManagedAwake()` instead ## UI System Changes - **AlbumViewPage** and **BoosterNotificationDot**: Migrated to `ManagedBehaviour` - **Fixed menu persistence bug**: Menus no longer reappear after scene transitions - **Pause Menu**: Now reacts to all scene loads (not just first scene) - **Orientation Enforcer**: Enforces per-scene via `SceneManagementService` - **Loading Screen**: Integrated with new lifecycle ## ⚠️ Breaking Changes 1. **`BootCompletionService` removed** → Use `ManagedBehaviour.OnManagedAwake()` with priority 2. **`Interactable.Awake()` sealed** → Override `OnManagedAwake()` instead 3. **SaveID format changed** → Now `{ParentName}_{ComponentType}` consistently 4. **MonoBehaviours needing init ordering** → Must inherit from `ManagedBehaviour` Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/51
2025-11-07 15:38:31 +00:00
using Core.Lifecycle;
2025-10-17 14:38:42 +02:00
Refactor interactions, introduce template-method lifecycle management, work on save-load system (#51) # Lifecycle Management & Save System Revamp ## Overview Complete overhaul of game lifecycle management, interactable system, and save/load architecture. Introduces centralized `ManagedBehaviour` base class for consistent initialization ordering and lifecycle hooks across all systems. ## Core Architecture ### New Lifecycle System - **`LifecycleManager`**: Centralized coordinator for all managed objects - **`ManagedBehaviour`**: Base class replacing ad-hoc initialization patterns - `OnManagedAwake()`: Priority-based initialization (0-100, lower = earlier) - `OnSceneReady()`: Scene-specific setup after managers ready - Replaces `BootCompletionService` (deleted) - **Priority groups**: Infrastructure (0-20) → Game Systems (30-50) → Data (60-80) → UI/Gameplay (90-100) - **Editor support**: `EditorLifecycleBootstrap` ensures lifecycle works in editor mode ### Unified SaveID System - Consistent format: `{ParentName}_{ComponentType}` - Auto-registration via `AutoRegisterForSave = true` - New `DebugSaveIds` editor tool for inspection ## Save/Load Improvements ### Enhanced State Management - **Extended SaveLoadData**: Unlocked minigames, card collection states, combination items, slot occupancy - **Async loading**: `ApplyCardCollectionState()` waits for card definitions before restoring - **New `SaveablePlayableDirector`**: Timeline sequences save/restore playback state - **Fixed race conditions**: Proper initialization ordering prevents data corruption ## Interactable & Pickup System - Migrated to `OnManagedAwake()` for consistent initialization - Template method pattern for state restoration (`RestoreInteractionState()`) - Fixed combination item save/load bugs (items in slots vs. follower hand) - Dynamic spawning support for combined items on load - **Breaking**: `Interactable.Awake()` now sealed, use `OnManagedAwake()` instead ## UI System Changes - **AlbumViewPage** and **BoosterNotificationDot**: Migrated to `ManagedBehaviour` - **Fixed menu persistence bug**: Menus no longer reappear after scene transitions - **Pause Menu**: Now reacts to all scene loads (not just first scene) - **Orientation Enforcer**: Enforces per-scene via `SceneManagementService` - **Loading Screen**: Integrated with new lifecycle ## ⚠️ Breaking Changes 1. **`BootCompletionService` removed** → Use `ManagedBehaviour.OnManagedAwake()` with priority 2. **`Interactable.Awake()` sealed** → Override `OnManagedAwake()` instead 3. **SaveID format changed** → Now `{ParentName}_{ComponentType}` consistently 4. **MonoBehaviours needing init ordering** → Must inherit from `ManagedBehaviour` Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/51
2025-11-07 15:38:31 +00:00
public class AudioManager : ManagedBehaviour, IPausable
2025-10-17 14:38:42 +02:00
{
2025-10-28 13:19:33 +01:00
/// <summary>
/// Play all audio, just music or no audio at all when the game is paused.
/// </summary>
public enum PauseBehavior
2025-10-29 17:01:02 +01:00
{ PlayAllAudio, MusicOnly, NoAudio }
2025-10-28 13:19:33 +01:00
public PauseBehavior currentPauseBehavior;
2025-10-29 17:01:02 +01:00
public AudioMixer audioMixer;
2025-10-28 13:19:33 +01:00
private AudioListener _audioListener;
2025-10-29 17:01:02 +01:00
public AppleAudioSource currentlyPlayingVO;
2025-10-28 13:19:33 +01:00
private static AudioManager _instance;
private GameObject _player;
2025-10-29 17:01:02 +01:00
public List<AppleAudioSource> criticalVOSources;
public List<AppleAudioSource> VOSources;
public List<AppleAudioSource> musicSources;
public List<AppleAudioSource> ambienceSources;
public List<AppleAudioSource> SFXSources;
private IAudioEventSource _eventSource;
2025-10-30 14:17:47 +01:00
private bool wasInterrupted;
2025-10-29 17:01:02 +01:00
2025-10-28 13:19:33 +01:00
/// <summary>
/// Singleton instance of the AudioManager.
/// </summary>
public static AudioManager Instance => _instance;
Refactor interactions, introduce template-method lifecycle management, work on save-load system (#51) # Lifecycle Management & Save System Revamp ## Overview Complete overhaul of game lifecycle management, interactable system, and save/load architecture. Introduces centralized `ManagedBehaviour` base class for consistent initialization ordering and lifecycle hooks across all systems. ## Core Architecture ### New Lifecycle System - **`LifecycleManager`**: Centralized coordinator for all managed objects - **`ManagedBehaviour`**: Base class replacing ad-hoc initialization patterns - `OnManagedAwake()`: Priority-based initialization (0-100, lower = earlier) - `OnSceneReady()`: Scene-specific setup after managers ready - Replaces `BootCompletionService` (deleted) - **Priority groups**: Infrastructure (0-20) → Game Systems (30-50) → Data (60-80) → UI/Gameplay (90-100) - **Editor support**: `EditorLifecycleBootstrap` ensures lifecycle works in editor mode ### Unified SaveID System - Consistent format: `{ParentName}_{ComponentType}` - Auto-registration via `AutoRegisterForSave = true` - New `DebugSaveIds` editor tool for inspection ## Save/Load Improvements ### Enhanced State Management - **Extended SaveLoadData**: Unlocked minigames, card collection states, combination items, slot occupancy - **Async loading**: `ApplyCardCollectionState()` waits for card definitions before restoring - **New `SaveablePlayableDirector`**: Timeline sequences save/restore playback state - **Fixed race conditions**: Proper initialization ordering prevents data corruption ## Interactable & Pickup System - Migrated to `OnManagedAwake()` for consistent initialization - Template method pattern for state restoration (`RestoreInteractionState()`) - Fixed combination item save/load bugs (items in slots vs. follower hand) - Dynamic spawning support for combined items on load - **Breaking**: `Interactable.Awake()` now sealed, use `OnManagedAwake()` instead ## UI System Changes - **AlbumViewPage** and **BoosterNotificationDot**: Migrated to `ManagedBehaviour` - **Fixed menu persistence bug**: Menus no longer reappear after scene transitions - **Pause Menu**: Now reacts to all scene loads (not just first scene) - **Orientation Enforcer**: Enforces per-scene via `SceneManagementService` - **Loading Screen**: Integrated with new lifecycle ## ⚠️ Breaking Changes 1. **`BootCompletionService` removed** → Use `ManagedBehaviour.OnManagedAwake()` with priority 2. **`Interactable.Awake()` sealed** → Override `OnManagedAwake()` instead 3. **SaveID format changed** → Now `{ParentName}_{ComponentType}` consistently 4. **MonoBehaviours needing init ordering** → Must inherit from `ManagedBehaviour` Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/51
2025-11-07 15:38:31 +00:00
// ManagedBehaviour configuration
public override int ManagedAwakePriority => 30; // Audio infrastructure
public override bool AutoRegisterPausable => true; // Auto-register as IPausable
private new void Awake()
2025-10-28 13:19:33 +01:00
{
Refactor interactions, introduce template-method lifecycle management, work on save-load system (#51) # Lifecycle Management & Save System Revamp ## Overview Complete overhaul of game lifecycle management, interactable system, and save/load architecture. Introduces centralized `ManagedBehaviour` base class for consistent initialization ordering and lifecycle hooks across all systems. ## Core Architecture ### New Lifecycle System - **`LifecycleManager`**: Centralized coordinator for all managed objects - **`ManagedBehaviour`**: Base class replacing ad-hoc initialization patterns - `OnManagedAwake()`: Priority-based initialization (0-100, lower = earlier) - `OnSceneReady()`: Scene-specific setup after managers ready - Replaces `BootCompletionService` (deleted) - **Priority groups**: Infrastructure (0-20) → Game Systems (30-50) → Data (60-80) → UI/Gameplay (90-100) - **Editor support**: `EditorLifecycleBootstrap` ensures lifecycle works in editor mode ### Unified SaveID System - Consistent format: `{ParentName}_{ComponentType}` - Auto-registration via `AutoRegisterForSave = true` - New `DebugSaveIds` editor tool for inspection ## Save/Load Improvements ### Enhanced State Management - **Extended SaveLoadData**: Unlocked minigames, card collection states, combination items, slot occupancy - **Async loading**: `ApplyCardCollectionState()` waits for card definitions before restoring - **New `SaveablePlayableDirector`**: Timeline sequences save/restore playback state - **Fixed race conditions**: Proper initialization ordering prevents data corruption ## Interactable & Pickup System - Migrated to `OnManagedAwake()` for consistent initialization - Template method pattern for state restoration (`RestoreInteractionState()`) - Fixed combination item save/load bugs (items in slots vs. follower hand) - Dynamic spawning support for combined items on load - **Breaking**: `Interactable.Awake()` now sealed, use `OnManagedAwake()` instead ## UI System Changes - **AlbumViewPage** and **BoosterNotificationDot**: Migrated to `ManagedBehaviour` - **Fixed menu persistence bug**: Menus no longer reappear after scene transitions - **Pause Menu**: Now reacts to all scene loads (not just first scene) - **Orientation Enforcer**: Enforces per-scene via `SceneManagementService` - **Loading Screen**: Integrated with new lifecycle ## ⚠️ Breaking Changes 1. **`BootCompletionService` removed** → Use `ManagedBehaviour.OnManagedAwake()` with priority 2. **`Interactable.Awake()` sealed** → Override `OnManagedAwake()` instead 3. **SaveID format changed** → Now `{ParentName}_{ComponentType}` consistently 4. **MonoBehaviours needing init ordering** → Must inherit from `ManagedBehaviour` Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/51
2025-11-07 15:38:31 +00:00
base.Awake(); // CRITICAL: Register with LifecycleManager!
// Set instance immediately so it's available before OnManagedAwake() is called
2025-10-28 13:19:33 +01:00
_instance = this;
}
Refactor interactions, introduce template-method lifecycle management, work on save-load system (#51) # Lifecycle Management & Save System Revamp ## Overview Complete overhaul of game lifecycle management, interactable system, and save/load architecture. Introduces centralized `ManagedBehaviour` base class for consistent initialization ordering and lifecycle hooks across all systems. ## Core Architecture ### New Lifecycle System - **`LifecycleManager`**: Centralized coordinator for all managed objects - **`ManagedBehaviour`**: Base class replacing ad-hoc initialization patterns - `OnManagedAwake()`: Priority-based initialization (0-100, lower = earlier) - `OnSceneReady()`: Scene-specific setup after managers ready - Replaces `BootCompletionService` (deleted) - **Priority groups**: Infrastructure (0-20) → Game Systems (30-50) → Data (60-80) → UI/Gameplay (90-100) - **Editor support**: `EditorLifecycleBootstrap` ensures lifecycle works in editor mode ### Unified SaveID System - Consistent format: `{ParentName}_{ComponentType}` - Auto-registration via `AutoRegisterForSave = true` - New `DebugSaveIds` editor tool for inspection ## Save/Load Improvements ### Enhanced State Management - **Extended SaveLoadData**: Unlocked minigames, card collection states, combination items, slot occupancy - **Async loading**: `ApplyCardCollectionState()` waits for card definitions before restoring - **New `SaveablePlayableDirector`**: Timeline sequences save/restore playback state - **Fixed race conditions**: Proper initialization ordering prevents data corruption ## Interactable & Pickup System - Migrated to `OnManagedAwake()` for consistent initialization - Template method pattern for state restoration (`RestoreInteractionState()`) - Fixed combination item save/load bugs (items in slots vs. follower hand) - Dynamic spawning support for combined items on load - **Breaking**: `Interactable.Awake()` now sealed, use `OnManagedAwake()` instead ## UI System Changes - **AlbumViewPage** and **BoosterNotificationDot**: Migrated to `ManagedBehaviour` - **Fixed menu persistence bug**: Menus no longer reappear after scene transitions - **Pause Menu**: Now reacts to all scene loads (not just first scene) - **Orientation Enforcer**: Enforces per-scene via `SceneManagementService` - **Loading Screen**: Integrated with new lifecycle ## ⚠️ Breaking Changes 1. **`BootCompletionService` removed** → Use `ManagedBehaviour.OnManagedAwake()` with priority 2. **`Interactable.Awake()` sealed** → Override `OnManagedAwake()` instead 3. **SaveID format changed** → Now `{ParentName}_{ComponentType}` consistently 4. **MonoBehaviours needing init ordering** → Must inherit from `ManagedBehaviour` Co-authored-by: Michal Pikulski <michal.a.pikulski@gmail.com> Co-authored-by: Michal Pikulski <michal@foolhardyhorizons.com> Reviewed-on: https://homelab.tailf7f81b.ts.net/tschesky/AppleHillsProduction/pulls/51
2025-11-07 15:38:31 +00:00
protected override void OnManagedAwake()
2025-10-28 13:19:33 +01:00
{
// Initialize lists if they were not set in inspector
criticalVOSources = criticalVOSources ?? new List<AppleAudioSource>();
VOSources = VOSources ?? new List<AppleAudioSource>();
musicSources = musicSources ?? new List<AppleAudioSource>();
ambienceSources = ambienceSources ?? new List<AppleAudioSource>();
SFXSources = SFXSources ?? new List<AppleAudioSource>();
2025-10-28 13:19:33 +01:00
// Perform singleton-dependent initialization here
if (QuickAccess.Instance != null)
{
_player = QuickAccess.Instance.PlayerGameObject;
if (QuickAccess.Instance.MainCamera != null)
{
_audioListener = QuickAccess.Instance.MainCamera.GetComponent<AudioListener>();
}
}
else
{
Debug.LogWarning("[AudioManager] QuickAccess.Instance is null during OnManagedAwake. Some audio references may remain unset.");
}
// Diagnostic
2025-10-29 17:01:02 +01:00
foreach (AppleAudioSource _audioSource in criticalVOSources)
{
Debug.Log("Found source: " + _audioSource.name);
}
Debug.Log("[AudioManager] OnManagedAwake completed");
2025-10-28 13:19:33 +01:00
}
public void SetAudioPauseBehavior(PauseBehavior newPauseBehavior)
{
switch (newPauseBehavior)
{
case PauseBehavior.PlayAllAudio:
2025-10-29 17:01:02 +01:00
audioMixer.updateMode = AudioMixerUpdateMode.UnscaledTime;
2025-10-28 13:19:33 +01:00
AudioListener.pause = false;
break;
case PauseBehavior.MusicOnly:
2025-10-29 17:01:02 +01:00
audioMixer.updateMode = AudioMixerUpdateMode.UnscaledTime; break;
2025-10-28 13:19:33 +01:00
//TODO: Pause all audio mixers except music mixer
case PauseBehavior.NoAudio:
2025-10-29 17:01:02 +01:00
audioMixer.updateMode = AudioMixerUpdateMode.Normal;
2025-10-28 13:19:33 +01:00
AudioListener.pause = true;
break;
}
}
2025-10-29 17:01:02 +01:00
public LevelAudioObject GetCurrentLevelAudioObject()
{
Debug.Log("Audio objects: " + FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length);
if (FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length > 1)
{
Debug.LogWarning("Warning! More than one LevelAudioObject in the level! Using the first one found");
return FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None)[0];
}
if (FindObjectsByType<LevelAudioObject>(FindObjectsInactive.Include, FindObjectsSortMode.None).Length == 0)
{
Debug.LogWarning("Error! No LevelAudioObject found, AudioManager might not function properly!");
return null;
}
else
return FindFirstObjectByType<LevelAudioObject>();
}
2025-10-28 13:19:33 +01:00
public void Pause()
{
SetAudioPauseBehavior(PauseBehavior.NoAudio);
2025-10-17 14:38:42 +02:00
}
2025-10-28 13:19:33 +01:00
public void DoResume()
2025-10-20 13:57:38 +02:00
{
2025-10-28 13:19:33 +01:00
SetAudioPauseBehavior(PauseBehavior.PlayAllAudio);
2025-10-17 14:38:42 +02:00
}
2025-10-29 17:01:02 +01:00
public void RegisterNewAudioSource(AppleAudioSource newAudioSource)
{
switch (newAudioSource.audioSourceType)
{
case AppleAudioSource.AudioSourceType.CriticalVO:
criticalVOSources.Add(newAudioSource);
break;
case AppleAudioSource.AudioSourceType.VO:
VOSources.Add(newAudioSource);
break;
case AppleAudioSource.AudioSourceType.SFX:
SFXSources.Add(newAudioSource);
break;
case AppleAudioSource.AudioSourceType.Ambience:
ambienceSources.Add(newAudioSource);
break;
case AppleAudioSource.AudioSourceType.Music:
musicSources.Add(newAudioSource);
break;
}
}
/// <summary>
/// Request playing a VO line. Returns true if whatever is playing is not critical, or weight of requested VO line is lower.
/// </summary>
public bool RequestPlayVO(AppleAudioSource requestedAudioSource)
{
2025-10-30 14:17:47 +01:00
//Debug.Log($"[AUDIOMANAGER] CurrentVO source prio: {currentlyPlayingVO.sourcePriority}, clip prio: {currentlyPlayingVO.clipPriority} requested VO prio: {requestedAudioSource.sourcePriority}, clip prio: {clipPriority}");
// If nothing is playing, let the requested audio source play
2025-10-29 17:01:02 +01:00
if (currentlyPlayingVO == null)
{
2025-10-30 14:17:47 +01:00
SetupNewAudioSource(requestedAudioSource);
Debug.Log($"[AUDIOMANAGER] Playing {currentlyPlayingVO.name} as nothing is currently playing.");
2025-10-29 17:01:02 +01:00
return true;
}
2025-10-30 16:31:01 +01:00
// If the requested audio is not critical, and the currently playing audio is, tell the request to get bent
if (requestedAudioSource.audioSourceType == AppleAudioSource.AudioSourceType.VO && currentlyPlayingVO.audioSourceType == AppleAudioSource.AudioSourceType.CriticalVO)
{
return false;
}
2025-10-30 14:17:47 +01:00
// If the requested audio source is the same, interrupt and trigger it again
if (currentlyPlayingVO == requestedAudioSource)
2025-10-29 17:01:02 +01:00
{
2025-10-30 14:17:47 +01:00
InterruptAudioSource(requestedAudioSource);
SetupNewAudioSource(requestedAudioSource);
Debug.Log($"[AUDIOMANAGER] {currentlyPlayingVO.name} is the same as {requestedAudioSource.name}. Triggering it again.");
2025-10-29 17:01:02 +01:00
return true;
2025-10-30 14:17:47 +01:00
2025-10-29 17:01:02 +01:00
}
2025-10-30 14:17:47 +01:00
// if the currently playing audio source is not critical, interrupt it and play the requested audio source
if (currentlyPlayingVO.audioSourceType != AppleAudioSource.AudioSourceType.CriticalVO)
{
InterruptAudioSource(requestedAudioSource);
SetupNewAudioSource(requestedAudioSource);
Debug.Log($"[AUDIOMANAGER] {currentlyPlayingVO.name} is not critical. Playing {requestedAudioSource.name} instead because it is critical.");
return true;
}
// If the requested audio source has the same priority as currently playing source, check the priority of the requested clip
if (currentlyPlayingVO.audioSourceType == AppleAudioSource.AudioSourceType.CriticalVO && currentlyPlayingVO.sourcePriority == requestedAudioSource.sourcePriority)
{
if (currentlyPlayingVO.clipPriority > requestedAudioSource.clipPriority)
{
InterruptAudioSource(requestedAudioSource);
SetupNewAudioSource(requestedAudioSource);
Debug.Log($"[AUDIOMANAGER] Interrupted {currentlyPlayingVO.name} because it has same priority as {requestedAudioSource.name} but the requested clip has higher priority");
return true;
}
else
{
return false;
}
}
// If the requested audio source has higher priority than the currently playing source, interrupt the current source and let the requested one play
if (currentlyPlayingVO.audioSourceType == AppleAudioSource.AudioSourceType.CriticalVO && currentlyPlayingVO.sourcePriority > requestedAudioSource.sourcePriority)
2025-10-29 17:01:02 +01:00
{
currentlyPlayingVO.InterruptAudio(requestedAudioSource.name);
2025-10-30 14:17:47 +01:00
Debug.Log($"[AUDIOMANAGER] Interrupted {currentlyPlayingVO.name} because {requestedAudioSource.name} has higher priority");
InterruptAudioSource(requestedAudioSource);
SetupNewAudioSource(requestedAudioSource);
2025-10-29 17:01:02 +01:00
return true;
}
2025-10-30 14:17:47 +01:00
// If the requested audio source didn't clear any of the above cases, tell it to get rekt.
2025-10-29 17:01:02 +01:00
else
2025-10-30 14:17:47 +01:00
{
Debug.Log($"[AUDIOMANAGER] {currentlyPlayingVO.name} is still playing. {requestedAudioSource.name} has lower priority");
2025-10-29 17:01:02 +01:00
return false;
}
}
private void OnApplicationQuit()
{
// TODO: Release the handles safely ReleaseAllHandles();
}
2025-10-30 14:17:47 +01:00
private void SetupNewAudioSource(AppleAudioSource audioSource)
2025-10-29 17:01:02 +01:00
{
2025-10-30 14:17:47 +01:00
if (audioSource.audioSource.resource == null)
2025-10-29 17:01:02 +01:00
{
2025-10-30 14:17:47 +01:00
Debug.Log($"[AUDIOMANAGER] Faled to setup {audioSource.name}. Invalid resource");
2025-10-29 17:01:02 +01:00
}
else
{
2025-10-30 14:17:47 +01:00
currentlyPlayingVO = audioSource;
_eventSource = audioSource.audioSource.RequestEventHandlers();
2025-10-29 17:01:02 +01:00
_eventSource.AudioStopped += OnAudioStopped;
_eventSource.AudioStarted += OnAudioStarted;
}
}
private void OnAudioStopped(object sender, EventArgs e)
{
2025-10-30 14:17:47 +01:00
if (wasInterrupted)
{
ResetAudioSource();
}
else
{
currentlyPlayingVO = null;
ResetAudioSource();
}
2025-10-29 17:01:02 +01:00
}
private void OnAudioStarted(object sender, EventArgs e)
{
}
2025-10-30 14:17:47 +01:00
private void ResetAudioSource()
{
_eventSource.AudioStopped -= OnAudioStopped;
_eventSource.AudioStarted -= OnAudioStarted;
wasInterrupted = false;
}
private void InterruptAudioSource(AppleAudioSource newAudioSource)
{
wasInterrupted = true;
//currentlyPlayingVO.InterruptAudio(newAudioSource.name);
InterruptAllVOSources();
2025-10-30 14:17:47 +01:00
ResetAudioSource();
currentlyPlayingVO = newAudioSource;
}
private void InterruptAllVOSources()
{
foreach (AppleAudioSource source in criticalVOSources)
{
source.InterruptAudio("GlobalInterrupt");
}
foreach (AppleAudioSource source in VOSources)
{
source.InterruptAudio("GlobalInterrupt");
}
}
2025-10-17 14:38:42 +02:00
}