miduo_client/Assets/Scripts/AnimatorEvent/AnimatorEventHandler.cs

384 lines
10 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

using UnityEngine;
using System.Collections;
using System.Collections.Generic;
#if UNITY_EDITOR
using System.IO;
#endif
public enum AnimatorEventType
{
Effect,
CameraShake,
Msg,
}
[System.Serializable]
public class MsgEvent
{
public MsgEvent()
{
type = AnimatorEventType.Msg;
}
public string msgFunction;
public string msgParams;
public AnimatorEventType type;
public string name = "";
public int layer = -1;
public float normalizedTime = 0.0f;
public bool IsEquals(object obj)
{
MsgEvent other = obj as MsgEvent;
if (other == null)
return false;
if (this.layer != other.layer
|| this.type != other.type
|| this.name != other.name
|| Mathf.Abs(this.normalizedTime - other.normalizedTime) > Mathf.Epsilon|| this.msgFunction != other.msgFunction
|| this.msgParams != other.msgParams)
return false;
return true;
}
}
[System.Serializable]
public class EventDataDic
{
public int stateHash;
public List<MsgEvent> eventList;
public EventDataDic(int hash)
{
stateHash = hash;
eventList=new List<MsgEvent>();
}
}
[System.Serializable]
public class AnimatorEventDatas
{
public List<EventDataDic> m_animatorEventData = null;
public void MakeSureEventList(int stateHash)
{
if (m_animatorEventData != null)
{
foreach (var eventList in m_animatorEventData)
{
if (eventList.stateHash == stateHash)
return;
}
}
else
{
m_animatorEventData = new List<EventDataDic>();
}
m_animatorEventData.Add(new EventDataDic(stateHash));
}
public List<MsgEvent> GetEventList(int stateHash)
{
if (m_animatorEventData != null)
{
foreach (var dataEventDic in m_animatorEventData)
{
if (dataEventDic.stateHash == stateHash)
return dataEventDic.eventList;
}
}
return null;
}
public List<MsgEvent> GetEventList(int stateHash, int layerIndex)
{
if (m_animatorEventData != null)
{
List<MsgEvent> events = new List<MsgEvent>();
foreach (var dataEventDic in m_animatorEventData)
{
if (dataEventDic.stateHash == stateHash)
{
for (int i = 0; i < dataEventDic.eventList.Count; ++i)
{
if (dataEventDic.eventList[i].layer == layerIndex || dataEventDic.eventList[i].layer == -1)
{
events.Add(dataEventDic.eventList[i]);
}
}
return events;
}
}
}
return null;
}
/// 干掉相同的事件
public bool RemoveSameEvents()
{
bool ret = false;
foreach (var itemData in m_animatorEventData)
{
var elem = itemData.eventList;
for (int i = elem.Count - 1; i >= 0; --i)
{
for (int j = i - 1; j >= 0; --j)
{
if (elem[i].IsEquals(elem[j]))
{
ret = true;
Debug.Log("removesameevents: key=" + itemData.stateHash + " type=" + elem[i].type + " name=" + elem[i].name + " time=" + elem[i].normalizedTime + " layer=" + elem[i].layer);
elem.RemoveAt(i);
break;
}
}
}
}
return ret;
}
public void Remove(int stateHash)
{
if (m_animatorEventData != null)
{
List<EventDataDic> deletEvents = new List<EventDataDic>();
foreach (var dataEventDic in m_animatorEventData)
{
if (dataEventDic.stateHash == stateHash)
{
deletEvents.Add(dataEventDic);
}
}
foreach(var delDataEvent in deletEvents)
{
m_animatorEventData.Remove(delDataEvent);
}
}
}
public bool HasEventStateHash(int stateHash)
{
foreach (var dataEventDic in m_animatorEventData)
{
if( dataEventDic.stateHash== stateHash)
{
return true;
}
}
return false;
}
public bool AddEvent(int stateHash, MsgEvent addEvent)
{
List<MsgEvent> eventList= GetEventList(stateHash);
if (eventList==null)
{
eventList = new List<MsgEvent>();
var eventDataDic= new EventDataDic(stateHash);
eventDataDic.eventList.Add(addEvent);
m_animatorEventData.Add(eventDataDic);
}
else
{
eventList.Add(addEvent);
}
return true;
}
public bool RemoveEvent(int stateHash, MsgEvent deleteEvent)
{
List<MsgEvent> eventList = GetEventList(stateHash);
if (eventList == null)
{
return false;
}
else
{
return eventList.Remove(deleteEvent);
}
}
}
[ExecuteInEditMode]
[RequireComponent(typeof(Animator))]
public class AnimatorEventHandler : MonoBehaviour {
class LayerRuntime {
public int stateNameHash = 0;
public float stateNormalizedTime = -0.000001f;
public float stateLength = 1;
public bool stateLoop = false;
}
#region private members
private Animator m_animator = null;
public AnimatorEventDatas animatorEventData = null;
private Dictionary<int, LayerRuntime> m_layerRuntimeDictionary = new Dictionary<int, LayerRuntime>();
#endregion
#region public members
public bool isUpdateEventInStateEndFrame = false;
#endregion
#region public properties
public Animator animator {
get {
if (m_animator == null) {
m_animator = GetComponent<Animator>();
}
return m_animator;
}
}
#endregion
void Start() {
Init();
}
void Init() {
if (animatorEventData == null)
{
animatorEventData = new AnimatorEventDatas();
}
m_layerRuntimeDictionary.Clear();
for (int i = 0; i < animator.layerCount; i++) {
m_layerRuntimeDictionary.Add(i, new LayerRuntime());
}
}
public AnimatorStateInfo GetCurrentStateInfo(int layerIndex) {
if (animator.IsInTransition(layerIndex)) {
return animator.GetNextAnimatorStateInfo(layerIndex);
}
return animator.GetCurrentAnimatorStateInfo(layerIndex);
}
void Update()
{
if (animator == null)
return;
if (animatorEventData == null)
return;
if (Time.deltaTime <= 0)
return;
if(Application.isPlaying)
{
for (int i = 0; i < animator.layerCount; ++i)
{
_UpdateLayer(i);
}
}
}
void _UpdateLayerChild(float stateNormalizedTime, LayerRuntime layerRuntime, int layerIndex)
{
int stateNameHash = layerRuntime.stateNameHash;
List<MsgEvent> eventList = animatorEventData.GetEventList(stateNameHash);
if (eventList == null)
return;
float currentTime = Time.time;
float currentNormalizedTime = stateNormalizedTime;
float lastNormalizedTime = layerRuntime.stateNormalizedTime;
layerRuntime.stateNormalizedTime = currentNormalizedTime;
int currentTimeFloor = Mathf.FloorToInt(currentNormalizedTime);
int lastTimeFloor = Mathf.FloorToInt(lastNormalizedTime);
float stateLength = layerRuntime.stateLength;
bool stateLoop = layerRuntime.stateLoop;
for (int i = 0; i < eventList.Count; ++i) {
MsgEvent animatorEvent = eventList[i];
if (layerIndex != animatorEvent.layer && animatorEvent.layer != -1)
continue;
if (!stateLoop) {
float eventNormailzedTime = animatorEvent.normalizedTime;
if (eventNormailzedTime > lastNormalizedTime && eventNormailzedTime <= currentNormalizedTime) {
float deltaNormalizedTime = currentNormalizedTime - animatorEvent.normalizedTime;
float eventFiredTime = currentTime - deltaNormalizedTime * stateLength;
App.LuaMgr.CallFunction(eventList[i].msgFunction,eventList[i].msgParams);
}
} else {
float floorTime = currentTime - Mathf.Repeat(currentNormalizedTime, 1f) * stateLength;
for (int floor = currentTimeFloor; floor >= lastTimeFloor && floor >= 0; --floor, floorTime -= stateLength) {
float eventNormailzedTime = floor + animatorEvent.normalizedTime;
if (eventNormailzedTime > lastNormalizedTime && eventNormailzedTime <= currentNormalizedTime) {
float eventFiredTime = floorTime + animatorEvent.normalizedTime * stateLength;
App.LuaMgr.CallFunction(eventList[i].msgFunction, eventList[i].msgParams);
}
}
}
}
}
// 是否处理状态切换结束帧的事件
public bool IsUpdateEventInStateEndFrame {
get {
return isUpdateEventInStateEndFrame;
}
set {
isUpdateEventInStateEndFrame = value;
}
}
private LayerRuntime layerRuntime;
void _UpdateLayer(int layerIndex)
{
AnimatorStateInfo stateInfo = GetCurrentStateInfo(layerIndex);
if (stateInfo.length <= 0f) { // 对于Empty做处理其实是异常情况
if (m_layerRuntimeDictionary.TryGetValue(layerIndex, out layerRuntime)) {
layerRuntime.stateNameHash = stateInfo.fullPathHash;
}
return;
}
float _stateNormalizedTime = stateInfo.normalizedTime;
if (!m_layerRuntimeDictionary.TryGetValue(layerIndex, out layerRuntime))
{
return;
}
if (layerRuntime.stateNameHash != stateInfo.fullPathHash||(_stateNormalizedTime < 1&& (_stateNormalizedTime < layerRuntime.stateNormalizedTime|| Time.deltaTime > stateInfo.length)))
{
if (isUpdateEventInStateEndFrame && layerRuntime.stateNameHash != stateInfo.fullPathHash)
{
float stateNormalizedTime = layerRuntime.stateNormalizedTime+ (Time.deltaTime - _stateNormalizedTime * stateInfo.length) / layerRuntime.stateLength;
if (stateNormalizedTime > 1)
{
stateNormalizedTime = 1;
}
_UpdateLayerChild(stateNormalizedTime, layerRuntime, layerIndex);
}
layerRuntime.stateLength = stateInfo.length;
layerRuntime.stateLoop = stateInfo.loop;
layerRuntime.stateNameHash = stateInfo.fullPathHash;
layerRuntime.stateNormalizedTime = -1f;
}
_UpdateLayerChild(_stateNormalizedTime, layerRuntime, layerIndex);
}
IEnumerator UpdateLayer() {
while (true) {
yield return new WaitForEndOfFrame();
for (int i = 0; i < animator.layerCount; ++i) {
_UpdateLayer(i);
}
}
}
}