Skip to content

Commit d6add48

Browse files
committed
做了如下修改:
1. 加入了 loglevel,可以选择输出哪些级别的log 2. await 模式下的时间是 oneshot,常规的不是 3. await 支持返回 AnimationEvent,这样就能获取动画信息啦! 4. 加入了事件的移除功能,并在 demo 中进行了演示
1 parent 94a0217 commit d6add48

File tree

9 files changed

+175
-50
lines changed

9 files changed

+175
-50
lines changed

Assets/MecanimEventSystem/Example/AnimClips/EventListener.cs

Lines changed: 54 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -15,28 +15,69 @@ private void Start()
1515
}
1616
private void OnGUI()
1717
{
18-
if (GUILayout.Button("Rotate动态添加回调 (oneshot)"))
18+
EventHandler.LogLevels = LogLevel.All & ~LogLevel.Warning; // warning 再本示例中输出太多,先干掉!
19+
void OnCompletedForRotate(AnimationEvent v)
1920
{
20-
animator.SetTarget("Rotate").OnCompleted((v) =>
21+
string clipname = v.animatorClipInfo.clip.name;
22+
if (v.animatorStateInfo.IsName("Base Layer.Rotate"))//演示Base Layer的事件接受 ---因为AnimationClip在这个动画机中被多次复用,层别Layer信息是非常必要的(区别于上面的示例)
2123
{
22-
string clipname = v.animatorClipInfo.clip.name;
23-
if (v.animatorStateInfo.IsName("Base Layer.Rotate"))//演示Base Layer的事件接受 ---因为AnimationClip在这个动画机中被多次复用,层别Layer信息是非常必要的(区别于上面的示例)
24-
{
25-
Debug.Log("结束时Base Layer:" + clipname + ":" + v.time * v.animatorClipInfo.clip.frameRate);
26-
}
24+
Debug.Log("结束时<color=red>Base Layer:</color>" + clipname + ":" + v.time * v.animatorClipInfo.clip.frameRate);
25+
}
26+
if (v.animatorStateInfo.IsName("New Layer.Rotate1212"))//演示其它层的事件接受
27+
{
28+
Debug.Log("结束时<color=green>New Layer:</color>" + clipname + ":" + v.time * v.animatorClipInfo.clip.frameRate);
29+
}
30+
}
31+
32+
33+
if (GUILayout.Button("1. Rotate动态添加回调"))
34+
{
35+
animator.SetTarget("Rotate").OnCompleted(OnCompletedForRotate);
36+
}
37+
if (GUILayout.Button("移除上面添加的回调"))
38+
{
39+
animator.RemoveListener(OnCompletedForRotate, "Rotate");
40+
}
2741

28-
if (v.animatorStateInfo.IsName("New Layer.Rotate1212"))//演示其它层的事件接受
29-
{
30-
Debug.Log("结束时New Layer:" + clipname + ":" + v.time * v.animatorClipInfo.clip.frameRate);
31-
}
32-
});
42+
void OnCompletedForRotateOneceMore(AnimationEvent v)
43+
{
44+
string clipname = v.animatorClipInfo.clip.name;
45+
if (v.animatorStateInfo.IsName("Base Layer.Rotate"))//演示Base Layer的事件接受
46+
{
47+
Debug.Log("结束时<color=red>Base Layer:</color>" + clipname + ":" + v.time * v.animatorClipInfo.clip.frameRate + "又搞一次!");
48+
}
49+
if (v.animatorStateInfo.IsName("New Layer.Rotate1212"))//演示其它层的事件接受
50+
{
51+
Debug.Log("结束时<color=green>New Layer:</color>" + clipname + ":" + v.time * v.animatorClipInfo.clip.frameRate + "又搞一次!");
52+
}
3353
}
3454

35-
if (GUILayout.Button("触发baseLayer.Left (oneshot)"))
55+
56+
if (GUILayout.Button("2. 为 Rotate 再叠加一个回调"))
57+
{
58+
animator.SetTarget("Rotate").OnCompleted(OnCompletedForRotateOneceMore);
59+
}
60+
if (GUILayout.Button("移除上面叠加的回调"))
61+
{
62+
animator.RemoveListener(OnCompletedForRotateOneceMore, "Rotate");
63+
}
64+
65+
66+
if (GUILayout.Button("3. 触发baseLayer.Left"))
3667
{
3768
animator.SetTrigger("Left");
3869
}
3970

