using System; using System.Collections.Generic; using UnityEngine.Audio; using UnityEngine.Playables; namespace UnityEngine.Timeline { /// /// A Timeline track that can play AudioClips. /// [Serializable] [TrackClipType(typeof(AudioPlayableAsset), false)] [TrackBindingType(typeof(AudioSource))] [ExcludeFromPreset] [TimelineHelpURL(typeof(AudioTrack))] public class AudioTrack : TrackAsset { [SerializeField] AudioMixerProperties m_TrackProperties = new AudioMixerProperties(); #if UNITY_EDITOR Playable m_LiveMixerPlayable = Playable.Null; #endif /// /// Create an TimelineClip for playing an AudioClip on this track. /// /// The audio clip to play /// A TimelineClip with an AudioPlayableAsset asset. public TimelineClip CreateClip(AudioClip clip) { if (clip == null) return null; var newClip = CreateDefaultClip(); var audioAsset = newClip.asset as AudioPlayableAsset; if (audioAsset != null) audioAsset.clip = clip; newClip.duration = clip.length; newClip.displayName = clip.name; return newClip; } internal override Playable CompileClips(PlayableGraph graph, GameObject go, IList timelineClips, IntervalTree tree) { var clipBlender = AudioMixerPlayable.Create(graph, timelineClips.Count); #if UNITY_EDITOR clipBlender.GetHandle().SetScriptInstance(m_TrackProperties.Clone()); m_LiveMixerPlayable = clipBlender; #else if (hasCurves) clipBlender.GetHandle().SetScriptInstance(m_TrackProperties.Clone()); #endif for (int i = 0; i < timelineClips.Count; i++) { var c = timelineClips[i]; var asset = c.asset as PlayableAsset; if (asset == null) continue; var buffer = 0.1f; var audioAsset = c.asset as AudioPlayableAsset; if (audioAsset != null) buffer = audioAsset.bufferingTime; var source = asset.CreatePlayable(graph, go); if (!source.IsValid()) continue; if (source.IsPlayableOfType()) { // Enforce initial values on all clips var audioClipPlayable = (AudioClipPlayable)source; var audioClipProperties = audioClipPlayable.GetHandle().GetObject(); audioClipPlayable.SetVolume(Mathf.Clamp01(m_TrackProperties.volume * audioClipProperties.volume)); audioClipPlayable.SetStereoPan(Mathf.Clamp(m_TrackProperties.stereoPan, -1.0f, 1.0f)); audioClipPlayable.SetSpatialBlend(Mathf.Clamp01(m_TrackProperties.spatialBlend)); } tree.Add(new ScheduleRuntimeClip(c, source, clipBlender, buffer)); graph.Connect(source, 0, clipBlender, i); source.SetSpeed(c.timeScale); source.SetDuration(c.extrapolatedDuration); clipBlender.SetInputWeight(source, 1.0f); } ConfigureTrackAnimation(tree, go, clipBlender); return clipBlender; } /// public override IEnumerable outputs { get { yield return AudioPlayableBinding.Create(name, this); } } #if UNITY_EDITOR internal void LiveLink() { if (!m_LiveMixerPlayable.IsValid()) return; var audioMixerProperties = m_LiveMixerPlayable.GetHandle().GetObject(); if (audioMixerProperties == null) return; audioMixerProperties.volume = m_TrackProperties.volume; audioMixerProperties.stereoPan = m_TrackProperties.stereoPan; audioMixerProperties.spatialBlend = m_TrackProperties.spatialBlend; } #endif void OnValidate() { m_TrackProperties.volume = Mathf.Clamp01(m_TrackProperties.volume); m_TrackProperties.stereoPan = Mathf.Clamp(m_TrackProperties.stereoPan, -1.0f, 1.0f); m_TrackProperties.spatialBlend = Mathf.Clamp01(m_TrackProperties.spatialBlend); } } }