using UnityEngine; using UnityEngine.Playables; using UnityEngine.Video; namespace UnityEngine.Timeline { public class VideoPlayableBehaviour : PlayableBehaviour { public VideoPlayer videoPlayer; public VideoClip videoClip; public bool mute = false; public bool loop = true; public double preloadTime = 0.3; public double clipInTime = 0.0; private bool playedOnce = false; private bool preparing = false; public void PrepareVideo() { if (videoPlayer == null || videoClip == null) return; videoPlayer.targetCameraAlpha = 0.0f; if (videoPlayer.clip != videoClip) StopVideo(); if (videoPlayer.isPrepared || preparing) return; videoPlayer.source = VideoSource.VideoClip; videoPlayer.clip = videoClip; videoPlayer.playOnAwake = false; videoPlayer.waitForFirstFrame = true; videoPlayer.isLooping = loop; for (ushort i = 0; i < videoClip.audioTrackCount; ++i) { if (videoPlayer.audioOutputMode == VideoAudioOutputMode.Direct) videoPlayer.SetDirectAudioMute(i, mute || !Application.isPlaying); else if (videoPlayer.audioOutputMode == VideoAudioOutputMode.AudioSource) { AudioSource audioSource = videoPlayer.GetTargetAudioSource(i); if (audioSource != null) audioSource.mute = mute || !Application.isPlaying; } } videoPlayer.loopPointReached += LoopPointReached; videoPlayer.time = clipInTime; videoPlayer.Prepare(); preparing = true; } void LoopPointReached(VideoPlayer vp) { playedOnce = !loop; } public override void PrepareFrame(Playable playable, FrameData info) { if (videoPlayer == null || videoClip == null) return; videoPlayer.timeReference = Application.isPlaying ? VideoTimeReference.ExternalTime : VideoTimeReference.Freerun; if (videoPlayer.isPlaying && Application.isPlaying) videoPlayer.externalReferenceTime = playable.GetTime(); else if (!Application.isPlaying) SyncVideoToPlayable(playable); } public override void OnBehaviourPlay(Playable playable, FrameData info) { if (videoPlayer == null) return; if (!playedOnce) { PlayVideo(); SyncVideoToPlayable(playable); } } public override void OnBehaviourPause(Playable playable, FrameData info) { if (videoPlayer == null) return; if (Application.isPlaying) PauseVideo(); else StopVideo(); } public override void ProcessFrame(Playable playable, FrameData info, object playerData) { if (videoPlayer == null || videoPlayer.clip == null) return; videoPlayer.targetCameraAlpha = info.weight; if (Application.isPlaying) { for (ushort i = 0; i < videoPlayer.clip.audioTrackCount; ++i) { if (videoPlayer.audioOutputMode == VideoAudioOutputMode.Direct) videoPlayer.SetDirectAudioVolume(i, info.weight); else if (videoPlayer.audioOutputMode == VideoAudioOutputMode.AudioSource) { AudioSource audioSource = videoPlayer.GetTargetAudioSource(i); if (audioSource != null) audioSource.volume = info.weight; } } } } public override void OnGraphStart(Playable playable) { playedOnce = false; } public override void OnGraphStop(Playable playable) { if (!Application.isPlaying) StopVideo(); } public override void OnPlayableDestroy(Playable playable) { StopVideo(); } public void PlayVideo() { if (videoPlayer == null) return; videoPlayer.Play(); preparing = false; if (!Application.isPlaying) PauseVideo(); } public void PauseVideo() { if (videoPlayer == null) return; videoPlayer.Pause(); preparing = false; } public void StopVideo() { if (videoPlayer == null) return; playedOnce = false; videoPlayer.Stop(); preparing = false; } private void SyncVideoToPlayable(Playable playable) { if (videoPlayer == null || videoPlayer.clip == null) return; videoPlayer.time = (clipInTime + (playable.GetTime() * videoPlayer.playbackSpeed)) % videoPlayer.clip.length; } } }