Files
aibis-dream/Assets/Scripts/SceneManagement/TimelineKit/DirectorHandler.cs
T
2026-02-26 14:14:44 +08:00

240 lines
6.1 KiB
C#

using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.Playables;
using UnityEngine.AddressableAssets;
namespace AibisDream
{
public class DirectorHandler : MonoBehaviour
{
public string timelineName;
[SerializeField] private PlayableDirector director;
[Header("多条Timeline")]
[SerializeField] private AssetReference[] timelineList;
private Dictionary<string, PlayableAsset> _timelineDict = new();
private Action _onCompleteCallback;
#if UNITY_EDITOR
/// <summary>
/// 在 Editor 中,当组件创建或 Inspector 变化时自动查找同物体上的 PlayableDirector
/// </summary>
private void OnValidate()
{
if (director == null)
{
director = GetComponent<PlayableDirector>();
}
}
#endif
private void Awake()
{
if (director == null)
{
director = GetComponent<PlayableDirector>();
}
// timelineList转字典
}
private void Start()
{
TimelineCenter.Instance.RegisterDirector(this);
}
private void OnDestroy()
{
TimelineCenter.Instance.UnregisterDirector(this);
if (director != null)
{
director.stopped -= OnDirectorStopped;
}
}
/// <summary>
/// 播放 Timeline
/// </summary>
public void Play(Action onComplete = null)
{
if (director == null)
{
Debug.LogError($"DirectorHandler {timelineName}: PlayableDirector is null");
return;
}
// 先停止再播放
director.stopped -= OnDirectorStopped;
if (director.state == PlayState.Playing)
{
director.Stop();
}
_onCompleteCallback = onComplete;
// 如果有完成回调,订阅 stopped 事件
if (onComplete != null)
{
director.stopped += OnDirectorStopped;
}
director.Play();
}
/// <summary>
/// 异步播放 Timeline(协程版本)
/// </summary>
public IEnumerator PlayAsync()
{
if (director == null)
{
Debug.LogError($"DirectorHandler {timelineName}: PlayableDirector is null");
yield break;
}
// 先停止再播放
if (director.state == PlayState.Playing)
{
director.Stop();
}
director.Play();
// 等待播放完成
while (director.state == PlayState.Playing)
{
yield return null;
}
}
/// <summary>
/// 停止播放
/// </summary>
public void Stop()
{
if (director == null) return;
// 先取消事件订阅,避免 Stop() 触发回调
director.stopped -= OnDirectorStopped;
director.Stop();
_onCompleteCallback = null;
}
/// <summary>
/// 暂停播放
/// </summary>
public void Pause()
{
if (director == null) return;
if (director.state == PlayState.Playing)
{
director.Pause();
}
}
/// <summary>
/// 恢复播放
/// </summary>
public void Resume()
{
if (director == null) return;
if (director.state == PlayState.Paused)
{
director.Resume();
}
}
/// <summary>
/// 重置 Timeline
/// </summary>
public void Reset()
{
if (director == null) return;
// 先取消事件订阅,避免 Stop() 触发回调
director.stopped -= OnDirectorStopped;
director.Stop();
director.time = 0;
director.Evaluate();
_onCompleteCallback = null;
}
/// <summary>
/// 获取当前播放时间
/// </summary>
public double GetPlaybackTime()
{
if (director == null) return 0;
return director.time;
}
/// <summary>
/// 获取总时长
/// </summary>
public double GetDuration()
{
if (director == null) return 0;
return director.duration;
}
/// <summary>
/// 设置播放速度
/// </summary>
public void SetPlaybackSpeed(float speed)
{
if (director == null) return;
if (director.playableGraph.IsValid())
{
director.playableGraph.GetRootPlayable(0).SetSpeed(speed);
}
else
{
Debug.LogWarning($"DirectorHandler {timelineName}: PlayableGraph is not valid. Cannot set playback speed.");
}
}
/// <summary>
/// 跳转到指定时间点
/// </summary>
public void SeekToTime(double time)
{
if (director == null) return;
director.time = Math.Clamp(time, 0, director.duration);
director.Evaluate();
}
/// <summary>
/// Director 停止事件处理
/// </summary>
private void OnDirectorStopped(PlayableDirector director)
{
// 立即取消订阅,避免重复触发
director.stopped -= OnDirectorStopped;
var callback = _onCompleteCallback;
_onCompleteCallback = null;
callback?.Invoke();
}
// /// <summary>
// /// 对象销毁时清理事件订阅
// /// </summary>
// private void OnDestroy()
// {
// }
}
}