General Animator
The animation methods introduced in this section are based on MilInstantAnimator
, also referred to as the general animator.
This subsection will go over additional mechanisms of the general animator. Unless otherwise noted with an “*”, the methods mentioned below follow a fluent interface design, meaning the method itself returns a MilInstantAnimator
.
For example, methods like Then
, ThenOneByOne
, and And
mentioned in the previous sections are part of the fluent interface. This means you can freely chain method calls on a MilInstantAnimator
instance, like so:
MAni.Make(
...
).MethodA(...)
.MethodB(...)
.MethodC(
...
).Play();
Lifecycle
By default, the general animator will automatically stop playback when the current scene is unloaded, preventing animation operations from continuing on destroyed objects.
If you want the animator to persist through scene changes—for example, when animating an object marked with DontDestroyOnLoad
—you can call:
DontStopOnLoad()
Playback Control
Enable looping for the animator:
EnableLooping()
Pause the animator*:
Pause()
Stop the animator*:
Stop()
Stop the animator and revert changes it applied*:
Reset()
Time Source
By default, the general animator uses UnscaledTime
to update animations, which means it is not affected by Time.timeScale
.
If you want it to be affected by timeScale
, use:
SetTimeSource(TimeSource.ScaledTime);
Reset Mode
When the animation starts from the beginning, the general animator will automatically call Reset()
. The extent of reverting applied changes depends on the “Reset Mode”.
There are two reset modes:
-
ResetToOriginalState
(default)This mode restores the properties modified by the animator to the state recorded at the start of playback.
-
ResetToInitialState
This mode restores the properties modified by the animator to the state defined by the animations at timestamp 0s.
You can set the reset mode using:
UsingResetMode(AnimationResetMode.ResetToInitialState);
-
Animations without a start value will always reset using
ResetToOriginalState
, regardless of theResetToInitialState
setting. -
Animations with blending mode
Additive
will always reset usingResetToOriginalState
, regardless of theResetToInitialState
setting. -
Since the
Play()
method submits animation tasks to the animator and they begin in the next frame, a situation may occur where a Canvas appears before animations apply, briefly showing its raw state. To avoid this, you can:- Use
PlayImmidiate()
to apply animations in the current frame. - Use
ResetToInitialState
as the reset mode. While the animation still starts on the next frame, the reset takes effect immediately, transitioning the state to the 0s animation target to avoid a visual glitch.
- Use
Reusing Animators with No Start Value
As explained in the reset mode section, if you reuse an animator that contains animations without a start value, it will reset the object's properties to the state before the animation started—likely not the intended result.
In this case, you should explicitly pass revertToChanges
as false
when calling Play
to prevent resetting changes made by such animations:
Play(null, false);
Delay the Previous Animation Group
Besides Then
, ThenOneByOne
, and And
, there is one more method for describing animation flow: Delayed
.
It delays the immediate preceding animation group by the specified number of seconds. For example:
MAni.Make(
1f / ballSpriteRender.MQuad(x => x.color, Color.clear, Color.white),
1f / music.MQuad(x => x.volume, 0f, 1f)
).Then(
2f / ballTransform.MQuad(x => x.position, Vector3.zero, Vector3.one * 3f),
1f + 0.5f / ballTransform.MQuad(x => x.localScale, Vector3.one, Vector3.one * 2f)
).Delayed(1f)
.ThenOneByOne(
1f / camera.MQuad(x => x.fieldOfView, 6f, 4.5f),
1f / camera.MQuad(x => x.localEulerAngles, Vector3.zero, new Vector3(0, 0, 20f))
).Play();
is equivalent to:
MAni.Make(
1f / ballSpriteRender.MQuad(x => x.color, Color.clear, Color.white),
1f / music.MQuad(x => x.volume, 0f, 1f)
).Then(
// Note the offset changes for this group
1f + 2f / ballTransform.MQuad(x => x.position, Vector3.zero, Vector3.one * 3f),
2f + 0.5f / ballTransform.MQuad(x => x.localScale, Vector3.one, Vector3.one * 2f)
).ThenOneByOne(
1f / camera.MQuad(x => x.fieldOfView, 6f, 4.5f),
1f / camera.MQuad(x => x.localEulerAngles, Vector3.zero, new Vector3(0, 0, 20f))
).Play();