240 lines
6.1 KiB
C#
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()
|
|
// {
|
|
|
|
// }
|
|
}
|
|
}
|