71+
if (animator.HasAnyListener("Rotate"))
72+
{
73+
if (GUILayout.Button("4. 触发 BaseLayer.Rotate "))
74+
{
75+
animator.SetTrigger("Rotate");
76+
}
77+
}
78+
79+
EventHandler.LogLevels = LogLevel.All;
80+
4081
}
4182
}
4283
}

Assets/MecanimEventSystem/Example/TestForAwait/Test.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -45,8 +45,8 @@ private async void OnButtonClicked()
4545
{
4646
button.interactable = false;
4747
Debug.Log($"{nameof(Test)}: Default is expand , Now start collapse!");
48-
await callbackClps.SetBoolAsync("Expand", false);
49-
Debug.Log($"{nameof(Test)}: collapse Completed !");
48+
var r = await callbackClps.SetBoolAsync("Expand", false);
49+
Debug.Log($"{nameof(Test)}: collapse Completed , clip name = {r.animatorClipInfo.clip.name}!");
5050
text.text = "collapsed";
5151
}
5252

Assets/MecanimEventSystem/Runtime/Async/MESCustomAwaiter.cs

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ public static class MESCustomAwaiter
88
public static AnimationAwaiter SetBoolAsync(this EventState state, string paramName, bool value)
99
{
1010
var awaiter = new AnimationAwaiter();
11-
state.OnCompleted(v => awaiter.Complete());
11+
state.OnCompleted(awaiter.SetResult);
1212
state.SetBool(paramName, value);
1313
return awaiter;
1414
}
@@ -34,10 +34,12 @@ public void OnCompleted(Action continuation)
3434
}
3535

3636
public AnimationAwaiter GetAwaiter() => this;
37-
public object GetResult() => null;
38-
public void Complete()
37+
public AnimationEvent GetResult() => animationEvent;
38+
AnimationEvent animationEvent;
39+
public void SetResult(AnimationEvent ae)
3940
{
4041
_isDone = true;
42+
animationEvent = ae;
4143
if (Thread.CurrentThread.ManagedThreadId == id)
4244
{
4345
_continuation?.Invoke();

Assets/MecanimEventSystem/Runtime/CallbackListener.cs

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1-
using System.Numerics;
1+
using Codice.CM.SEIDInfo;
2+
using System;
3+
using System.Collections.Generic;
4+
using System.Numerics;
25
using UnityEditor;
36
using UnityEngine;
47
using static zFrame.Event.EventHandler;
@@ -19,9 +22,18 @@ private void AnimatorEventCallBack(AnimationEvent ae)
1922
AnimationClip clip = ae.animatorClipInfo.clip;//动画片段名称
2023
int currentFrame = Mathf.FloorToInt(ae.animatorClipInfo.clip.frameRate * ae.time); //动画片段当前帧 向下取整
2124
var actions = GetAction(animator, clip, currentFrame);
22-
foreach (var item in actions)
25+
var temp = new List<Action<AnimationEvent>>(actions);
26+
for (int i = 0; i < temp.Count; i++)
2327
{
24-
item?.Invoke(ae);
28+
var action = temp[i];
29+
if (action != null)
30+
{
31+
action.Invoke(ae);
32+
if (action.Method.DeclaringType.Name == nameof(AnimationAwaiter)) // the callback which comes from AnimationAwaiter should be oneshot event.
33+
{
34+
actions.Remove(action);
35+
}
36+
}
2537
}
2638
}
2739
}

Assets/MecanimEventSystem/Runtime/EventExtension.cs

Lines changed: 22 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using UnityEngine;
1+
using System;
2+
using UnityEngine;
23
using static zFrame.Event.EventHandler;
34

