最近使用动画时,需要在播放动画时调用函数,于是想了想便自己实现一个动画的事件工具类,废话不多说了 直接上代码:
/****************************************************
文件:GAnimationCtrl.cs
作者:GHY
邮箱: 851267723@qq.com
日期:2019/2/23 16:55:57
功能:动画控制器
*****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class GAnimationCtrl<T>
{
private Dictionary<AnimationClip, GAnimationEvent<T>> animDic = new Dictionary<AnimationClip, GAnimationEvent<T>>();
public Animation animation;
public bool IsRun { get; set; }
public float Rate { get; private set; }
public GAnimationCtrl(Animation animation, float rate = 0.1f)
{
if (animation == null)
{
throw new NullReferenceException();
}
this.animation = animation;
this.Rate = rate;
IsRun = false;
if (!GServiceManager.isExist)
{
GameObject go = new GameObject("GServiceManager");
go.AddComponent<GServiceManager>().Init();
}
}
public void RegisterEvent(AnimationClip clip, GAnimationEvent<T> animEvent)
{
GAnimationEvent<T> evt = null;
if (animDic.TryGetValue(clip, out evt))
{
if (animEvent != null)
{
evt.beginEvt = animEvent.beginEvt;
evt.runEvt = animEvent.runEvt;
evt.endEvt = animEvent.endEvt;
}
}
else
{
evt = new GAnimationEvent<T>();
if (animEvent != null)
{
evt.beginEvt = animEvent.beginEvt;
evt.runEvt = animEvent.runEvt;
evt.endEvt = animEvent.endEvt;
evt.beginParm = animEvent.beginParm;
evt.runParm = animEvent.runParm;
evt.endParm = animEvent.endParm;
}
animDic.Add(clip, evt);
}
}
public void RemoveEvent(AnimationClip clip)
{
animDic.Remove(clip);
}
public void RemoveEvent(AnimationClip clip, GEventType type)
{
GAnimationEvent<T> evt = null;
if (animDic.TryGetValue(clip, out evt))
{
switch (type)
{
case GEventType.Begin:
evt.beginEvt = null;
evt.beginParm = default(T);
break;
case GEventType.Run:
evt.runEvt = null;
evt.runParm = default(T);
break;
case GEventType.End:
evt.endEvt = null;
evt.endParm = default(T);
break;
}
}
}
public GAnimationEvent<T> GetCurrentEvent()
{
AnimationClip clip = animation.clip;
GAnimationEvent<T> evt = null;
if (clip != null && animation.isPlaying)
{
animDic.TryGetValue(clip, out evt);
}
return evt;
}
}
/****************************************************
文件:GAnimatorCtrl.cs
作者:GHY
邮箱: 851267723@qq.com
日期:2019/2/23 16:55:57
功能:动画状态机控制器
*****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class GAnimatorCtrl<T>
{
private Dictionary<GAnimatorInfo, GAnimationEvent<T>> animDic = new Dictionary<GAnimatorInfo, GAnimationEvent<T>>();
private Dictionary<string, GAnimatorInfo> infoDic = new Dictionary<string, GAnimatorInfo>();
private Animator animator;
public bool IsRun { get; set; }
public float Rate { get; private set; }
public GAnimatorCtrl(Animator animator, float rate = 0.1f)
{
if (animator == null)
{
throw new NullReferenceException();
}
this.animator = animator;
this.Rate = rate;
IsRun = false;
if (!GServiceManager.isExist)
{
GameObject go = new GameObject("GServiceManager");
go.AddComponent<GServiceManager>().Init();
}
}
public void RegisterEvent(GAnimatorInfo info,GAnimationEvent<T> evt)
{
GAnimationEvent<T> evt1 = new GAnimationEvent<T>();
if (!animDic.ContainsKey(info))
{
if (evt != null && info.state != GAnimatorState.None)
{
evt1.beginEvt = evt.beginEvt;
evt1.runEvt = evt.runEvt;
evt1.endEvt = evt.endEvt;
evt1.beginParm = evt.beginParm;
evt1.runParm = evt.runParm;
evt1.endParm = evt.endParm;
animDic.Add(info, evt);
infoDic.Add(info.name, info);
}
}
}
public void RemoveState(GAnimatorInfo info)
{
animDic.Remove(info);
infoDic.Remove(info.name);
}
public void RemoveEvent(GAnimatorInfo info, GEventType type)
{
GAnimationEvent<T> evt = null;
if(animDic.TryGetValue(info, out evt))
{
switch (type)
{
case GEventType.Begin:
evt.beginEvt = null;
evt.beginParm = default(T);
break;
case GEventType.Run:
evt.runEvt = null;
evt.runParm = default(T);
break;
case GEventType.End:
evt.endEvt = null;
evt.endParm = default(T);
break;
}
}
}
public GAnimationEvent<T> GetCurrentEvent()
{
AnimatorClipInfo[] clips = animator.GetCurrentAnimatorClipInfo(0);
if (clips.Length > 0)
{
string name = clips[0].clip.name;
GAnimationEvent<T> evt = null;
GAnimatorInfo info = null; ;
infoDic.TryGetValue(name, out info);
if (info != null) animDic.TryGetValue(info, out evt);
return evt;
}
return null;
}
}
/****************************************************
文件:GServiceHelp.cs
作者:GHY
邮箱: 851267723@qq.com
日期:2019/2/23 16:55:57
功能:服务管理
*****************************************************/
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System;
public class GServiceManager : MonoBehaviour
{
public static GServiceManager instance { get; private set; }
public static bool isExist = false;
public void Init()
{
DontDestroyOnLoad(this);
instance = this;
isExist = true;
}
public static void StartSvc<T>(GAnimatorCtrl<T> ctrl)
{
if (ctrl != null && ctrl.IsRun == false)
{
ctrl.IsRun = true;
instance.StartCoroutine(instance.Run(ctrl));
}
}
public static void StartSvc<T>(GAnimationCtrl<T> ctrl)
{
if (ctrl != null && ctrl.IsRun == false)
{
ctrl.IsRun = true;
instance.StartCoroutine(instance.Run(ctrl));
}
}
public static void StopSvc<T>(GAnimatorCtrl<T> ctrl)
{
if (ctrl != null && ctrl.IsRun == true)
{
ctrl.IsRun = false;
}
}
public static void StopSvc<T>(GAnimationCtrl<T> ctrl)
{
if (ctrl != null && ctrl.IsRun == true)
{
ctrl.IsRun = false;
}
}
private IEnumerator Run<T>(GAnimatorCtrl<T> ctrl)
{
GAnimationEvent<T> current = ctrl.GetCurrentEvent();
if (current != null) current.BeginEvtCall();
while (true)
{
GAnimationEvent<T> current1 = ctrl.GetCurrentEvent();
if (current1 != current)
{
if (current != null)
{
current.EndEvtCall();
}
if (current1 != null) {
current1.BeginEvtCall();
}
current = current1;
}
if (current1 != null)
{
current1.RunEvtCall();
}
if (ctrl.IsRun == false) yield break;
yield return new WaitForSeconds(ctrl.Rate);
}
}
private IEnumerator Run<T>(GAnimationCtrl<T> ctrl)
{
GAnimationEvent<T> current = ctrl.GetCurrentEvent();
if (current != null) current.BeginEvtCall();
while (true)
{
GAnimationEvent<T> current1 = ctrl.GetCurrentEvent();
if (current1 != current)
{
if (current != null)
{
current.EndEvtCall();
}
if (current1 != null)
{
current1.BeginEvtCall();
}
current = current1;
}
if (current1 != null)
{
current1.RunEvtCall();
}
if (ctrl.IsRun == false) yield break;
yield return new WaitForSeconds(ctrl.Rate);
}
}
}
/****************************************************
文件:GServiceHelp.cs
作者:GHY
邮箱: 851267723@qq.com
日期:2019/2/23 16:55:57
功能:数据帮助定义处
*****************************************************/
using System;
public enum GEventType
{
Begin,
Run,
End
}
public class GAnimatorInfo
{
public string name;
public GAnimatorState state;
}
public enum GAnimatorState
{
None,
Idle,
Walk,
Run
}
public class GAnimationEvent<T>
{
public Action<T> beginEvt;
public Action<T> runEvt;
public Action<T> endEvt;
public T beginParm;
public T runParm;
public T endParm;
public void BeginEvtCall()
{
if (beginEvt != null)
{
beginEvt(beginParm);
}
}
public void RunEvtCall()
{
if (runEvt != null)
{
runEvt(runParm);
}
}
public void EndEvtCall()
{
if (endEvt != null)
{
endEvt(endParm);
}
}
}
一共4个类 GAnimationCtrl与GAnimatorCtrl都是需要用到,一个对应动画,一个对应动画状态机,实例化后注册事件,通过GServiceManager.StartSvc来启动,通过GServiceManager.StopSvc来停止 之所以定义GAnimatorState枚举,只为了更好判断状态机现在处于哪个动画.
新人博主 新手程序员,有问题、意见 都可以加QQ,加QQ说明来意即可 谢谢 多多点赞
补充:
需要案例的可以加QQ说明来意