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;
|
|
}
|
|
}
|
|
} |