228 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C#
		
	
	
	
			
		
		
	
	
			228 lines
		
	
	
		
			5.1 KiB
		
	
	
	
		
			C#
		
	
	
	
| using System.Collections;
 | |
| using System.Collections.Generic;
 | |
| using UnityEngine;
 | |
| using UnityEngine.Playables;
 | |
| using UnityEngine.Animations;
 | |
| 
 | |
| namespace MotionFramework.Experimental.Animation
 | |
| {
 | |
| 	public class AnimPlayable
 | |
| 	{
 | |
| 		private readonly List<AnimState> _states = new List<AnimState>(10);
 | |
| 		private readonly List<AnimMixer> _mixers = new List<AnimMixer>(10);
 | |
| 
 | |
| 		private PlayableGraph _graph;
 | |
| 		private AnimationPlayableOutput _output;
 | |
| 		private AnimationLayerMixerPlayable _mixerRoot;
 | |
| 
 | |
| 		public void Create(Animator animator)
 | |
| 		{
 | |
| 			string name = animator.gameObject.name;
 | |
| 			_graph = PlayableGraph.Create(name);
 | |
| 			_graph.SetTimeUpdateMode(DirectorUpdateMode.Manual);
 | |
| 
 | |
| 			_mixerRoot = AnimationLayerMixerPlayable.Create(_graph);
 | |
| 			_output = AnimationPlayableOutput.Create(_graph, name, animator);
 | |
| 			_output.SetSourcePlayable(_mixerRoot);
 | |
| 		}
 | |
| 		public void Update(float deltaTime)
 | |
| 		{
 | |
| 			_graph.Evaluate(deltaTime);
 | |
| 
 | |
| 			// 更新所有层级
 | |
| 			for (int i = 0; i < _mixers.Count; i++)
 | |
| 			{
 | |
| 				var mixer = _mixers[i];
 | |
| 				if(mixer.IsConnect)
 | |
| 					mixer.Update(deltaTime);
 | |
| 			}
 | |
| 		}
 | |
| 		public void Destroy()
 | |
| 		{
 | |
| 			_graph.Destroy();
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Play the graph
 | |
| 		/// </summary>
 | |
| 		public void PlayGraph()
 | |
| 		{
 | |
| 			_graph.Play();
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// Stop the graph
 | |
| 		/// </summary>
 | |
| 		public void StopGraph()
 | |
| 		{
 | |
| 			_graph.Stop();
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// 检测动画是否正在播放
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">动画名称</param>
 | |
| 		public bool IsPlaying(string name)
 | |
| 		{
 | |
| 			AnimState state = GetAnimState(name);
 | |
| 			if (state == null)
 | |
| 				return false;
 | |
| 
 | |
| 			return state.IsConnect && state.IsPlaying;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// 播放一个动画
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">动画名称</param>
 | |
| 		/// <param name="fadeLength">融合时间</param>
 | |
| 		public void Play(string name, float fadeLength)
 | |
| 		{
 | |
| 			var animState = GetAnimState(name);
 | |
| 			if (animState == null)
 | |
| 			{
 | |
| 				MotionLog.Warning($"Not found animation {name}");
 | |
| 				return;
 | |
| 			}
 | |
| 
 | |
| 			int layer = animState.Layer;
 | |
| 			var animMixer = GetAnimMixer(layer);
 | |
| 			if (animMixer == null)
 | |
| 				animMixer = CreateAnimMixer(layer);
 | |
| 
 | |
| 			if(animMixer.IsConnect == false)
 | |
| 				animMixer.Connect(_mixerRoot, animMixer.Layer);		
 | |
| 
 | |
| 			animMixer.Play(animState, fadeLength);
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// 停止一个动画
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">动画名称</param>
 | |
| 		public void Stop(string name)
 | |
| 		{
 | |
| 			var animState = GetAnimState(name);
 | |
| 			if (animState == null)
 | |
| 			{
 | |
| 				MotionLog.Warning($"Not found animation {name}");
 | |
| 				return;
 | |
| 			}
 | |
| 
 | |
| 			if (animState.IsConnect == false)
 | |
| 				return;
 | |
| 
 | |
| 			var animMixer = GetAnimMixer(animState.Layer);
 | |
| 			if (animMixer == null)
 | |
| 				throw new System.Exception("Should never get here.");
 | |
| 
 | |
| 			animMixer.Stop(animState.Name);
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// 添加一个动画片段
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">动画名称</param>
 | |
| 		/// <param name="clip">动画片段</param>
 | |
| 		/// <param name="layer">动画层级</param>
 | |
| 		public bool AddAnimation(string name, AnimationClip clip, int layer = 0)
 | |
| 		{
 | |
| 			if (string.IsNullOrEmpty(name))
 | |
| 				throw new System.ArgumentException("Name is null or empty.");
 | |
| 			if (clip == null)
 | |
| 				throw new System.ArgumentNullException();
 | |
| 			if (layer < 0)
 | |
| 				throw new System.Exception("Layer must be greater than zero.");
 | |
| 
 | |
| 			if (IsContains(name))
 | |
| 			{
 | |
| 				MotionLog.Warning($"Animation already exists : {name}");
 | |
| 				return false;
 | |
| 			}
 | |
| 
 | |
| 			AnimState stateNode = new AnimState(_graph, clip, name, layer);
 | |
| 			_states.Add(stateNode);
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// 移除一个动画片段
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">动画名称</param>
 | |
| 		public bool RemoveAnimation(string name)
 | |
| 		{
 | |
| 			if (IsContains(name) == false)
 | |
| 			{
 | |
| 				MotionLog.Warning($"Not found Animation : {name}");
 | |
| 				return false;
 | |
| 			}
 | |
| 
 | |
| 			AnimState animState = GetAnimState(name);
 | |
| 			AnimMixer animMixer = GetAnimMixer(animState.Layer);
 | |
| 			if(animMixer != null)
 | |
| 				animMixer.RemoveState(animState.Name);
 | |
| 
 | |
| 			animState.Destroy();
 | |
| 			_states.Remove(animState);
 | |
| 			return true;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// 获取一个动画状态
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">动画名称</param>
 | |
| 		public AnimState GetAnimState(string name)
 | |
| 		{
 | |
| 			for (int i = 0; i < _states.Count; i++)
 | |
| 			{
 | |
| 				if (_states[i].Name == name)
 | |
| 					return _states[i];
 | |
| 			}
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		/// <summary>
 | |
| 		/// 是否包含一个动画状态
 | |
| 		/// </summary>
 | |
| 		/// <param name="name">动画名称</param>
 | |
| 		public bool IsContains(string name)
 | |
| 		{
 | |
| 			for (int i = 0; i < _states.Count; i++)
 | |
| 			{
 | |
| 				if (_states[i].Name == name)
 | |
| 					return true;
 | |
| 			}
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		private AnimMixer GetAnimMixer(int layer)
 | |
| 		{
 | |
| 			for (int i = 0; i < _mixers.Count; i++)
 | |
| 			{
 | |
| 				if (_mixers[i].Layer == layer)
 | |
| 					return _mixers[i];
 | |
| 			}
 | |
| 			return null;
 | |
| 		}
 | |
| 		private AnimMixer CreateAnimMixer(int layer)
 | |
| 		{
 | |
| 			// Increase input count
 | |
| 			int inputCount = _mixerRoot.GetInputCount();
 | |
| 			if(layer == 0 && inputCount == 0)
 | |
| 			{
 | |
| 				_mixerRoot.SetInputCount(1);
 | |
| 			}
 | |
| 			else
 | |
| 			{
 | |
| 				if (layer > inputCount - 1)
 | |
| 				{
 | |
| 					_mixerRoot.SetInputCount(layer + 1);
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			var animMixer = new AnimMixer(_graph, layer);
 | |
| 			_mixers.Add(animMixer);
 | |
| 			return animMixer;
 | |
| 		}
 | |
| 	}
 | |
| } |