private static PlaySoundResult PlaySoundIfAvailable(string soundGroupName, AudioInfo info, Vector3 sourcePosition, float volumePercentage, ref bool forgetSoundPlayed, float? pitch = null, AudioGroupInfo audioGroup = null, Transform sourceTrans = null, bool attachToSource = false, float delaySoundTime = 0f, bool useVector3 = false, bool makePlaySoundResult = false, bool isChaining = false, bool isSingleSubscribedPlay = false) { if (info.source == null) { // this avoids false errors when stopping the game (from became "invisible" event callers) return null; } MasterAudioGroup maGroup = audioGroup._group; if (maGroup.curVariationMode == MasterAudioGroup.VariationMode.Normal && info.source.audio.isPlaying) { var playedPercentage = AudioUtil.GetAudioPlayedPercentage(info.source); var retriggerPercent = maGroup.retriggerPercentage; if (playedPercentage < retriggerPercent) { return null; // wait for this to stop playing or play further. } } info.variation.Stop(); info.variation.ObjectToFollow = null; if (useVector3) { info.source.transform.position = sourcePosition; if (MasterAudio.Instance.prioritizeOnDistance) { AudioPrioritizer.Set3dPriority(info.source); } } else if (sourceTrans != null) { if (attachToSource) { info.variation.ObjectToFollow = sourceTrans; } else { info.source.transform.position = sourceTrans.position; info.variation.ObjectToTriggerFrom = sourceTrans; } if (MasterAudio.Instance.prioritizeOnDistance) { AudioPrioritizer.Set3dPriority(info.source); } } else { // "2d manner" - from Master Audio location if (MasterAudio.Instance.prioritizeOnDistance) { AudioPrioritizer.Set2dSoundPriority(info.source); } info.source.transform.localPosition = Vector3.zero; // put it back in MA prefab position after being detached. } var groupVolume = maGroup.groupMasterVolume; var busVolume = GetBusVolume(maGroup); float calcVolume = info.originalVolume * groupVolume * busVolume * MasterAudio.Instance.masterAudioVolume; // set volume to percentage. float volume = calcVolume * volumePercentage; var targetVolume = volume; var randomVol = 0f; if (info.variation.useRandomVolume) { // random volume randomVol = UnityEngine.Random.Range(info.variation.randomVolumeMin, info.variation.randomVolumeMax); switch (info.variation.randomVolumeMode) { case SoundGroupVariation.RandomVolumeMode.AddToClipVolume: targetVolume += randomVol; break; case SoundGroupVariation.RandomVolumeMode.IgnoreClipVolume: targetVolume = randomVol; break; } } info.source.audio.volume = targetVolume; // save these for on the fly adjustments afterward info.lastPercentageVolume = volumePercentage; info.lastRandomVolume = randomVol; bool isActive = false; #if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 isActive = info.source.audio.gameObject.active; #else isActive = info.source.audio.gameObject.activeInHierarchy; #endif if (!isActive) { return null; } PlaySoundResult result = null; if (makePlaySoundResult) { result = new PlaySoundResult(); result.ActingVariation = info.variation; if (delaySoundTime > 0f) { result.SoundScheduled = true; } else { result.SoundPlayed = true; } } else { forgetSoundPlayed = true; } var playSoundParams = new SoundGroupVariation.PlaySoundParams(maGroup.name, volumePercentage, targetVolume, pitch, sourceTrans, attachToSource, delaySoundTime, maGroup.curVariationMode == MasterAudioGroup.VariationMode.LoopedChain, isSingleSubscribedPlay); if (playSoundParams.isChainLoop && !isChaining) { maGroup.ChainLoopCount = 0; } if (playSoundParams.isChainLoop) { // make sure there isn't 2 going, ever MasterAudio.StopAllOfSound(playSoundParams.soundType); } info.variation.Play(pitch, targetVolume, playSoundParams); return result; }
void Awake() { if (GameObject.FindObjectsOfType(typeof(MasterAudio)).Length > 1) { Destroy(gameObject); Debug.Log("More than one Master Audio prefab exists in this Scene. Destroying the newer one called '" + this.name + "'. You may wish to set up a Bootstrapper Scene so this does not occur."); return; } this.useGUILayout = false; trans = this.transform; soundsLoaded = false; var aud = this.audio; if (aud != null) { // delete the previewer GameObject.Destroy(aud); } audioSourcesBySoundType.Clear(); playlistControllersByName.Clear(); lastTimeSoundGroupPlayed.Clear(); var plNames = new List<string>(); AudioResourceOptimizer.ClearAudioClips(); PlaylistController.Instances = null; // clear the cache var playlists = PlaylistController.Instances; for (var i = 0; i < playlists.Count; i++) { var aList = playlists[i]; if (plNames.Contains(aList.name)) { Debug.LogError("You have more than 1 Playlist Controller with the name '" + aList.name + "'. You must name them all uniquely or the same-named ones will be deleted once they awake."); continue; } else { plNames.Add(aList.name); } playlistControllersByName.Add(aList.name, aList); if (persistBetweenScenes) { DontDestroyOnLoad(aList); } } // start up Objects! if (persistBetweenScenes) { DontDestroyOnLoad(this.gameObject); } Transform parentGroup; List<AudioInfo> sources; var playedStatuses = new List<int>(); AudioSource source; AudioGroupInfo _group; MasterAudioGroup groupScript; randomizer = new Dictionary<string, List<int>>(); clipsPlayedBySoundTypeOldestFirst = new Dictionary<string, List<int>>(); string soundType = string.Empty; var firstGroupName = string.Empty; for (var k = 0; k < trans.childCount; k++) { parentGroup = trans.GetChild(k); sources = new List<AudioInfo>(); groupScript = parentGroup.GetComponent<MasterAudioGroup>(); if (groupScript == null) { Debug.LogError("MasterAudio could not find 'MasterAudioGroup' script for group '" + parentGroup.name + "'. Skipping this group."); continue; } soundType = parentGroup.name; if (string.IsNullOrEmpty(firstGroupName)) { firstGroupName = soundType; } var newWeightedChildren = new List<Transform>(); SoundGroupVariation variation = null; SoundGroupVariation childVariation = null; Transform child = null; for (int i = 0; i < parentGroup.childCount; i++) { child = parentGroup.GetChild(i); variation = child.GetComponent<SoundGroupVariation>(); source = child.audio; var weight = variation.weight; for (var j = 0; j < weight; j++) { if (j > 0) { 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.audio; sources.Add(new AudioInfo(childVariation, source, source.volume)); if (childVariation.audLocation == MasterAudio.AudioLocation.ResourceFile) { AudioResourceOptimizer.AddTargetForClip(childVariation.resourceFileName, source); } } else { sources.Add(new AudioInfo(variation, source, source.volume)); if (variation.audLocation == MasterAudio.AudioLocation.ResourceFile) { AudioResourceOptimizer.AddTargetForClip(variation.resourceFileName, source); } } } } // attach extra children from weight property. for (var i = 0; i < newWeightedChildren.Count; i++) { newWeightedChildren[i].parent = parentGroup; } _group = new AudioGroupInfo(sources, groupScript); if (groupScript.isSoloed) { soloedGroups.Add(groupScript); } if (audioSourcesBySoundType.ContainsKey(soundType)) { Debug.LogError("You have more than one SoundGroup named '" + soundType + "'. Ignoring the 2nd one. Please rename it."); continue; } _group._sources.Sort(delegate(AudioInfo x, AudioInfo y) { return x.variation.name.CompareTo(y.variation.name); }); audioSourcesBySoundType.Add(soundType, _group); for (var i = 0; i < sources.Count; i++) { playedStatuses.Add(i); } randomizer.Add(soundType, playedStatuses); clipsPlayedBySoundTypeOldestFirst.Add(soundType, new List<int>()); playedStatuses = new List<int>(); } busFades.Clear(); groupFades.Clear(); Playlist pl = null; float firstSongLength = 0f; // check Syncrhonized Playlists for problems! for (var i = 0; i < musicPlaylists.Count; i++) { pl = musicPlaylists[i]; if (pl.songTransitionType != SongFadeInPosition.SynchronizeClips) { continue; } if (pl.MusicSettings.Count < 2) { continue; } var songOne = pl.MusicSettings[0].clip; if (songOne == null) { continue; } firstSongLength = songOne.length; for (var s = 1; s < pl.MusicSettings.Count; s++) { var clip = pl.MusicSettings[s].clip; if (clip == null) { continue; } if (clip.length != firstSongLength) { Debug.LogError("Playlist '" + pl.playlistName + "' is marked as Synchronized but the clip lengths are not all the same within the Playlist. Clips may not synchronize as intended."); break; } } } // populate ducking sounds dictionary duckingBySoundType.Clear(); for (var i = 0; i < musicDuckingSounds.Count; i++) { var aDuck = musicDuckingSounds[i]; duckingBySoundType.Add(aDuck.soundType, aDuck); } soundsLoaded = true; // pre-warm the code so the first sound played for real doesn't have to JIT and be slow. if (!string.IsNullOrEmpty(firstGroupName)) { var result = PlaySound(firstGroupName, 0f, 1f, 0f, null, false, false); if (result != null && result.SoundPlayed) { result.ActingVariation.Stop(); } } }
private static void AddRuntimeGroupInfo(string groupName, AudioGroupInfo groupInfo) { AudioSourcesBySoundType.Add(groupName, groupInfo); var sources = new List<AudioSource>(groupInfo.Sources.Count); // ReSharper disable ForCanBeConvertedToForeach for (var i = 0; i < groupInfo.Sources.Count; i++) { // ReSharper restore ForCanBeConvertedToForeach sources.Add(groupInfo.Sources[i].Source); } TrackRuntimeAudioSources(sources); }
/*! \endcond */ #endregion #region MonoDevelop events and Helpers // ReSharper disable once UnusedMember.Local // ReSharper disable once FunctionComplexityOverflow private void Awake() { if (FindObjectsOfType(typeof(MasterAudio)).Length > 1) { Destroy(gameObject); 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; } useGUILayout = false; _soundsLoaded = false; _innerLoopDelay = new WaitForSeconds(InnerLoopCheckInterval); var aud = GetComponent<AudioSource>(); if (aud != null) { // delete the previewer // ReSharper disable once ArrangeStaticMemberQualifier GameObject.Destroy(aud); } AudioSourcesBySoundType.Clear(); PlaylistControllersByName.Clear(); LastTimeSoundGroupPlayed.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.name)) { Debug.LogError("You have more than 1 Playlist Controller with the name '" + aList.name + "'. You must name them all uniquely or the same-named ones will be deleted once they awake."); continue; } plNames.Add(aList.name); PlaylistControllersByName.Add(aList.name, 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>>(); _randomizerLeftovers = new Dictionary<string, List<int>>(); _clipsPlayedBySoundTypeOldestFirst = new Dictionary<string, List<int>>(); var firstGroupName = string.Empty; var allVars = new List<SoundGroupVariation>(); _groupsToRemove = new List<string>(Trans.childCount); for (var k = 0; k < Trans.childCount; k++) { parentGroup = Trans.GetChild(k); sources = new List<AudioInfo>(); groupScript = parentGroup.GetComponent<MasterAudioGroup>(); if (groupScript == null) { Debug.LogError("MasterAudio could not find 'MasterAudioGroup' script for group '" + parentGroup.name + "'. Skipping this group."); continue; } soundType = parentGroup.name; if (string.IsNullOrEmpty(firstGroupName)) { firstGroupName = soundType; } var newWeightedChildren = new List<Transform>(); // ReSharper disable TooWideLocalVariableScope SoundGroupVariation variation; SoundGroupVariation childVariation; Transform child; // ReSharper restore TooWideLocalVariableScope 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; case AudioLocation.FileOnInternet: AudioResourceOptimizer.AddTargetForClip(childVariation.internetFileUrl, 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; case AudioLocation.FileOnInternet: AudioResourceOptimizer.AddTargetForClip(variation.internetFileUrl, 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 (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); _randomizerLeftovers.Add(soundType, new List<int>(playedStatuses.Count)); // fill leftovers pool. _randomizerLeftovers[soundType].AddRange(playedStatuses); _clipsPlayedBySoundTypeOldestFirst.Add(soundType, new List<int>()); playedStatuses = new List<int>(); } BusFades.Clear(); GroupFades.Clear(); // ReSharper disable TooWideLocalVariableScope Playlist pl; float firstSongLength; // ReSharper restore TooWideLocalVariableScope // check Syncrhonized Playlists for problems! // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < musicPlaylists.Count; i++) { pl = musicPlaylists[i]; if (pl.songTransitionType != SongFadeInPosition.SynchronizeClips) { continue; } if (pl.MusicSettings.Count < 2) { continue; } var songOne = pl.MusicSettings[0].clip; if (songOne == null) { continue; } firstSongLength = songOne.length; for (var s = 1; s < pl.MusicSettings.Count; s++) { var clip = pl.MusicSettings[s].clip; if (clip == null) { continue; } if (clip.length == firstSongLength) { continue; } Debug.LogWarning("Playlist '" + pl.playlistName + "' is marked as Synchronized but the clip lengths are not all the same within the Playlist. Clips may not synchronize as intended."); break; } } // 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)) { continue; } duckingBySoundType.Add(aDuck.soundType, aDuck); } _soundsLoaded = true; _warming = true; // pre-warm the code so the first sound played for real doesn't have to JIT and be slow. if (!string.IsNullOrEmpty(firstGroupName)) { var result = PlaySound3DFollowTransform(firstGroupName, Trans, 0f); if (result != null && result.SoundPlayed) { result.ActingVariation.Stop(); } } FireCustomEvent("FakeEvent", _trans.position); // 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); } // done warming _warming = false; // ReSharper disable once ForCanBeConvertedToForeach for (var i = 0; i < allVars.Count; i++) { allVars[i].DisableUpdater(); } // fixed: make sure this happens before Playlists start or the volume won't be right. PersistentAudioSettings.RestoreMasterSettings(); }
// ReSharper disable once FunctionComplexityOverflow private static PlaySoundResult PlaySoundIfAvailable(AudioInfo info, Vector3 sourcePosition, float volumePercentage, ref bool forgetSoundPlayed, float? pitch = null, AudioGroupInfo audioGroup = null, Transform sourceTrans = null, bool attachToSource = false, float delaySoundTime = 0f, bool useVector3 = false, bool makePlaySoundResult = false, bool isChaining = false, bool isSingleSubscribedPlay = false) { if (info.Source == null) { // this avoids false errors when stopping the game (from became "invisible" event callers) return null; } // ReSharper disable once PossibleNullReferenceException var maGroup = audioGroup.Group; if (maGroup.curVariationMode == MasterAudioGroup.VariationMode.Normal && info.Source.isPlaying) { var playedPercentage = AudioUtil.GetAudioPlayedPercentage(info.Source); var retriggerPercent = maGroup.retriggerPercentage; if (playedPercentage < retriggerPercent) { return null; // wait for this to stop playing or play further. } } info.Variation.Stop(); info.Variation.ObjectToFollow = null; var shouldUseClipAgePriority = Instance.prioritizeOnDistance && (Instance.useClipAgePriority || info.Variation.ParentGroup.useClipAgePriority); if (useVector3) { info.Source.transform.position = sourcePosition; if (Instance.prioritizeOnDistance) { AudioPrioritizer.Set3DPriority(info.Source, shouldUseClipAgePriority); } } else if (sourceTrans != null) { if (attachToSource) { info.Variation.ObjectToFollow = sourceTrans; } else { info.Source.transform.position = sourceTrans.position; info.Variation.ObjectToTriggerFrom = sourceTrans; } if (Instance.prioritizeOnDistance) { AudioPrioritizer.Set3DPriority(info.Source, shouldUseClipAgePriority); } } else { // "2d manner" - from Master Audio location if (Instance.prioritizeOnDistance) { AudioPrioritizer.Set2DSoundPriority(info.Source); } info.Source.transform.localPosition = Vector3.zero; // put it back in MA prefab position after being detached. } var groupVolume = maGroup.groupMasterVolume; var busVolume = GetBusVolume(maGroup); var varVol = info.OriginalVolume; var randomVol = 0f; if (info.Variation.useRandomVolume) { // random volume randomVol = UnityEngine.Random.Range(info.Variation.randomVolumeMin, info.Variation.randomVolumeMax); switch (info.Variation.randomVolumeMode) { case SoundGroupVariation.RandomVolumeMode.AddToClipVolume: varVol += randomVol; break; case SoundGroupVariation.RandomVolumeMode.IgnoreClipVolume: varVol = randomVol; break; } } var calcVolume = varVol * groupVolume * busVolume * Instance._masterAudioVolume; // set volume to percentage. var volume = calcVolume * volumePercentage; var targetVolume = volume; info.Source.volume = targetVolume; // save these for on the fly adjustments afterward info.LastPercentageVolume = volumePercentage; info.LastRandomVolume = randomVol; // ReSharper disable once JoinDeclarationAndInitializer bool isActive; #if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 isActive = info.Variation.GameObj.active; #else isActive = info.Variation.GameObj.activeInHierarchy; #endif if (!isActive) { return null; } PlaySoundResult result = null; if (makePlaySoundResult) { result = new PlaySoundResult { ActingVariation = info.Variation }; if (delaySoundTime > 0f) { result.SoundScheduled = true; } else { result.SoundPlayed = true; } } else { forgetSoundPlayed = true; } var soundType = maGroup.GameObjectName; var isChainLoop = maGroup.curVariationMode == MasterAudioGroup.VariationMode.LoopedChain; if (isChainLoop) { if (!isChaining) { maGroup.ChainLoopCount = 0; } var objFollow = info.Variation.ObjectToFollow; // make sure there isn't 2 chains going, ever! if (maGroup.ActiveVoices > 0 && !isChaining) { StopAllOfSound(soundType); } // restore this because it is lost from the Stop above; info.Variation.ObjectToFollow = objFollow; } info.Variation.Play(pitch, targetVolume, soundType, volumePercentage, targetVolume, pitch, sourceTrans, attachToSource, delaySoundTime, isChaining, isSingleSubscribedPlay); return result; }
private static void RemoveClipAndRefillIfEmpty(AudioGroupInfo grp, bool isNonSpecific, int? randomIndex, List<int> choices, string sType, int pickedChoice, bool loggingEnabledForGrp, bool isSingleVarLoop) { if (isSingleVarLoop) { grp.Group.ChainLoopCount++; // this doesn't call Refill Sound Group where this normally occurs so this part needs to happen separately return; } if (isNonSpecific && randomIndex.HasValue) { // only if successfully played! choices.RemoveAt(randomIndex.Value); _clipsPlayedBySoundTypeOldestFirst[sType].Add(pickedChoice); if (choices.Count == 0) { if (loggingEnabledForGrp) { LogMessage("Refilling Variation pool: " + sType); } RefillSoundGroupPool(sType); } } if (grp.Group.curVariationSequence == MasterAudioGroup.VariationSequence.TopToBottom && grp.Group.useInactivePeriodPoolRefill) { UpdateRefillTime(sType, grp.Group.inactivePeriodSeconds); } }
private static void SetLastPlayed(AudioGroupInfo grp) { grp.LastTimePlayed = Time.realtimeSinceStartup; grp.LastFramePlayed = Time.frameCount; }
void Awake() { if (GameObject.FindObjectsOfType(typeof(MasterAudio)).Length > 1) { Destroy(gameObject); Debug.Log("More than one Master Audio prefab exists in this Scene. Destroying the newer one called '" + this.name + "'. You may wish to set up a Bootstrapper Scene so this does not occur."); return; } this.useGUILayout = false; soundsLoaded = false; innerLoopDelay = new WaitForSeconds(INNER_LOOP_CHECK_INTERVAL); var aud = this.GetComponent<AudioSource>(); if (aud != null) { // delete the previewer GameObject.Destroy(aud); } audioSourcesBySoundType.Clear(); playlistControllersByName.Clear(); lastTimeSoundGroupPlayed.Clear(); var plNames = new List<string>(); AudioResourceOptimizer.ClearAudioClips(); PlaylistController.Instances = null; // clear the cache var playlists = PlaylistController.Instances; for (var i = 0; i < playlists.Count; i++) { var aList = playlists[i]; if (plNames.Contains(aList.name)) { Debug.LogError("You have more than 1 Playlist Controller with the name '" + aList.name + "'. You must name them all uniquely or the same-named ones will be deleted once they awake."); continue; } else { plNames.Add(aList.name); } playlistControllersByName.Add(aList.name, aList); if (persistBetweenScenes) { DontDestroyOnLoad(aList); } } // start up Objects! if (persistBetweenScenes) { DontDestroyOnLoad(this.gameObject); } Transform parentGroup; List<AudioInfo> sources; var playedStatuses = new List<int>(); AudioSource source; AudioGroupInfo _group; MasterAudioGroup groupScript; randomizer = new Dictionary<string, List<int>>(); randomizerLeftovers = new Dictionary<string, List<int>>(); clipsPlayedBySoundTypeOldestFirst = new Dictionary<string, List<int>>(); string soundType = string.Empty; var firstGroupName = string.Empty; var allVars = new List<SoundGroupVariation>(); groupsToRemove = new List<string>(Trans.childCount); for (var k = 0; k < Trans.childCount; k++) { parentGroup = Trans.GetChild(k); sources = new List<AudioInfo>(); groupScript = parentGroup.GetComponent<MasterAudioGroup>(); if (groupScript == null) { Debug.LogError("MasterAudio could not find 'MasterAudioGroup' script for group '" + parentGroup.name + "'. Skipping this group."); continue; } soundType = parentGroup.name; if (string.IsNullOrEmpty(firstGroupName)) { firstGroupName = soundType; } var newWeightedChildren = new List<Transform>(); SoundGroupVariation variation = null; SoundGroupVariation childVariation = null; Transform child = null; for (int 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) { 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); if (childVariation.audLocation == MasterAudio.AudioLocation.ResourceFile) { AudioResourceOptimizer.AddTargetForClip(childVariation.resourceFileName, source); } } else { sources.Add(new AudioInfo(variation, source, source.volume)); allVars.Add(variation); if (variation.audLocation == MasterAudio.AudioLocation.ResourceFile) { var resFileName = AudioResourceOptimizer.GetLocalizedFileName(variation.useLocalization, variation.resourceFileName); AudioResourceOptimizer.AddTargetForClip(resFileName, source); } } } } // attach extra children from weight property. for (var i = 0; i < newWeightedChildren.Count; i++) { newWeightedChildren[i].parent = parentGroup; } _group = new AudioGroupInfo(sources, groupScript); if (groupScript.isSoloed) { soloedGroups.Add(groupScript); } if (audioSourcesBySoundType.ContainsKey(soundType)) { Debug.LogError("You have more than one SoundGroup named '" + soundType + "'. Ignoring the 2nd one. Please rename it."); continue; } _group._sources.Sort(delegate(AudioInfo x, AudioInfo y) { return x.variation.name.CompareTo(y.variation.name); }); // added code for persistent group volume var persistentVolume = PersistentAudioSettings.GetGroupVolume(soundType); if (persistentVolume.HasValue) { _group._group.groupMasterVolume = persistentVolume.Value; } audioSourcesBySoundType.Add(soundType, _group); for (var i = 0; i < sources.Count; i++) { playedStatuses.Add(i); } randomizer.Add(soundType, playedStatuses); randomizerLeftovers.Add(soundType, new List<int>(playedStatuses.Count)); clipsPlayedBySoundTypeOldestFirst.Add(soundType, new List<int>()); playedStatuses = new List<int>(); } busFades.Clear(); groupFades.Clear(); Playlist pl = null; float firstSongLength = 0f; // check Syncrhonized Playlists for problems! for (var i = 0; i < musicPlaylists.Count; i++) { pl = musicPlaylists[i]; if (pl.songTransitionType != SongFadeInPosition.SynchronizeClips) { continue; } if (pl.MusicSettings.Count < 2) { continue; } var songOne = pl.MusicSettings[0].clip; if (songOne == null) { continue; } firstSongLength = songOne.length; for (var s = 1; s < pl.MusicSettings.Count; s++) { var clip = pl.MusicSettings[s].clip; if (clip == null) { continue; } if (clip.length != firstSongLength) { Debug.LogError("Playlist '" + pl.playlistName + "' is marked as Synchronized but the clip lengths are not all the same within the Playlist. Clips may not synchronize as intended."); break; } } } // initialize persistent bus volumes for (var i = 0; i < groupBuses.Count; i++) { var busName = groupBuses[i].busName; var busVol = PersistentAudioSettings.GetBusVolume(busName); if (!busVol.HasValue) { continue; } SetBusVolumeByName(busName, busVol.Value); } // populate ducking sounds dictionary duckingBySoundType.Clear(); for (var i = 0; i < musicDuckingSounds.Count; i++) { var aDuck = musicDuckingSounds[i]; duckingBySoundType.Add(aDuck.soundType, aDuck); } soundsLoaded = true; warming = true; // pre-warm the code so the first sound played for real doesn't have to JIT and be slow. if (!string.IsNullOrEmpty(firstGroupName)) { var result = PlaySound3DFollowTransform(firstGroupName, Trans, 0f, 1f, 0f, null); if (result != null && result.SoundPlayed) { result.ActingVariation.Stop(); } } FireCustomEvent("FakeEvent", this.trans.position); // Event Sounds warmer var evts = GameObject.FindObjectsOfType(typeof(EventSounds)); if (evts.Length > 0) { var evt = evts[0] as EventSounds; evt.PlaySounds(evt.particleCollisionSound, EventSounds.EventType.UserDefinedEvent); } // done warming warming = false; for (var i = 0; i < allVars.Count; i++) { allVars[i].DisableUpdater(); } // fixed: make sure this happens before Playlists start or the volume won't be right. PersistentAudioSettings.RestoreMasterSettings(); }
private static PlaySoundResult PlaySoundIfAvailable(string soundGroupName, AudioInfo info, Vector3 sourcePosition, float volumePercentage, ref bool forgetSoundPlayed, float? pitch = null, AudioGroupInfo audioGroup = null, Transform sourceTrans = null, bool attachToSource = false, float delaySoundTime = 0f, bool useVector3 = false, bool makePlaySoundResult = false, bool isChaining = false) { if (info.source == null) { // this avoids false errors when stopping the game (from became invisible event callers) return null; } MasterAudioGroup maGroup = audioGroup._group; if (info.source.audio.isPlaying) { var playedPercentage = AudioUtil.GetAudioPlayedPercentage(info.source); var retriggerPercent = maGroup.retriggerPercentage; if (playedPercentage < retriggerPercent) { return null; // wait for this to stop playing or play further. } } info.variation.Stop(); info.variation.ObjectToFollow = null; if (useVector3) { info.source.transform.position = sourcePosition; if (MasterAudio.Instance.prioritizeOnDistance) { AudioPrioritizer.Set3dPriority(info.source); } } else if (sourceTrans != null) { if (attachToSource) { info.variation.ObjectToFollow = sourceTrans; } else { info.source.transform.position = sourceTrans.position; } if (MasterAudio.Instance.prioritizeOnDistance) { AudioPrioritizer.Set3dPriority(info.source); } } else { // "2d manner" if (MasterAudio.Instance.prioritizeOnDistance) { AudioPrioritizer.Set2dSoundPriority(info.source); } info.source.transform.localPosition = Vector3.zero; // put it back in MA prefab position after being detached. } var groupVolume = maGroup.groupMasterVolume; var busVolume = GetBusVolume(maGroup); float calcVolume = info.originalVolume * groupVolume * busVolume * MasterAudio.Instance.masterAudioVolume; // set volume to percentage. float volume = calcVolume * volumePercentage; // random volume var randomVol = 0f; if (info.variation.randomVolume != 0f) { randomVol = UnityEngine.Random.Range(-info.variation.randomVolume, info.variation.randomVolume); } var targetVolume = volume + randomVol; info.source.audio.volume = targetVolume; // save these for on the fly adjustments afterward info.lastPercentageVolume = volumePercentage; info.lastRandomVolume = randomVol; bool isActive = false; #if UNITY_3_0 || UNITY_3_1 || UNITY_3_2 || UNITY_3_3 || UNITY_3_4 || UNITY_3_5 isActive = info.source.audio.gameObject.active; #else isActive = info.source.audio.gameObject.activeInHierarchy; #endif if (!isActive) { return null; } PlaySoundResult result = null; if (makePlaySoundResult) { result = new PlaySoundResult(); result.ActingVariation = info.variation; if (delaySoundTime > 0f) { result.SoundScheduled = true; } else { result.SoundPlayed = true; } } else { forgetSoundPlayed = true; } var playSoundParams = new SoundGroupVariation.PlaySoundParams(maGroup.name, volumePercentage, calcVolume, pitch, sourceTrans, attachToSource, delaySoundTime, maGroup.curVariationMode == MasterAudioGroup.VariationMode.LoopedChain); if (playSoundParams.isChainLoop && !isChaining) { maGroup.ChainLoopCount = 0; } if (playSoundParams.isChainLoop) { // make sure there isn't 2 going, ever MasterAudio.StopAllOfSound(playSoundParams.soundType); } info.variation.Play(pitch, targetVolume, playSoundParams); if (delaySoundTime == 0f) { // sound play worked! Duck music if a ducking sound. var ma = MasterAudio.Instance; var matchingDuck = ma.musicDuckingSounds.Find(delegate(DuckGroupInfo obj) { return obj.soundType == soundGroupName; }); if (ma.EnableMusicDucking && matchingDuck != null) { // duck music var duckLength = info.source.audio.clip.length; var duckPitch = info.source.pitch; var pcs = PlaylistController.Instances; for (var i = 0; i < pcs.Count; i++) { pcs[i].DuckMusicForTime(duckLength, duckPitch, matchingDuck.riseVolStart); } if (pcs.Count == 0) { Debug.LogWarning("Playlist Controller is not in the Scene. Cannot duck music."); } } } return result; }