/// <summary>
 /// Called when the volumes enabled on a layer have changed.
 /// </summary>
 /// <param name="layer">The layer to mark dirty.</param>
 internal void SetLayerDirty(VolumeLayer layer)
 {
     m_sortNeeded[layer] = true;
 }
        /// <summary>
        /// Finds the volumes on a layer that have a non-zero influence given a scene point.
        /// </summary>
        /// <param name="target">The transform whose position is used to compute volume distance.
        /// When null, only global volumes are considred.</param>
        /// <param name="layer">The volume layer controlling which volumes are evaluated.</param>
        /// <returns>A list of relevant volumes sorted by decending weight.</returns>
        public IReadOnlyList <WeightedVolume> Evaluate(Transform target, VolumeLayer layer)
        {
            m_weightedVolumes.Clear();

            if (layer == null)
            {
                return(m_weightedVolumes);
            }

            if (!m_volumes.TryGetValue(layer, out var volumes))
            {
                return(m_weightedVolumes);
            }

            // update the volume layer if it is dirty
            if (m_sortNeeded[layer])
            {
                volumes.Sort((a, b) => a.Priority.CompareTo(b.Priority));
                m_sortNeeded[layer] = false;
            }

            foreach (var volume in volumes)
            {
                if (!volume.enabled || volume.Weight <= 0)
                {
                    continue;
                }

                if (volume.IsGlobal)
                {
                    AddWeightedVolume(new WeightedVolume
                    {
                        volume = volume,
                        weight = volume.Weight,
                    });
                    continue;
                }

                if (target == null || volume.Colliders.Count == 0)
                {
                    continue;
                }

                // find the squared distance from the volume to the point
                var pos = target.position;
                var closestDistanceSqr = float.PositiveInfinity;

                foreach (var collider in volume.Colliders)
                {
                    if (collider.enabled)
                    {
                        var d = (collider.ClosestPoint(pos) - pos).sqrMagnitude;
                        if (d < closestDistanceSqr)
                        {
                            closestDistanceSqr = d;
                        }
                    }
                }

                // check if the volume is close enough to have influence
                var blendDistSqr = volume.BlendDistance * volume.BlendDistance;

                if (closestDistanceSqr > blendDistSqr)
                {
                    continue;
                }

                // linearlize the distance and compute the influence
                var weight = volume.Weight;

                if (blendDistSqr > 0f)
                {
                    weight *= 1f - (Mathf.Sqrt(closestDistanceSqr) / Mathf.Sqrt(blendDistSqr));
                }

                AddWeightedVolume(new WeightedVolume
                {
                    volume = volume,
                    weight = weight,
                });
            }

            // sort the volumes by decending influence
            m_weightedVolumes.Sort((a, b) => b.weight.CompareTo(a.weight));

            return(m_weightedVolumes);
        }
        /// <inheritdoc/>
        protected override void UpdateBlending(Transform target, VolumeLayer layer)
        {
            foreach (var source in m_sources)
            {
                source.volume = 0f;
            }

            m_active.Clear();

            var profiles = AudioVolumeManager.Instance.Evaluate(target, layer);

            for (var i = 0; i < profiles.Count; i++)
            {
                var profileBlend = profiles[i];
                var volume       = profileBlend.volume;
                var profile      = volume.Audio;

                if (profile.Clip != null)
                {
                    // create an audiosource for this sound
                    if (!m_profileToSources.TryGetValue(profile, out var source))
                    {
                        source      = gameObject.AddComponent <AudioSource>();
                        source.clip = profile.Clip;
                        source.outputAudioMixerGroup = profile.Mixer;
                        source.playOnAwake           = false;
                        source.loop         = profile.Loop;
                        source.pitch        = profile.Pitch;
                        source.panStereo    = profile.Pan;
                        source.spatialBlend = 0f;

                        source.volume = 0f;

                        m_profileToSources.Add(profile, source);
                        m_sources.Add(source);
                    }

                    m_active.Add(source);

                    // set the volume based on the weight
                    var vol = volume.Volume * profileBlend.weight;

                    if (!source.isPlaying && vol > 0)
                    {
                        source.Play();
                    }

                    source.volume += vol;
                }
            }

            // make sure any sources not in an active volume are not playing
            foreach (var source in m_sources)
            {
                if (source.isPlaying && !m_active.Contains(source))
                {
                    if (m_restartWhenActivated)
                    {
                        source.Stop();
                    }
                    else
                    {
                        source.Pause();
                    }

                    source.volume = 0f;
                }
            }
        }
 /// <summary>
 /// Evaluates and applies the volume blend.
 /// </summary>
 /// <param name="target">The transform position to use.</param>
 /// <param name="layer">The volume layer controlling which volumes are evaluated.</param>
 protected abstract void UpdateBlending(Transform target, VolumeLayer layer);
예제 #5
0
        /// <inheritdoc/>
        protected override void UpdateBlending(Transform target, VolumeLayer layer)
        {
            foreach (var source in m_sources)
            {
                source.Volume = 0f;
            }

            m_active.Clear();

            var volumesWeights = MusicVolumeManager.Instance.Evaluate(target, layer);

            for (var i = 0; i < volumesWeights.Count; i++)
            {
                var profileBlend = volumesWeights[i];
                var volume       = profileBlend.volume;
                var profile      = volume.Music;

                if (profile != null && profile.Track != null)
                {
                    if (!m_profileToSources.TryGetValue(profile, out var source))
                    {
                        source = new MusicPlayer(gameObject, m_pausable)
                        {
                            Volume = 0f
                        };

                        m_profileToSources.Add(profile, source);
                        m_sources.Add(source);
                    }

                    m_active.Add(source);

                    // set the volume based on the weight
                    var vol = volume.Volume * profileBlend.weight;

                    if (!source.IsPlaying && vol > 0)
                    {
                        source.Play(profile);
                    }

                    source.Volume += vol;
                }
            }

            // make sure any sources not in an active volume are not playing
            foreach (var source in m_sources)
            {
                if (source.IsPlaying && !m_active.Contains(source))
                {
                    if (m_restartWhenActivated)
                    {
                        source.Stop();
                    }
                    else
                    {
                        source.Pause();
                    }

                    source.Volume = 0f;
                }

                source.Update();
            }
        }