45
namespace zFrame.Event
@@ -13,7 +14,7 @@ public static class EventExtension
1314
/// <returns>事件配置器</returns>
1415
public static EventState SetTarget(this Animator animator, string clipName)
1516
{
16-
EventInfo a_EventInfo = GenerAnimationInfo(animator, clipName);
17+
EventInfo a_EventInfo = GetAnimationInfo(animator, clipName);
1718
animator.EnsureComponent<CallbackListener>();
1819
//获得需要处理的动画片段
1920
return new EventState(a_EventInfo);
@@ -27,7 +28,7 @@ public static EventState SetTarget(this Animator animator, string clipName)
2728
/// <returns>事件配置器</returns>
2829
public static EventState GetEventConfig(this Animator animator, string clipName)
2930
{
30-
EventInfo a_EventInfo = GenerAnimationInfo(animator, clipName);
31+
EventInfo a_EventInfo = GetAnimationInfo(animator, clipName);
3132
animator.EnsureComponent<CallbackListener>();
3233
//获得需要处理的动画片段
3334
return new EventState(a_EventInfo);
@@ -41,13 +42,29 @@ public static EventState GetEventConfig(this Animator animator, string clipName)
4142
/// <returns>事件配置器</returns>
4243
public static EventState SetTarget(this Animator animator, string clipName, int frame)
4344
{
44-
EventInfo a_EventInfo = GenerAnimationInfo(animator, clipName);
45+
EventInfo a_EventInfo = GetAnimationInfo(animator, clipName);
4546
animator.EnsureComponent<CallbackListener>();
4647
//获得需要处理的动画片段
4748
return new EventState(a_EventInfo, frame);
4849
}
4950

50-
51+
public static void RemoveListener(this Animator animator, Action<AnimationEvent> action, string clipName, int frame = -1)
52+
{
53+
EventInfo a_EventInfo = GetAnimationInfo(animator, clipName, false);
54+
if (null != a_EventInfo)
55+
{
56+
a_EventInfo.RemoveListener(frame, action);
57+
}
58+
}
59+
public static bool HasAnyListener(this Animator animator, string clipName, int frame = -1)
60+
{
61+
EventInfo a_EventInfo = GetAnimationInfo(animator, clipName, false);
62+
if (null != a_EventInfo)
63+
{
64+
return a_EventInfo.HasAnyListener(frame);
65+
}
66+
return false;
67+
}
5168
private static T EnsureComponent<T>(this Component target) where T : Component
5269
{
5370
T component = target.GetComponent<T>();

Assets/MecanimEventSystem/Runtime/EventHandler.cs

Lines changed: 47 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,23 @@
22
using System.Collections.Generic;
33
using UnityEngine;
44

5+
[Flags]
6+
public enum LogLevel
7+
{
8+
None = 1,
9+
Error = 2,
10+
Warning = 4,
11+
Info = 8,
12+
All = Error | Warning | Info
13+
}
14+
515
namespace zFrame.Event
616
{
717
public static class EventHandler
818
{
919
/// <summary>动画机及其事件信息Pairs</summary>
1020
private static List<EventInfo> eventContainer = new List<EventInfo>();
21+
public static LogLevel LogLevels = LogLevel.All;
1122

1223
private const string func = "AnimatorEventCallBack";
1324

@@ -17,12 +28,12 @@ public static class EventHandler
1728
/// <param name="animator">动画机</param>
1829
/// <param name="clipName">动画片段名称</param>
1930
/// <param name="frame">指定帧</param>
20-
public static EventInfo GenerAnimationInfo(Animator animator, string clipName)
31+
public static EventInfo GetAnimationInfo(Animator animator, string clipName, bool createIfNotFound = true)
2132
{
2233
AnimationClip clip = GetAnimationClip(animator, clipName);
2334
if (clip)
2435
{
25-
return GetEventInfo(animator, clip); //获取指定事件信息类
36+
return GetEventInfo(animator, clip, createIfNotFound); //获取指定事件信息类
2637
}
2738
else
2839
{
@@ -39,16 +50,22 @@ public static void GenerateAnimationEvent(EventInfo eventInfo, int frame)
3950
{
4051
if (frame < 0 || frame > eventInfo.totalFrames)
4152
{
42-
Debug.LogError($"AnimatorEventSystem[紧急]:【{eventInfo.animator.name}】所在的动画机【{eventInfo.animationClip.name}】片段帧数设置错误【{frame}】!");
53+
if (LogLevels.HasFlag(LogLevel.Error))
54+
{
55+
Debug.LogError($"AnimatorEventSystem[紧急]:【{eventInfo.animator.name}】所在的动画机【{eventInfo.animationClip.name}】片段帧数设置错误【{frame}】!");
56+
}
4357
return;
4458
}
4559
float _time = frame / eventInfo.animationClip.frameRate;
4660
AnimationEvent[] events = eventInfo.animationClip.events;
47-
AnimationEvent varEvent = Array.Find(events, v =>Mathf.Approximately(v.time, _time));
61+
AnimationEvent varEvent = Array.Find(events, v => Mathf.Approximately(v.time, _time));
4862
if (null != varEvent)
4963
{
5064
if (varEvent.functionName == func) return;
51-
Debug.Log($"AnimatorEventSystem[一般]:【{eventInfo.animator.name}】所在的动画机【{eventInfo.animationClip.name}】片段【{frame}】帧已存在回调方法【{varEvent.functionName}】,将自动覆盖!");
65+
if (LogLevels.HasFlag(LogLevel.Info))
66+
{
67+
Debug.Log($"AnimatorEventSystem[一般]:【{eventInfo.animator.name}】所在的动画机【{eventInfo.animationClip.name}】片段【{frame}】帧已存在回调方法【{varEvent.functionName}】,将自动覆盖!");
68+
}
5269
}
5370
varEvent = new()
5471
{
@@ -58,7 +75,10 @@ public static void GenerateAnimationEvent(EventInfo eventInfo, int frame)
5875
};
5976
eventInfo.animationClip.AddEvent(varEvent); //绑定事件
6077
eventInfo.animator.Rebind(); //重新绑定动画器的所有动画的属性和网格数据。
61-
Debug.Log($"{nameof(EventHandler)}:完成 AnimationEvent 添加, 建议优先在编辑器下就把事件安插OK以避免动画机的重新绑定,see more ↓ \nClip Name = {eventInfo.animationClip.name} , frame = {frame} , time = {_time} ,Function Name = {func}");
78+
if (LogLevels.HasFlag(LogLevel.Info))
79+
{
80+
Debug.Log($"{nameof(EventHandler)}:完成 AnimationEvent 添加, 建议优先在编辑器下就把事件安插OK以避免动画机的重新绑定,see more ↓ \nClip Name = {eventInfo.animationClip.name} , frame = {frame} , time = {_time} ,Function Name = {func}");
81+
}
6282
}
6383

6484
/// <summary>数据重置,用于总管理类清理数据用</summary>
@@ -78,10 +98,10 @@ public static void Clear()
7898
/// <param name="animator">动画机</param>
7999
/// <param name="clip">动画片段</param>
80100
/// <returns>事件信息类</returns>
81-
private static EventInfo GetEventInfo(Animator animator, AnimationClip clip)
101+
private static EventInfo GetEventInfo(Animator animator, AnimationClip clip, bool createIfNotFound = true)
82102
{
83103
EventInfo a_EventInfo = eventContainer.Find(v => v.animator == animator && v.animationClip == clip);
84-
if (null == a_EventInfo)
104+
if (null == a_EventInfo && createIfNotFound)
85105
{
86106
a_EventInfo = new EventInfo(animator, clip);
87107
eventContainer.Add(a_EventInfo);
@@ -100,25 +120,33 @@ public static AnimationClip GetAnimationClip(Animator animator, string name)
100120
#region 异常提示
101121
if (null == animator)
102122
{
103-
Debug.LogError("AnimatorEventSystem[紧急]:指定Animator不得为空!");
123+
if (LogLevels.HasFlag(LogLevel.Error))
124+
{
125+
Debug.LogError("AnimatorEventSystem[紧急]:指定Animator不得为空!");
126+
}
104127
return null;
105128
}
106129
RuntimeAnimatorController runtimeAnimatorController = animator.runtimeAnimatorController;
107130
if (null == runtimeAnimatorController)
108131
{
109-
Debug.LogError("AnimatorEventSystem[紧急]:指定【" + animator.name + "】Animator未挂载Controller!");
132+
if (LogLevels.HasFlag(LogLevel.Error))
133+
{
134+
Debug.LogError("AnimatorEventSystem[紧急]:指定【" + animator.name + "】Animator未挂载Controller!");
135+
}
110136
return null;
111137
}
112138
AnimationClip[] clips = runtimeAnimatorController.animationClips;
113139
AnimationClip[] varclip = Array.FindAll(clips, v => v.name == name);
114140
if (null == varclip || varclip.Length == 0)
115141
{
116-
Debug.LogError("AnimatorEventSystem[紧急]:指定【" + animator.name + "】Animator不存在名为【" + name + "】的动画片段!");
117-
return null;
142+
throw new InvalidOperationException("AnimatorEventSystem[紧急]:指定【" + animator.name + "】Animator不存在名为【" + name + "】的动画片段!");
118143
}
119144
if (varclip.Length >= 2)
120145
{
121-
Debug.LogWarningFormat("AnimatorEventSystem[一般]:指定【{0}】Animator存在【{1}】个名为【{2}】的动画片段!\n 建议:若非复用导致的重名,请务必修正!否则,事件将绑定在找的第一个Clip上。", animator.name, varclip.Length, name);
146+
if (LogLevels.HasFlag(LogLevel.Warning))
147+
{
148+
Debug.LogWarning($"AnimatorEventSystem[一般]:指定【{animator.name}】Animator存在【{varclip.Length}】个名为【{name}】的动画片段!\n 建议:若非复用导致的重名,请务必修正!否则,事件将绑定在找的第一个Clip上。");
149+
}
122150
}
123151
#endregion
124152
return varclip[0];
@@ -136,14 +164,13 @@ public static List<Action<AnimationEvent>> GetAction(Animator animator, Animatio
136164
EventInfo a_EventInfo = eventContainer.Find(v => v.animator == animator && v.animationClip == clip);
137165
if (null != a_EventInfo)
138166
{
139-
if (a_EventInfo.frameCallBackPairs.ContainsKey(frame))
140-
{
141-
actions = new(a_EventInfo.frameCallBackPairs[frame]);
142-
a_EventInfo.frameCallBackPairs[frame] = new(); // just one shot
143-
}
144-
else
167+
if (!a_EventInfo.frameCallBackPairs.TryGetValue(frame, out actions))
145168
{
146-
Debug.LogWarning($"{nameof(EventHandler)}: Key [frame = {frame}] dose not exsit! \n {animator.name} - {clip.name}");
169+
actions = new();
170+
if (LogLevels.HasFlag(LogLevel.Warning))
171+
{
172+
Debug.LogWarning($"{nameof(EventHandler)}: Key [frame = {frame}] dose not exsit! \n {animator.name} - {clip.name}");
173+
}
147174
}
148175
}
149176
return actions;

Assets/MecanimEventSystem/Runtime/EventInfo.cs

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,30 @@ public EventInfo(Animator anim, AnimationClip clip)
2525
//经验表明需要 向下取整 以获取当前的帧数
2626
totalFrames = Mathf.FloorToInt(animationClip.frameRate * animationClip.length);
2727
}
28+
public void RemoveListener(int frame, Action<AnimationEvent> action)
29+
{
30+
if (frame == -1)
31+
{
32+
frame = totalFrames;
33+
}
34+
if (frameCallBackPairs.ContainsKey(frame))
35+
{
36+
frameCallBackPairs[frame].Remove(action);
37+
}
38+
}
39+
40+
public bool HasAnyListener(int frame)
41+
{
42+
if (frame == -1)
43+
{
44+
frame = totalFrames;
45+
}
46+
if (frameCallBackPairs.TryGetValue(frame, out var list))
47+
{
48+
return list.Count > 0;
49+
}
50+
return false;
51+
}
2852

2953
/// <summary>清除数据</summary>
3054
public void Clear()

Assets/MecanimEventSystem/Runtime/EventState.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,10 @@ protected void ConfigEvent(int frame, Action<AnimationEvent> action)
6060
}
6161
else
6262
{
63-
Debug.LogWarning($"AnimatorEventSystem[一般]:指定AnimationClip【{a_Event.animationClip.name}】已经订阅了该事件【{action.Method.Name}】!\n 建议:请勿频繁订阅!");
63+
if (LogLevels.HasFlag(LogLevel.Warning))
64+
{
65+
Debug.LogWarning($"AnimatorEventSystem[一般]:指定AnimationClip【{a_Event.animationClip.name}】已经订阅了该事件【{action.Method.Name}】!\n 建议:请勿频繁订阅!");
66+
}
6467
}
6568
}
6669

0 commit comments

Comments
 (0)