/MultiplayerMA/Assets/Plugins/DarkTonic/MasterAudio/Scripts/Singleton/MasterAudio.cs
C# | 1266 lines | 995 code | 209 blank | 62 comment | 85 complexity | dc60249f4e6c5b1b6f235d25412b7cea MD5 | raw file
- using System.Linq;
- #if UNITY_EDITOR
- using UnityEditor;
- #endif
- using UnityEngine;
- using System;
- using System.Collections;
- using System.Collections.Generic;
- using UnityEngine.Audio;
- using Debug = UnityEngine.Debug;
- using Random = UnityEngine.Random;
- #if UNITY_2019_3_OR_NEWER
- using UnityEngine.Video;
- #endif
- #if UNITY_XBOXONE
- using PlayerPrefs = DarkTonic.MasterAudio.FilePlayerPrefs;
- #endif
- // ReSharper disable once CheckNamespace
- namespace DarkTonic.MasterAudio {
- /// <summary>
- /// This class contains the heart of the Master Audio API. There are also convenience methods here for Playlist Controllers, even though you can call those methods on the Playlist Controller itself as well.
- /// </summary>
- // ReSharper disable once CheckNamespace
- [AudioScriptOrder(-50)]
- public class MasterAudio : MonoBehaviour {
- /*! \cond PRIVATE */
- #region Constants
- #pragma warning disable 1591
- public const string VideoPlayersSoundGroupSelectedError = "Can't use specially named Sound Group for Video Players. Please select another.";
- public const string VideoPlayerSoundGroupName = "_VideoPlayers";
- public const string VideoPlayerBusName = "_VideoPlayers";
- public const string MasterAudioDefaultFolder = "Assets/Plugins/DarkTonic/MasterAudio";
- public const string PreviewText = "Random delay, custom fading & start/end position settings are ignored by preview in edit mode.";
- public const string LoopDisabledLoopedChain = "Loop Clip is always OFF for Looped Chain Groups";
- public const string LoopDisabledCustomEnd = "Loop Clip is always OFF when using Custom End Position";
- public const string DragAudioTip = "Drag Audio clips or a folder containing some here";
- public const string NoCategory = "[Uncategorized]";
- public const float SemiTonePitchFactor = 1.05946f;
- public const float SpatialBlend_2DValue = 0f;
- public const float SpatialBlend_3DValue = 1f;
- public const float MaxCrossFadeTimeSeconds = 120;
- public const float DefaultDuckVolCut = -6f;
- // error numbers
- public const int ERROR_MA_LAYER_COLLISIONS_DISABLED = 1;
- public const int PHYSICS_DISABLED = 2;
- public const string StoredLanguageNameKey = "~MA_Language_Key~";
- public static readonly YieldInstruction EndOfFrameDelay = new WaitForEndOfFrame();
- public static readonly List<string> ExemptChildNames = new List<string> { AmbientUtil.FollowerHolderName };
- public static readonly HashSet<int> ErrorNumbersLogged = new HashSet<int>();
- public static List<string> ImportanceChoices = new List<string> { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "10" };
- #if ADDRESSABLES_ENABLED
- public static List<string> AddressableDeadIds = new List<string>();
- #endif
- /// <summary>
- /// Subscribe to this event to be notified when the number of Audio Sources being used by Master Audio changes.
- /// </summary>
- // ReSharper disable once RedundantNameQualifier
- public static System.Action NumberOfAudioSourcesChanged;
- public const int HardCodedBusOptions = 2;
- public const string AllBusesName = "[All]";
- public const string NoGroupName = "[None]";
- public const string DynamicGroupName = "[Type In]";
- public const string NoPlaylistName = "[No Playlist]";
- public const string NoVoiceLimitName = "[NO LMT]";
- public const string OnlyPlaylistControllerName = "~only~";
- public const float InnerLoopCheckInterval = .1f;
- private const int MaxComponents = 20;
- #endregion
- #region Public Variables
- // ReSharper disable InconsistentNaming
- public AudioLocation bulkLocationMode = AudioLocation.Clip;
- public string groupTemplateName = "Default Single";
- public string audioSourceTemplateName = "Max Distance 500";
- public bool showGroupCreation = true;
- public bool useGroupTemplates = false;
- public DragGroupMode curDragGroupMode = DragGroupMode.OneGroupPerClip;
- public List<GameObject> groupTemplates = new List<GameObject>(10);
- public List<GameObject> audioSourceTemplates = new List<GameObject>(10);
- public bool mixerMuted;
- public bool playlistsMuted;
- public LanguageMode langMode = LanguageMode.UseDeviceSetting;
- public SystemLanguage testLanguage = SystemLanguage.English;
- public SystemLanguage defaultLanguage = SystemLanguage.English;
- public List<SystemLanguage> supportedLanguages = new List<SystemLanguage>()
- {
- SystemLanguage.English
- };
- public string busFilter = string.Empty;
- public bool useTextGroupFilter = false;
- public string textGroupFilter = string.Empty;
- public bool resourceClipsPauseDoNotUnload = false;
- public Transform playlistControllerPrefab;
- public bool persistBetweenScenes = false;
- public bool shouldLogDestroys = false;
- public bool showBusColors = false;
- public bool showGroupImportance = false;
- public bool areGroupsExpanded = true;
- public Transform soundGroupTemplate;
- public Transform soundGroupVariationTemplate;
- public List<GroupBus> groupBuses = new List<GroupBus>();
- public bool groupByBus = true;
- public bool sortAlpha = true;
- public bool showRangeSoundGizmos = true;
- public bool showSelectedRangeSoundGizmos = true;
- public Color rangeGizmoColor = Color.green;
- public Color selectedRangeGizmoColor = Color.cyan;
- public bool showAdvancedSettings = true;
- public bool showLocalization = true;
- public bool showVideoPlayerSettings = false;
- #if UNITY_2019_3_OR_NEWER && VIDEO_ENABLED
- public List<VideoPlayer> videoPlayers = new List<VideoPlayer>();
- #endif
- public bool useTextPlaylistFilter = false;
- public string textPlaylistFilter = string.Empty;
- public bool playListExpanded = true;
- public bool playlistsExpanded = true;
- public AllMusicSpatialBlendType musicSpatialBlendType = AllMusicSpatialBlendType.ForceAllTo2D;
- public float musicSpatialBlend = 0f;
- #if DISABLE_3D_SOUND
- public AllMixerSpatialBlendType mixerSpatialBlendType = AllMixerSpatialBlendType.ForceAllTo2D;
- #else
- public AllMixerSpatialBlendType mixerSpatialBlendType = AllMixerSpatialBlendType.ForceAllTo3D;
- #endif
- public float mixerSpatialBlend = 1f;
- public GroupPlayType groupPlayType = GroupPlayType.Always;
- public DefaultGroupPlayType defaultGroupPlayType = DefaultGroupPlayType.Always;
- #if DISABLE_3D_SOUND
- public ItemSpatialBlendType newGroupSpatialType = ItemSpatialBlendType.ForceTo2D;
- #else
- public ItemSpatialBlendType newGroupSpatialType = ItemSpatialBlendType.ForceTo3D;
- #endif
- public float newGroupSpatialBlend = 1f;
- public List<Playlist> musicPlaylists = new List<Playlist>()
- {
- new Playlist()
- };
- public float _masterAudioVolume = 1.0f;
- public bool vrSettingsExpanded = false;
- public bool useSpatializer = false;
- public bool useSpatializerPostFX = false;
- public bool addOculusAudioSources = false;
- public bool addResonanceAudioSources = false;
- public bool ignoreTimeScale = false;
- public bool useGaplessPlaylists = false;
- public bool useGaplessAutoReschedule = false;
- public bool saveRuntimeChanges = false;
- public bool prioritizeOnDistance = false;
- public int rePrioritizeEverySecIndex = 1;
- public bool useOcclusion = false;
- public float occlusionMaxCutoffFreq = AudioUtil.DefaultMaxOcclusionCutoffFrequency;
- public float occlusionMinCutoffFreq = AudioUtil.DefaultMinOcclusionCutoffFrequency;
- public float occlusionFreqChangeSeconds = 0f;
- public OcclusionSelectionType occlusionSelectType = OcclusionSelectionType.AllGroups;
- public int occlusionMaxRayCastsPerFrame = 4;
- public float occlusionRayCastOffset = 0f;
- public bool occlusionUseLayerMask;
- public LayerMask occlusionLayerMask;
- public bool occlusionShowRaycasts = true;
- public bool occlusionShowCategories = false;
- public RaycastMode occlusionRaycastMode = RaycastMode.Physics3D;
- public bool occlusionIncludeStartRaycast2DCollider = true;
- public bool occlusionRaycastsHitTriggers = true;
- public bool ambientAdvancedExpanded = false;
- public int ambientMaxRecalcsPerFrame = 4;
- public bool visualAdvancedExpanded = true;
- public bool logAdvancedExpanded = true;
- public bool listenerAdvancedExpanded = false;
- public bool listenerFollowerHasRigidBody = true;
- public bool deletePreviewerAudioSourceWhenPlaying = true;
- public VariationFollowerType variationFollowerType = VariationFollowerType.LateUpdate;
- public bool showFadingSettings = false;
- public bool stopZeroVolumeGroups = false;
- public bool stopZeroVolumeBuses = false;
- public bool stopZeroVolumePlaylists = false;
- public float stopOldestBusFadeTime = 0.3f;
- public bool resourceAdvancedExpanded = true;
- public bool useClipAgePriority = false;
- public bool logOutOfVoices = true;
- public bool LogSounds;
- public bool logCustomEvents = false;
- public bool disableLogging = false;
- public bool showMusicDucking = false;
- public bool enableMusicDucking = true;
- public List<DuckGroupInfo> musicDuckingSounds = new List<DuckGroupInfo>();
- public float defaultRiseVolStart = .5f;
- public float defaultUnduckTime = 1f;
- public float defaultDuckedVolumeCut = DefaultDuckVolCut;
- public float crossFadeTime = 1f;
- public float _masterPlaylistVolume = 1f;
- public bool showGroupSelect = false;
- public bool hideGroupsWithNoActiveVars = false;
- public JukeBoxDisplayMode jukeBoxDisplayMode = JukeBoxDisplayMode.DisplayAll;
- public bool logPerfExpanded = true;
- public bool willWarm = true;
- public bool mixerSettingsExpanded;
- public AudioMixerUpdateMode mixerUpdateMode = AudioMixerUpdateMode.UnscaledTime;
- public string newEventName = "my event";
- public bool showCustomEvents = true;
- public string newCustomEventCategoryName = "New Category";
- public string addToCustomEventCategoryName = "New Category";
- public List<CustomEvent> customEvents = new List<CustomEvent>();
- public List<CustomEventCategory> customEventCategories = new List<CustomEventCategory> {
- new CustomEventCategory()
- };
- public Dictionary<string, DuckGroupInfo> duckingBySoundType = new Dictionary<string, DuckGroupInfo>(StringComparer.OrdinalIgnoreCase);
- // populated at runtime
- #if ADDRESSABLES_ENABLED
- //public SortedCache<int> addressablesToReleaseAfterSecondsByAddressableId
- #endif
- public int frames;
- public bool showUnityMixerGroupAssignment = true;
- public static readonly PlaySoundResult AndForgetSuccessResult = new PlaySoundResult {
- SoundPlayed = true
- };
- private static readonly PlaySoundResult failedResultDuringInit = new PlaySoundResult {
- SoundPlayed = false
- };
- #endregion
- #region Private Variables
- private readonly Dictionary<string, AudioGroupInfo> AudioSourcesBySoundType =
- new Dictionary<string, AudioGroupInfo>(StringComparer.OrdinalIgnoreCase);
- private Dictionary<string, List<int>> _randomizer = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- private Dictionary<string, List<int>> _randomizerOrigin = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- private Dictionary<string, List<int>> _randomizerLeftovers = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- private Dictionary<string, List<int>> _nonRandomChoices = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- private Dictionary<string, List<int>> _clipsPlayedBySoundTypeOldestFirst = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- private readonly List<SoundGroupVariationUpdater> ActiveVariationUpdaters = new List<SoundGroupVariationUpdater>(32);
- private readonly List<SoundGroupVariationUpdater> ActiveUpdatersToRemove = new List<SoundGroupVariationUpdater>();
- private readonly List<ICustomEventReceiver> ValidReceivers = new List<ICustomEventReceiver>();
- private readonly List<CustomEventCandidate> ValidReceiverCandidates = new List<CustomEventCandidate>(10);
- private readonly List<MasterAudioGroup> SoloedGroups = new List<MasterAudioGroup>();
- private readonly List<AmbientSoundToTriggerInfo> AmbientsToDelayedTrigger = new List<AmbientSoundToTriggerInfo>();
- private readonly Queue<CustomEventToFireInfo> CustomEventsToFire = new Queue<CustomEventToFireInfo>(32);
- private readonly Queue<TransformFollower> TransFollowerColliderPositionRecalcs = new Queue<TransformFollower>(32);
- private readonly List<TransformFollower> ProcessedColliderPositionRecalcs = new List<TransformFollower>(32);
- private readonly List<BusFadeInfo> BusFades = new List<BusFadeInfo>(2);
- private readonly List<GroupFadeInfo> GroupFades = new List<GroupFadeInfo>();
- private readonly List<GroupPitchGlideInfo> GroupPitchGlides = new List<GroupPitchGlideInfo>();
- private readonly List<BusPitchGlideInfo> BusPitchGlides = new List<BusPitchGlideInfo>();
- private readonly List<OcclusionFreqChangeInfo> VariationOcclusionFreqChanges = new List<OcclusionFreqChangeInfo>();
- private readonly List<AudioSource> AllAudioSources = new List<AudioSource>();
- private readonly Dictionary<string, Dictionary<ICustomEventReceiver, Transform>> ReceiversByEventName =
- new Dictionary<string, Dictionary<ICustomEventReceiver, Transform>>(StringComparer.OrdinalIgnoreCase);
- private readonly Dictionary<string, PlaylistController> PlaylistControllersByName =
- new Dictionary<string, PlaylistController>(StringComparer.OrdinalIgnoreCase);
- private readonly Dictionary<string, SoundGroupRefillInfo> LastTimeSoundGroupPlayed =
- new Dictionary<string, SoundGroupRefillInfo>(StringComparer.OrdinalIgnoreCase);
- private readonly List<GameObject> OcclusionSourcesInRange = new List<GameObject>(32);
- private readonly List<GameObject> OcclusionSourcesOutOfRange = new List<GameObject>(32);
- private readonly List<GameObject> OcclusionSourcesBlocked = new List<GameObject>(32);
- private readonly Queue<SoundGroupVariationUpdater> QueuedOcclusionRays = new Queue<SoundGroupVariationUpdater>(32);
- #if UNITY_2019_3_OR_NEWER && VIDEO_ENABLED
- private readonly List<VideoPlayerTracker> VideoPlayerTrackers = new List<VideoPlayerTracker>();
- #endif
- #if ADDRESSABLES_ENABLED
- private readonly List<AddressableDelayedRelease> AddressablesToReleaseLater = new List<AddressableDelayedRelease>();
- #endif
- private readonly List<string> AllSoundGroupNames = new List<string>(32); // use this to loop through the list. Looping on .Keys of a Dictionary allocates.
- private readonly List<string> AllBusNames = new List<string>(32); // use this to loop through the list. Looping on .Keys of a Dictionary allocates.
- private readonly List<AudioInfo> GroupsToDelete = new List<AudioInfo>();
-
- private readonly List<SoundGroupVariation> VariationsStartedDuringMultiStop = new List<SoundGroupVariation>(16);
- private readonly List<PlaylistController> ControllersToPause = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToUnpause = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToMute = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToUnmute = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToToggleMute = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToStop = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToFade = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToTrigNext = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToTrigRandom = new List<PlaylistController>();
- private readonly List<PlaylistController> ControllersToStart = new List<PlaylistController>();
- private readonly List<AmbientSoundToTriggerInfo> AmbientsToTriggerNow = new List<AmbientSoundToTriggerInfo>();
- private bool _isStoppingMultiple;
- private float _repriTime = -1f;
- private List<string> _groupsToRemove;
- private bool _mustRescanGroups;
- private Transform _trans;
- private bool _soundsLoaded;
- private bool _warming;
- // ReSharper restore InconsistentNaming
- private static MasterAudio _instance;
- private static string _prospectiveMAFolder = string.Empty;
- private static Transform _listenerTrans;
-
- #endregion
- #region Master Audio enums
- public enum JukeBoxDisplayMode
- {
- DisplayAll,
- DisplayActive
- }
- public enum BusVoiceLimitExceededMode
- {
- DoNotPlayNewSound,
- StopOldestSound,
- StopFarthestSound,
- StopLeastImportantSound
- }
-
- public enum AmbientSoundExitMode {
- StopSound,
- FadeSound
- }
- public enum AmbientSoundReEnterMode {
- StopExistingSound,
- FadeInSameSound
- }
- public enum VariationFollowerType {
- LateUpdate,
- FixedUpdate
- }
- public enum LinkedGroupSelectionType {
- All,
- OneAtRandom
- }
- public enum OcclusionSelectionType {
- AllGroups,
- TurnOnPerBusOrGroup
- }
- public enum RaycastMode {
- Physics3D,
- Physics2D
- }
- public enum AllMusicSpatialBlendType {
- ForceAllTo2D
- #if DISABLE_3D_SOUND
- #else
- ,
- ForceAllTo3D,
- ForceAllToCustom,
- AllowDifferentPerController
- #endif
- }
- public enum AllMixerSpatialBlendType {
- ForceAllTo2D
- #if DISABLE_3D_SOUND
- #else
- ,
- ForceAllTo3D,
- ForceAllToCustom,
- AllowDifferentPerGroup
- #endif
- }
- public enum ItemSpatialBlendType {
- ForceTo2D
- #if DISABLE_3D_SOUND
- #else
- ,
- ForceTo3D,
- ForceToCustom,
- UseCurveFromAudioSource
- #endif
- }
- public enum GroupPlayType
- {
- Always,
- WhenActorInAudibleRange,
- AllowDifferentPerGroup
- }
- public enum DefaultGroupPlayType {
- Always,
- WhenActorInAudibleRange
- }
- public enum MixerWidthMode {
- Narrow,
- Normal,
- Wide
- }
- public enum CustomEventReceiveMode {
- Always,
- WhenDistanceLessThan,
- WhenDistanceMoreThan,
- Never,
- OnSameGameObject,
- OnChildGameObject,
- OnParentGameObject,
- OnSameOrChildGameObject,
- OnSameOrParentGameObject
- }
- public enum EventReceiveFilter {
- All,
- Closest,
- Random
- }
- public enum VariationLoadStatus {
- None,
- Loading,
- Loaded,
- LoadFailed
- }
- /*! \endcond */
- /// <summary>
- /// This setting lets you choose where the Audio Clip lives: Clip, Resource File or Addressable
- /// </summary>
- public enum AudioLocation {
- Clip,
- ResourceFile
- #if ADDRESSABLES_ENABLED
- ,Addressable
- #endif
- }
- /// <summary>
- /// This controls where the song starts, Beginning, Specific Time or Random Time.
- /// </summary>
- public enum CustomSongStartTimeMode
- {
- Beginning,
- SpecificTime,
- RandomTime,
- Section
- }
- /*! \cond PRIVATE */
- public enum BusCommand {
- None,
- FadeToVolume,
- Mute,
- Pause,
- Solo,
- Unmute,
- Unpause,
- Unsolo,
- Stop,
- ChangePitch,
- ToggleMute,
- StopBusOfTransform,
- PauseBusOfTransform,
- UnpauseBusOfTransform,
- GlideByPitch,
- StopOldBusVoices,
- FadeOutOldBusVoices
- }
- public enum DragGroupMode {
- OneGroupPerClip,
- OneGroupWithVariations
- }
- public enum EventSoundFunctionType {
- PlaySound,
- GroupControl,
- BusControl,
- PlaylistControl,
- CustomEventControl,
- GlobalControl,
- UnityMixerControl,
- PersistentSettingsControl
- }
- public enum LanguageMode {
- UseDeviceSetting,
- SpecificLanguage,
- DynamicallySet
- }
- public enum UnityMixerCommand {
- None,
- TransitionToSnapshot,
- TransitionToSnapshotBlend
- }
- public enum PlaylistCommand {
- None,
- ChangePlaylist, // by name
- FadeToVolume,
- PlaySong, // by name
- PlayRandomSong,
- PlayNextSong,
- Pause,
- Resume,
- Stop,
- Mute,
- Unmute,
- ToggleMute,
- Restart,
- Start,
- StopLoopingCurrentSong,
- StopPlaylistAfterCurrentSong,
- AddSongToQueue
- }
- public enum CustomEventCommand {
- None,
- FireEvent
- }
- public enum GlobalCommand {
- None,
- PauseMixer,
- UnpauseMixer,
- StopMixer,
- StopEverything,
- PauseEverything,
- UnpauseEverything,
- MuteEverything,
- UnmuteEverything,
- SetMasterMixerVolume,
- SetMasterPlaylistVolume,
- PauseAudioListener,
- UnpauseAudioListener
- }
- public enum SoundGroupCommand {
- None,
- FadeToVolume,
- FadeOutAllOfSound,
- Mute,
- Pause,
- Solo,
- StopAllOfSound,
- Unmute,
- Unpause,
- Unsolo,
- StopAllSoundsOfTransform,
- PauseAllSoundsOfTransform,
- UnpauseAllSoundsOfTransform,
- StopSoundGroupOfTransform,
- PauseSoundGroupOfTransform,
- UnpauseSoundGroupOfTransform,
- FadeOutSoundGroupOfTransform,
- RefillSoundGroupPool,
- RouteToBus,
- GlideByPitch,
- ToggleSoundGroup,
- ToggleSoundGroupOfTransform,
- FadeOutAllSoundsOfTransform,
- StopOldSoundGroupVoices,
- FadeOutOldSoundGroupVoices
- }
- public enum PersistentSettingsCommand {
- None,
- SetBusVolume,
- SetGroupVolume,
- SetMixerVolume,
- SetMusicVolume,
- MixerMuteToggle,
- MusicMuteToggle
- }
- public enum SongFadeInPosition {
- NewClipFromBeginning = 1,
- NewClipFromLastKnownPosition = 3,
- SynchronizeClips = 5,
- }
- public enum SoundSpawnLocationMode {
- MasterAudioLocation,
- CallerLocation,
- AttachToCaller
- }
- public enum VariationCommand {
- None = 0,
- Stop = 1,
- Pause = 2,
- Unpause = 3
- }
- public static readonly List<SoundGroupCommand> GroupCommandsWithNoGroupSelector = new List<SoundGroupCommand> {
- SoundGroupCommand.None,
- SoundGroupCommand.PauseAllSoundsOfTransform,
- SoundGroupCommand.StopAllSoundsOfTransform,
- SoundGroupCommand.UnpauseAllSoundsOfTransform,
- SoundGroupCommand.FadeOutAllSoundsOfTransform
- };
- public static readonly List<SoundGroupCommand> GroupCommandsWithNoAllGroupSelector = new List<SoundGroupCommand> {
- SoundGroupCommand.None,
- SoundGroupCommand.FadeOutSoundGroupOfTransform,
- SoundGroupCommand.PauseSoundGroupOfTransform,
- SoundGroupCommand.UnpauseSoundGroupOfTransform,
- SoundGroupCommand.StopSoundGroupOfTransform,
- SoundGroupCommand.ToggleSoundGroupOfTransform,
- SoundGroupCommand.ToggleSoundGroup,
- SoundGroupCommand.FadeOutAllSoundsOfTransform
- };
- #endregion
- #region Inner classes & Structs
- [Serializable]
- public struct CustomEventCandidate {
- public float DistanceAway;
- public ICustomEventReceiver Receiver;
- public Transform Trans;
- public int RandomId;
- public CustomEventCandidate(float distance, ICustomEventReceiver rec, Transform trans, int randomId) {
- DistanceAway = distance;
- Receiver = rec;
- Trans = trans;
- RandomId = randomId;
- }
- }
- [Serializable]
- public class AudioGroupInfo {
- public List<AudioInfo> Sources;
- public int LastFramePlayed;
- public float LastTimePlayed;
- public MasterAudioGroup Group;
- public bool PlayedForWarming;
- public AudioGroupInfo(List<AudioInfo> sources, MasterAudioGroup groupScript) {
- Sources = sources;
- LastFramePlayed = -50;
- LastTimePlayed = -50;
- Group = groupScript;
- PlayedForWarming = false;
- }
- }
- [Serializable]
- public class AudioInfo {
- public AudioSource Source;
- public float OriginalVolume;
- public float LastPercentageVolume;
- public float LastRandomVolume;
- public SoundGroupVariation Variation;
- public AudioInfo(SoundGroupVariation variation, AudioSource source, float origVol) {
- Variation = variation;
- Source = source;
- OriginalVolume = origVol;
- LastPercentageVolume = 1f;
- LastRandomVolume = 0f;
- }
- }
- [Serializable]
- public class Playlist {
- // ReSharper disable InconsistentNaming
- public bool isExpanded = true;
- public string playlistName = "new playlist";
- public SongFadeInPosition songTransitionType = SongFadeInPosition.NewClipFromBeginning;
- public List<MusicSetting> MusicSettings;
- public AudioLocation bulkLocationMode = AudioLocation.Clip;
- public CrossfadeTimeMode crossfadeMode = CrossfadeTimeMode.UseMasterSetting;
- public float crossFadeTime = 1f;
- public bool fadeInFirstSong = false;
- public bool fadeOutLastSong = false;
- public bool bulkEditMode = false;
- public bool isTemporary = false;
- public bool showMetadata = false;
- public List<SongMetadataProperty> songMetadataProps = new List<SongMetadataProperty>();
- public string newMetadataPropName = "PropertyName";
- public SongMetadataProperty.MetadataPropertyType newMetadataPropType = SongMetadataProperty.MetadataPropertyType.String;
- public bool newMetadataPropRequired = true;
- public bool newMetadataPropCanHaveMult = false;
- // ReSharper restore InconsistentNaming
- private readonly List<int> _actorInstanceIds = new List<int>();
- public enum CrossfadeTimeMode {
- UseMasterSetting,
- Override
- }
- public Playlist() {
- MusicSettings = new List<MusicSetting>();
- }
- public void AddActorInstanceId(int instanceId)
- {
- if (_actorInstanceIds.Contains(instanceId))
- {
- return;
- }
- _actorInstanceIds.Add(instanceId);
- }
- public void RemoveActorInstanceId(int instanceId)
- {
- _actorInstanceIds.Remove(instanceId);
- }
- public bool HasLiveActors {
- get {
- return _actorInstanceIds.Count > 0;
- }
- }
- }
- [Serializable]
- public class SoundGroupRefillInfo {
- public float LastTimePlayed;
- public float InactivePeriodSeconds;
- public SoundGroupRefillInfo(float lastTimePlayed, float inactivePeriodSeconds) {
- LastTimePlayed = lastTimePlayed;
- InactivePeriodSeconds = inactivePeriodSeconds;
- }
- }
- /*! \endcond */
- #endregion
- #region MonoDevelop events and Helpers
- #if UNITY_2019_3_OR_NEWER
- [RuntimeInitializeOnLoadMethod(RuntimeInitializeLoadType.SubsystemRegistration)]
- static void Init() {
- AppIsShuttingDown = false;
- }
- #endif
- // ReSharper disable once UnusedMember.Local
- // ReSharper disable once FunctionComplexityOverflow
- private void Awake() {
- var mas = FindObjectsOfType(typeof(MasterAudio));
- if (mas.Length > 1) {
- Destroy(gameObject);
- bool shouldLog = false;
- for (var i = 0; i < mas.Length; i++) {
- MasterAudio ama = mas[i] as MasterAudio;
- if (!ama.persistBetweenScenes) {
- continue;
- }
- if (ama.shouldLogDestroys) {
- shouldLog = true;
- break;
- }
- }
- if (shouldLog) {
- Debug.Log("More than one Master Audio prefab exists in this Scene. Destroying the newer one called '" +
- name + "'. You may wish to set up a Bootstrapper Scene so this does not occur.");
- }
- return;
- }
- AudioListener.pause = false; // in case you exited last time with it paused. You would hear nothing on next play.
- useGUILayout = false;
- _soundsLoaded = false;
- _mustRescanGroups = false;
- var listener = ListenerTrans;
- if (listener != null && deletePreviewerAudioSourceWhenPlaying) {
- var aud = listener.GetComponent<AudioSource>();
- if (aud != null) {
- // delete the previewer
- // ReSharper disable once ArrangeStaticMemberQualifier
- GameObject.Destroy(aud);
- }
- }
- AmbientUtil.InitFollowerHolder();
- AudioSourcesBySoundType.Clear();
- AllBusNames.Clear();
- AllSoundGroupNames.Clear();
- GroupsToDelete.Clear();
- ValidReceivers.Clear();
- ValidReceiverCandidates.Clear();
- ControllersToPause.Clear();
- ControllersToUnpause.Clear();
- ControllersToMute.Clear();
- ControllersToUnmute.Clear();
- ControllersToToggleMute.Clear();
- ControllersToStop.Clear();
- ControllersToFade.Clear();
- ControllersToTrigNext.Clear();
- ControllersToTrigRandom.Clear();
- ControllersToStart.Clear();
- PlaylistControllersByName.Clear();
- LastTimeSoundGroupPlayed.Clear();
- ErrorNumbersLogged.Clear();
- AmbientsToTriggerNow.Clear();
- AllAudioSources.Clear();
- OcclusionSourcesInRange.Clear();
- OcclusionSourcesOutOfRange.Clear();
- OcclusionSourcesBlocked.Clear();
- QueuedOcclusionRays.Clear();
- TransFollowerColliderPositionRecalcs.Clear();
- CustomEventsToFire.Clear();
- AmbientsToDelayedTrigger.Clear();
- ProcessedColliderPositionRecalcs.Clear();
- ActiveVariationUpdaters.Clear();
- ActiveUpdatersToRemove.Clear();
- var plNames = new List<string>();
- AudioResourceOptimizer.ClearAudioClips();
- PlaylistController.Instances = null; // clear the cache
- var playlists = PlaylistController.Instances;
- // ReSharper disable once ForCanBeConvertedToForeach
- for (var i = 0; i < playlists.Count; i++) {
- var aList = playlists[i];
- if (plNames.Contains(aList.ControllerName)) {
- Debug.LogError("You have more than 1 Playlist Controller with the name '" + aList.ControllerName +
- "'. You must name them all uniquely or the same-named ones will be deleted once they awake.");
- continue;
- }
- plNames.Add(aList.ControllerName);
- PlaylistControllersByName.Add(aList.ControllerName, aList);
- if (persistBetweenScenes) {
- DontDestroyOnLoad(aList);
- }
- }
- // start up Objects!
- if (persistBetweenScenes) {
- DontDestroyOnLoad(gameObject);
- }
- var playedStatuses = new List<int>();
- // ReSharper disable TooWideLocalVariableScope
- Transform parentGroup;
- List<AudioInfo> sources;
- AudioSource source;
- AudioGroupInfo group;
- MasterAudioGroup groupScript;
- string soundType;
- // ReSharper restore TooWideLocalVariableScope
- _randomizer = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- _randomizerOrigin = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- _randomizerLeftovers = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- _nonRandomChoices = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- _clipsPlayedBySoundTypeOldestFirst = new Dictionary<string, List<int>>(StringComparer.OrdinalIgnoreCase);
- var allVars = new List<SoundGroupVariation>();
- _groupsToRemove = new List<string>(Trans.childCount);
- var mutedGroups = new List<string>();
- for (var k = 0; k < Trans.childCount; k++) {
- parentGroup = Trans.GetChild(k);
- sources = new List<AudioInfo>();
- groupScript = parentGroup.GetComponent<MasterAudioGroup>();
- if (groupScript == null) {
- if (!ArrayListUtil.IsExcludedChildName(parentGroup.name)) {
- Debug.LogError("MasterAudio could not find 'MasterAudioGroup' script for group '" + parentGroup.name + "'. Skipping this group.");
- }
- continue;
- }
- soundType = groupScript.GameObjectName;
- var newWeightedChildren = new List<Transform>();
- // ReSharper disable TooWideLocalVariableScope
- SoundGroupVariation variation;
- SoundGroupVariation childVariation;
- Transform child;
- // ReSharper restore TooWideLocalVariableScope
- var allStatuses = new List<int>();
- for (var i = 0; i < parentGroup.childCount; i++) {
- child = parentGroup.GetChild(i);
- variation = child.GetComponent<SoundGroupVariation>();
- source = child.GetComponent<AudioSource>();
- var weight = variation.weight;
- for (var j = 0; j < weight; j++) {
- if (j > 0) {
- // ReSharper disable once ArrangeStaticMemberQualifier
- var extraChild = (GameObject)GameObject.Instantiate(child.gameObject, parentGroup.transform.position, Quaternion.identity);
- extraChild.transform.name = child.gameObject.name;
- childVariation = extraChild.GetComponent<SoundGroupVariation>();
- childVariation.weight = 1;
- newWeightedChildren.Add(extraChild.transform);
- source = extraChild.GetComponent<AudioSource>();
- sources.Add(new AudioInfo(childVariation, source, source.volume));
- allVars.Add(childVariation);
- switch (childVariation.audLocation) {
- case AudioLocation.ResourceFile:
- AudioResourceOptimizer.AddTargetForClip(childVariation.resourceFileName, source);
- break;
- }
- } else {
- sources.Add(new AudioInfo(variation, source, source.volume));
- allVars.Add(variation);
- switch (variation.audLocation) {
- case AudioLocation.ResourceFile:
- var resFileName =
- AudioResourceOptimizer.GetLocalizedFileName(variation.useLocalization,
- variation.resourceFileName);
- AudioResourceOptimizer.AddTargetForClip(resFileName, source);
- break;
- }
- }
- }
- }
- // attach extra children from weight property.
- // ReSharper disable once ForCanBeConvertedToForeach
- for (var i = 0; i < newWeightedChildren.Count; i++) {
- newWeightedChildren[i].parent = parentGroup;
- }
- group = new AudioGroupInfo(sources, groupScript);
- if (groupScript.isSoloed) {
- SoloedGroups.Add(groupScript);
- }
- if (groupScript.isMuted) {
- if (mutedGroups.Contains(groupScript.GameObjectName)) {
- continue;
- }
- mutedGroups.Add(groupScript.GameObjectName);
- }
- if (AudioSourcesBySoundType.ContainsKey(soundType)) {
- Debug.LogError("You have more than one SoundGroup named '" + soundType +
- "'. Ignoring the 2nd one. Please rename it.");
- continue;
- }
- group.Group.OriginalVolume = group.Group.groupMasterVolume;
- // added code for persistent group volume
- var persistentVolume = PersistentAudioSettings.GetGroupVolume(soundType);
- if (persistentVolume.HasValue) {
- group.Group.groupMasterVolume = persistentVolume.Value;
- }
- AddRuntimeGroupInfo(soundType, group);
- for (var i = 0; i < sources.Count; i++) {
- playedStatuses.Add(i);
- }
- if (group.Group.curVariationSequence == MasterAudioGroup.VariationSequence.Randomized) {
- ArrayListUtil.SortIntArray(ref playedStatuses);
- }
- _randomizer.Add(soundType, playedStatuses);
- allStatuses.Clear();
- allStatuses.AddRange(playedStatuses);
- _randomizerOrigin.Add(soundType, allStatuses); // must be a copy of one gets lost later
- _randomizerLeftovers.Add(soundType, new List<int>(playedStatuses.Count));
- // fill leftovers pool.
- _randomizerLeftovers[soundType].AddRange(playedStatuses);
- _clipsPlayedBySoundTypeOldestFirst.Add(soundType, new List<int>());
- _nonRandomChoices.Add(soundType, new List<int>());
- playedStatuses = new List<int>();
- }
- GroupFades.Clear();
- BusFades.Clear();
- GroupPitchGlides.Clear();
- BusPitchGlides.Clear();
- VariationOcclusionFreqChanges.Clear();
- // initialize persistent bus volumes
- // ReSharper disable once ForCanBeConvertedToForeach
- for (var i = 0; i < groupBuses.Count; i++) {
- var aBus = groupBuses[i];
- aBus.OriginalVolume = aBus.volume;
- var busName = aBus.busName;
- var busVol = PersistentAudioSettings.GetBusVolume(busName);
- if (!busVol.HasValue) {
- continue;
- }
- SetBusVolumeByName(busName, busVol.Value);
- }
- // populate ducking sounds dictionary
- duckingBySoundType.Clear();
- // ReSharper disable once ForCanBeConvertedToForeach
- for (var i = 0; i < musicDuckingSounds.Count; i++) {
- var aDuck = musicDuckingSounds[i];
- if (duckingBySoundType.ContainsKey(aDuck.soundType)) {
- Debug.LogWarning("You have more than one Duck Group set up with the Sound Group '" + aDuck.soundType + "'. Please delete the duplicates before running again.");
- continue;
- }
- if (aDuck.soundType == VideoPlayerSoundGroupName)
- {
- Debug.LogError("The specially named Sound Group for Video Players '" + VideoPlayerSoundGroupName + "' cannot be used as a Music Ducking Group. Please remove it.");
- continue;
- }
- duckingBySoundType.Add(aDuck.soundType, aDuck);
- }
- #if UNITY_2019_3_OR_NEWER && VIDEO_ENABLED
- if (videoPlayers.Count > 0)
- {
- var videoPlayerHolder = VideoPlayerSoundGroupTransform;
- if (videoPlayerHolder == null)
- {
- Debug.LogError("You have deleted the specially named Sound Group for Video Players. Please press stop and open the Master Audio Inspector and expand the Video Player Settings section so it will be automatically created again. Otherwise the audio for your Video Players will not work properly.");
- }
- else
- {
- VideoPlayerTrackers.Clear();
- for (var i = 0; i < videoPlayers.Count; i++)
- {
- var aPlayer = videoPlayers[i];
- if (aPlayer.clip == null)
- {
- Debug.LogError("Your clip for Video Player in Game Object '" + aPlayer.name + " is empty. Please assign a video clip or delete this Video Player from Master Audio.");
- continue;
- }
- var childVariationGO = videoPlayerHolder.Find(aPlayer.name);
- if (childVariationGO == null)
- {
- Debug.LogError("You have deleted the one or more Variations in the specially named Video Players Sound Group. Please press stop and open the Master Audio Inspector and expand the Video Player Settings section so it will be automatically created again. Otherwise the audio for your Video Players will not work properly.");
- continue;
- }
- var childVariation = childVariationGO.transform.GetComponent<SoundGroupVariation>();
- VideoPlayerTrackers.Add(new VideoPlayerTracker(aPlayer, childVariation));
- }
- }
- var videoPlayerBus = GrabBusByName(VideoPlayerBusName);
- if (videoPlayerBus == null)
- {
- Debug.LogError("You have deleted the specially named Video Players Bus. Please press stop and open the Master Audio Inspector and expand the Video Player Settings section so it will be automatically created again. Otherwise the audio for your Video Players will not work properly.");
- }
- }
- #endif
- _soundsLoaded = true;
- if (willWarm) {
- _warming = true;
- var warmGroup = SoundGroupForWarming();
- // pre-warm the code so the first sound played for real doesn't have to JIT and be slow.
- if (!string.IsNullOrEmpty(warmGroup)) {
- var result = PlaySound3DFollowTransform(warmGroup, Trans, 0f);
- if (result != null && result.SoundPlayed) {
- result.ActingVariation.Stop();
- }
- }
- FireCustomEvent("FakeEvent", _trans);
- // ReSharper disable once ForCanBeConvertedToForeach
- // Reset stuff for people who use "Save runtime changes".
- for (var i = 0; i < customEvents.Count; i++) {
- customEvents[i].frameLastFired = -1;
- }
- frames = 0;
- // Event Sounds warmer
- // ReSharper disable once ArrangeStaticMemberQualifier
- var evts = GameObject.FindObjectsOfType(typeof(EventSounds));
- if (evts.Length > 0) {
- var evt = evts[0] as EventSounds;
- evt.PlaySounds(evt.particleCollisionSound, EventSounds.EventType.UserDefinedEvent);
- }
- // ReSharper disable once ForCanBeConvertedToForeach
- for (var i = 0; i < mutedGroups.Count; i++) {
- MuteGroup(mutedGroups[i], false);
- }
- // done warming
- _warming = false;
- }
- // ReSharper disable once ForCanBeConvertedToForeach
- for (var i = 0; i < allVars.Count; i++) {
- allVars[i].DisableUpdater();
- }
- AmbientUtil.InitListenerFollower(); // start this up so it's available to batch occlusion stuff
- // fixed: make sure this happens before Playlists start or the volume won't be right.
- PersistentAudioSettings.RestoreMasterSettings();
- }
- // ReSharper disable once UnusedMember.Local
- private void Start() {
- // wait for Playlist Controller to initialize!
- if (musicPlaylists.Count > 0
- && musicPlaylists[0].MusicSettings != null
- && musicPlaylists[0].MusicSettings.Count > 0
- && musicPlaylists[0].MusicSettings[0].clip != null
- && PlaylistControllersByName.Count == 0) {
- Debug.Log("No Playlist Controllers exist in the Scene. Music will not play.");
- }
- }
- // ReSharper disable once UnusedMember.Local
- void OnDisable() {
- var sources = GetComponentsInChildren<AudioSource>().ToList();
- StopTrackingRuntimeAudioSources(sources);
- }
- // ReSharper disable once UnusedMember.Local
- void Update() {
- frames++;
- // adjust for Inspector realtime slider.
- PerformOcclusionFrequencyChanges();
- PerformBusFades();
- PerformBusPitchGlides();
- PerformGroupFades();
- PerformGroupPitchGlides();
- PerformDelayedAmbientTriggers();
- RefillInactiveGroupPools();
- FireCustomEventsWaiting();
- #if UNITY_2019_3_OR_NEWER && VIDEO_ENABLED
- TrackVideoPlayers();
- #endif
- #if ADDRESSABLES_ENABLED
- CheckAddressablesForDelayedRelease();
- #endif
- }
- // ReSharper disable once UnusedMember.Local
- void LateUpdate() {
- if (variationFollowerType != VariationFollowerType.LateUpdate) {
- return;
- }
- ManualUpdate();
- }
- // ReSharper disable once UnusedMember.Local
- void FixedUpdate() {
- if (variationFollowerType != VariationFollowerType.FixedUpdate) {
- return;
- }
- ManualUpdate();
- }
- private void ManualUpdate() {
- RecalcClosestColliderPositions();
- AmbientUtil.ManualUpdate();
- UpdateActiveVariations();
- }
- /*! \cond PRIVATE */
- public string SoundGroupForWarming() {
- string firstGroupName = null;
- for (var k = 0; k < Trans.childCount; k++) {
- var parentGroup = Trans.GetChild(k);
- if (parentGroup.name == AmbientUtil.FollowerHolderName) {
- continue; // don't pick this, not a Sound Group
- }
- if (firstGroupName == null) {
- firstGroupName = parentGroup.name;
- }
- for (var i = 0; i < parentGroup.childCount; i++) {
- var variationGO = parentGroup.GetChild(i);
- var variation = variationGO.GetComponent<SoundGroupVariation>();
- if (variation == null) {
- continue;
- }
- if (variation.audLocation == AudioLocation.Clip) {
- return parentGroup.name;
- }
-