|
|
Model Engine 4 adds a new animation system that, to put it simply, is a direct upgrade from the previous Priority
|
|
|
System. Hence, it was given a clunky yet precise name: **Priority State-Machine Animation System**.
|
|
|
|
|
|
Although the old system is still usable, we highly recommend switching over to using this new system as it can do
|
|
|
everything the old system does but better and more flexible!
|
|
|
|
|
|
This bakes the question: What was wrong with the old system? A lot, apparently.
|
|
|
|
|
|
## The Problem
|
|
|
|
|
|
Let's do a recap on the old system.
|
|
|
|
|
|
The Priority System relies on 2 very important (but wrong) assumptions:
|
|
|
|
|
|
* That each animation has a distinct priority and will never change
|
|
|
* That interpolating between two animations equates to fading in and out the animations, and adding them together
|
|
|
|
|
|
These assumptions are obviously very wrong. While the first point can be worked around, the second point affects
|
|
|
animation freedom severely, especially on interpolating rotations between two animations. Whenever you see weird
|
|
|
interpolation bugs happening when a model switches between `IDLE` and `WALK` state, that is the doing of the second
|
|
|
assumption.
|
|
|
|
|
|
To understand this problem a little bit better (for academic reasons,) here is a very simple example. If you don't care
|
|
|
about it, first why are you here ?_?, second you can skip to the next part.
|
|
|
|
|
|
Let's say we have a model with an `idle` and `walk` animation, and let's compress the animations down to interpolating
|
|
|
between two values.
|
|
|
|
|
|
| Animation | Value |
|
|
|
|-----------|:-----:|
|
|
|
| default | 1 |
|
|
|
| idle | 0 |
|
|
|
| walk | 0 |
|
|
|
|
|
|
Let's visualize `idle` trying to interpolate into `walk`. Since both animations have the same value `0`, logically
|
|
|
speaking, the value would remain at 0. However, because we assumed that all animations have a defined priority, `walk`
|
|
|
is technically higher priority than `idle`. Furthermore, we also assumed that interpolation is just adding two faded
|
|
|
values, our formula becomes: `lerp(idle, default, progress) + lerp(default, walk, progress)`. Substituting `progress`
|
|
|
with `0.5`, we get `lerp(0, 1, 0.5) + lerp(1, 0, 0.5)`, or `0.5 + 0.5 = 1`. Our interpolation somehow reached `1`.
|
|
|
|
|
|
The astute among you will realize that the culprit comes from the default model value being `1`, because if we set
|
|
|
default to `0` while the two animations to `1`, the formula works out. In fact, the formula functions properly as long
|
|
|
as the default value is `0`. This explains why simple models seldom encounter this, while more complex models that
|
|
|
requires default rotations suffers
|
|
|
greatly.
|
|
|
|
|
|
## The Solution
|
|
|
|
|
|
Don't give animations a priority.
|
|
|
|
|
|
Yep, that's it. At least we are not using animation priorities for interpolations. The new system uses state-machines to
|
|
|
ensure that only one animation is playing at a time, and interpolate animations directly from each other instead of
|
|
|
doing through the default pose first.
|
|
|
|
|
|
However, since the state-machine can only play one animation, this means that animation overlapping is no longer
|
|
|
available: a trait that the priority system allows. This is where we merge the two ideas into one.
|
|
|
|
|
|
Instead of one state-machine per model, each model can have an infinite amount of state-machines, all still limited to
|
|
|
playing only one animation. We then assign priorities to these state-machines, so that the final result of the animation
|
|
|
is computed with the values calculated by the state-machines.
|
|
|
|
|
|
## Conclusion
|
|
|
|
|
|
~~I am a fucking genius.~~
|
|
|
To be fair it took me this long to figure this out, I'm ashamed of thinking the old system is a good idea. But it's
|
|
|
fixed now so woohoo! |
|
|
\ No newline at end of file |