2025-10-09 17:44:56 +09:00

134 lines
4.5 KiB
C#

using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.Video;
[System.Serializable]
public class VideoPlayerBehaviour : PlayableBehaviour
{
public VideoClip videoClip;
public float playbackSpeed = 1f;
private VideoPlayer m_VideoPlayer;
private PlayableDirector m_Director;
private bool m_VideoSetup = false;
private bool m_WasTimelinePlaying = false;
private double m_LastSyncTime = -1;
private int m_SyncCooldownFrames = 0;
private const int SYNC_COOLDOWN_DURATION = 5;
public override void OnPlayableCreate(Playable playable)
{
if (m_Director == null)
{
m_Director = Object.FindFirstObjectByType<PlayableDirector>();
}
m_VideoSetup = false;
m_WasTimelinePlaying = false;
m_LastSyncTime = -1;
m_SyncCooldownFrames = 0;
}
public override void ProcessFrame(Playable playable, FrameData info, object playerData)
{
if (playerData == null) return;
m_VideoPlayer = playerData as VideoPlayer;
if (m_VideoPlayer == null) return;
if (m_SyncCooldownFrames > 0)
{
m_SyncCooldownFrames--;
}
if (!m_VideoSetup && videoClip != null)
{
m_VideoPlayer.clip = videoClip;
m_VideoSetup = true;
}
if (info.weight > 0.5f)
{
bool isTimelinePlaying = m_Director != null && m_Director.state == PlayState.Playing;
double normalizedTime = playable.GetTime() / playable.GetDuration();
double targetTime = normalizedTime * videoClip.length;
if (isTimelinePlaying != m_WasTimelinePlaying)
{
Debug.Log($"Timeline state changed: {m_WasTimelinePlaying} -> {isTimelinePlaying}");
if (isTimelinePlaying)
{
Debug.Log($"Starting playback at time: {targetTime:F3} (Timeline: {playable.GetTime():F3})");
m_VideoPlayer.time = targetTime;
m_VideoPlayer.playbackSpeed = playbackSpeed;
m_LastSyncTime = targetTime;
m_SyncCooldownFrames = SYNC_COOLDOWN_DURATION;
if (!m_VideoPlayer.isPlaying)
{
m_VideoPlayer.Play();
}
}
else
{
Debug.Log($"Pausing at time: {m_VideoPlayer.time:F3}");
if (m_VideoPlayer.isPlaying)
{
m_VideoPlayer.Pause();
}
}
m_WasTimelinePlaying = isTimelinePlaying;
}
if (isTimelinePlaying)
{
if (m_SyncCooldownFrames <= 0)
{
double timeDiff = Mathf.Abs((float)(m_VideoPlayer.time - targetTime));
if (timeDiff > 0.3)
{
Debug.Log($"Large drift detected - Re-syncing: Video={m_VideoPlayer.time:F3}, Target={targetTime:F3}, Diff={timeDiff:F3}");
if (m_VideoPlayer.isPrepared)
{
m_VideoPlayer.time = targetTime;
m_LastSyncTime = targetTime;
m_SyncCooldownFrames = SYNC_COOLDOWN_DURATION;
}
}
}
}
else
{
if (m_SyncCooldownFrames <= 0)
{
double timeDiff = Mathf.Abs((float)(m_VideoPlayer.time - targetTime));
if (timeDiff > 0.033)
{
if (m_VideoPlayer.isPrepared)
{
m_VideoPlayer.time = targetTime;
m_LastSyncTime = targetTime;
m_SyncCooldownFrames = 2;
}
}
}
}
}
}
public override void OnBehaviourPause(Playable playable, FrameData info)
{
Debug.Log("Clip ended - stopping video");
if (m_VideoPlayer != null)
{
m_VideoPlayer.Pause();
}
m_WasTimelinePlaying = false;
m_LastSyncTime = -1;
m_SyncCooldownFrames = 0;
}
}