forked from kimsama/UnityToolbag
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathTimeScaleIndependentAnimation.cs
143 lines (124 loc) · 4.7 KB
/
TimeScaleIndependentAnimation.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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/*
* Code in this file based on code provided by Asteroid Base in their blog:
* http://www.asteroidbase.com/devlog/9-pausing-without-pausing/
*/
using UnityEngine;
using System;
namespace UnityToolbag
{
/// <summary>
/// A component that can be attached to an object with an Animation to update it using real-time,
/// to allow it to continue updating when Time.timeScale is set to 0.
/// </summary>
[AddComponentMenu("UnityToolbag/Time Scale Independent Animation")]
public class TimeScaleIndependentAnimation : TimeScaleIndependentUpdate
{
// Cache the animation so we can minimize calls to GetComponent which happen
// implicitly each time you call the MonoBehaviour.animation property.
private Animation _animation;
private AnimationState _currentState;
private Action _callback0;
private Action<TimeScaleIndependentAnimation> _callback1;
private float _elapsedTime;
private bool _isPlaying;
[SerializeField]
private bool _playOnStart;
[SerializeField]
private string _playOnStartStateName;
void Start()
{
if (_playOnStart) {
Play(_playOnStartStateName);
}
}
protected override void Update()
{
// Always update the base first when subclassing TimeScaleIndependentUpdate
base.Update();
if (_isPlaying) {
// If for some reason the state goes away (maybe the animation is destroyed), log a warning and stop playing.
if (!_currentState) {
Debug.LogWarning("Animation is playing but the AnimationState isn't valid.", this);
Stop();
return;
}
_elapsedTime += deltaTime;
_currentState.normalizedTime = _elapsedTime / _currentState.length;
if (_elapsedTime >= _currentState.length) {
_isPlaying = false;
if (_currentState.wrapMode == WrapMode.Loop) {
Play(_currentState.name);
}
else if (_callback0 != null) {
_callback0();
}
else if (_callback1 != null) {
_callback1(this);
}
}
}
}
/// <summary>
/// Plays a given animation.
/// </summary>
/// <param name="name">The name of the animation to play.</param>
public void Play(string name)
{
// Validate that we have an animation
if (!_animation) {
_animation = GetComponent<Animation>();
if (!_animation) {
Debug.LogWarning("No valid animation attached to object.", this);
return;
}
}
// Get and validate the animation state
var state = GetComponent<Animation>()[name];
if (!state) {
Debug.LogWarning(string.Format("No animation state named '{0}' found.", name), this);
return;
}
_elapsedTime = 0f;
_currentState = state;
_currentState.normalizedTime = 0;
_currentState.enabled = true;
_currentState.weight = 1;
_isPlaying = true;
_callback0 = null;
_callback1 = null;
}
/// <summary>
/// Plays a given animation with an action to invoke when the animation completes.
/// </summary>
/// <param name="name">The name of the animation to play.</param>
/// <param name="callback">The action to invoke when the animation completes.</param>
public void Play(string name, Action callback)
{
Play(name);
_callback0 = callback;
_callback1 = null;
}
/// <summary>
/// Plays a given animation with an action to invoke when the animation completes.
/// </summary>
/// <param name="name">The name of the animation to play.</param>
/// <param name="callback">The action to invoke when the animation completes.</param>
public void Play(string name, Action<TimeScaleIndependentAnimation> callback)
{
Play(name);
_callback0 = null;
_callback1 = callback;
}
/// <summary>
/// Stops playback of the animation.
/// </summary>
public void Stop()
{
_elapsedTime = 0f;
_currentState = null;
_callback0 = null;
_callback1 = null;
_isPlaying = false;
}
}
}