using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.Playables; using UnityEngine.Animations; namespace MotionFramework.Experimental.Animation { public abstract class AnimNode { private readonly PlayableGraph _graph; private Playable _source; private Playable _parent; private float _fadeSpeed = 0f; private float _fadeWeight = 0f; private bool _isFading = false; /// /// 是否已经连接 /// public bool IsConnect { get; private set; } = false; /// /// 输入端口 /// public int InputPort { private set; get; } /// /// 是否已经完成 /// If the duration of the playable is set, when the time of the playable reaches its duration during playback this flag will be set to true. /// public bool IsDone { get { return _source.IsDone(); } } /// /// 是否有效 /// if the Playable is properly constructed by the PlayableGraph and has not been destroyed, false otherwise. /// public bool IsValid { get { return _source.IsValid(); } } /// /// 是否正在播放中 /// public bool IsPlaying { get { return _source.GetPlayState() == PlayState.Playing; } } /// /// 时间轴 /// public float Time { set { _source.SetTime(value); } get { return (float)_source.GetTime(); } } /// /// 播放速度 /// public float Speed { set { _source.SetSpeed(value); } get { return (float)_source.GetSpeed(); } } /// /// 权重值 /// public float Weight { set { _parent.SetInputWeight(InputPort, value); } get { return _parent.GetInputWeight(InputPort); } } public AnimNode(PlayableGraph graph) { _graph = graph; } public virtual void Update(float deltaTime) { if (_isFading) { Weight = Mathf.MoveTowards(Weight, _fadeWeight, _fadeSpeed * deltaTime); if (Mathf.Approximately(Weight, _fadeWeight)) { _isFading = false; } } } public virtual void Destroy() { if (IsValid) { _graph.DestroySubgraph(_source); } } public virtual void PlayNode() { // NOTE : When playing, the local time of this Playable will be updated during the evaluation of the PlayableGraph. _source.Play(); // NOTE : Changes a flag indicating that a playable has completed its operation. // Playable that reach the end of their duration are automatically marked as done. _source.SetDone(false); } public virtual void PauseNode() { // NOTE : When paused, the local time of this Playable will not be updated during the evaluation of the PlayableGraph. _source.Pause(); // NOTE : Changes a flag indicating that a playable has completed its operation. // Playable that reach the end of their duration are automatically marked as done. _source.SetDone(true); } public virtual void ResetNode() { _fadeSpeed = 0; _fadeWeight = 0; _isFading = false; Time = 0; Speed = 1; Weight = 0; } /// /// 连接到父节点 /// /// 父节点对象 /// 父节点上的输入端口 public void Connect(Playable parent, int parentInputPort) { if (IsConnect) throw new System.Exception("AnimNode is connected."); _parent = parent; InputPort = parentInputPort; // 重置节点 ResetNode(); // 连接 _graph.Connect(_source, 0, parent, parentInputPort); IsConnect = true; } /// /// 同父节点断开连接 /// public void Disconnect() { if (IsConnect == false) throw new System.Exception("AnimNode is disconnected."); // 断开 _graph.Disconnect(_parent, InputPort); IsConnect = false; } /// /// 开始权重值过渡 /// /// 目标权重值 /// 过渡时间 public void StartWeightFade(float destWeight, float fadeDuration) { if (fadeDuration <= 0) { Weight = destWeight; _isFading = false; return; } //注意:保持统一的渐变速度 _fadeSpeed = 1f / fadeDuration; _fadeWeight = destWeight; _isFading = true; } protected void SetSourcePlayable(Playable playable) { _source = playable; } } }