-
Notifications
You must be signed in to change notification settings - Fork 2
/
AnimatorStateBinding.cs
128 lines (125 loc) · 4.18 KB
/
AnimatorStateBinding.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
using UnityEngine;
using System.Collections;
namespace MecanimEffects {
/// <summary>
/// Animator state binding connects chosen animator state to an effects list.
/// </summary>
[System.Serializable]
public sealed class AnimatorStateBinding {
/// <summary>
/// Occurs when animator enters the state bound.
/// </summary>
public event EventHandler<AnimatorStateBinding, LayerInfo> OnEnter;
/// <summary>
/// Occurs every frame while the animatior remains in the state bound.
/// </summary>
public event EventHandler<AnimatorStateBinding, LayerInfo> OnUpdate;
/// <summary>
/// Occurs when timer reached it's value while animator remains in the state bound.
/// </summary>
public event EventHandler<AnimatorStateBinding, LayerInfo> OnTimer;
/// <summary>
/// Occurs when animator exits the state bound.
/// </summary>
public event EventHandler<AnimatorStateBinding, LayerInfo> OnExit;
/// <summary>
/// The name of the state (readonly).
/// </summary>
public string stateName;
/// <summary>
/// The name for the message sent in the first frame of the bound state (readonly).
/// </summary>
public string enterMessage;
/// <summary>
/// The name for the message sent in the frame following the last frame of the bound state (readonly).
/// </summary>
public string exitMessage;
/// <summary>
/// The name for the message sent every frame of the bound state (readonly).
/// </summary>
public string updateMessage;
/// <summary>
/// The name of the message set when timer reached each one of treshold's values (readonly).
/// </summary>
public string timerMessage;
/// <summary>
/// The timer tresholds (readonly).
/// </summary>
public float timerTreshold;
/// <summary>
/// The effects what should be played along with this state (readonly).
/// </summary>
public AnimatorEffect[] effects;
/// <summary>
/// When last timer was started.
/// </summary>
private float timestamp;
/// <summary>
/// Reset this instance to default state.
/// </summary>
public void Reset() {
System.Array.ForEach(effects, effect => effect.Reset());
timestamp = .0f;
}
/// <summary>
/// Plays all effects, bound to the animator's state.
/// </summary>
public void Enter(LayerInfo li) {
li.controller.Trace("AnimatorStateBinding.Enter: {0}", stateName);
if(OnEnter != null) {
OnEnter(this, li);
}
if(!string.IsNullOrEmpty(enterMessage)) {
li.controller.gameObject.SendMessage(enterMessage, li, SendMessageOptions.RequireReceiver);
}
foreach(var effect in effects) {
effect.Play(li);
}
if(timerTreshold != .0f && !string.IsNullOrEmpty(timerMessage)) {
li.controller.StartCoroutine(TimerCoroutine(li));
}
}
/// <summary>
/// Checks and sends update and timer messages when needed.
/// </summary>
public void Update(LayerInfo li) {
li.controller.Trace("AnimatorStateBinding.Update: {0}", stateName);
if(OnUpdate != null) {
OnUpdate(this, li);
}
if(!string.IsNullOrEmpty(updateMessage)) {
li.controller.gameObject.SendMessage(updateMessage, li, SendMessageOptions.RequireReceiver);
}
}
/// <summary>
/// Stops all effects, bound to the animator's state.
/// </summary>
public void Exit(LayerInfo li) {
li.controller.Trace("AnimatorStateBinding.Exit: {0}", stateName);
if(OnExit != null) {
OnExit(this, li);
}
if(!string.IsNullOrEmpty(exitMessage)) {
li.controller.gameObject.SendMessage(exitMessage, li, SendMessageOptions.RequireReceiver);
}
foreach(var effect in effects) {
effect.Stop(li);
}
}
/// <summary>
/// Sends a timer message if state still active after the timer treshold.
/// </summary>
private IEnumerator TimerCoroutine(LayerInfo li) {
var timestamp = this.timestamp = Time.time;
yield return new WaitForSeconds(timerTreshold);
// execution of coroutine will be continued here after some time
if(timestamp != this.timestamp) yield return null;
if(!li.state.IsName(stateName)) yield return null;
li.controller.Trace("AnimatorStateBinding.Timer: {0}", stateName);
if(OnTimer != null) {
OnTimer(this, li);
}
li.controller.gameObject.SendMessage(timerMessage, li, SendMessageOptions.RequireReceiver);
}
}
}