Ideas for new animation system

Hi

I wanted to discuss about new and better animation system that I hope to implement into Armory3D. The limitations of the current animation system is listed here on GitHub.

I looked around a bit on how other game engines(Unity, Unreal, Godot, etc…) do these animations and came to a conclusion that Godot had a relatively simple yet robust animation system. And, to take inspiration from these systems.

Just for reference, here is a YouTube tutorial of making a TPS controller.

For starters, Godot has 3 different types of animation nodes:

  1. Animation getter nodes. These get the required animations

  2. Blend nodes: These simply blend 2 or 3 animations together.

  3. Transition nodes. These help animation to smoothly switch from one animation tree to another.

The animation tree is a group of nodes that contain animation getters and blend nodes.

Here, to keep things simple, I will be focusing only on 3 different nodes, and how to implement them.

get action Node, Blend Node, transition Node: The objective here is to first get such an animation system working:

So any ideas on how we could implement something like this?

Best,
QC

5 Likes

Nice to see you interest on this! :slight_smile:

Godot way doesn’t look too much simple from my view, but i wouldn’t doubt you were able to reproduce it.

I think we all can plan a better and more user friendly way. At least Godot “logic nodes” are known for being harder than code properly, i wouldn’t expect different from its animation nodes.

So any ideas on how we could implement something like this?

Did you mean the nodes?

I guess the biggest trouble (or only) is to blend more than two animations, and my newbie idea on this is to keep blending between two animations per node / function (like it is already on the image you send), so consider this:

You connect two animations in a node that will lerp them (like a fac input we have in shader nodes). No mask is required here afaik (only for performance polishing or refined control purpose).

Them we got a node setup like this:

Action 1 -> Factor -> Action 2 -> Outputs Action 3

Action 3 is the result of mixing the two previous animations and it can mixed with many other animations infinitely… So consider with proper animations now:

Run forward -> 0.5 -> Run right -> Outputs Run diagonally right

This is simple in user view, but maybe for performance may be more complex

My reason to ignore the mask in the previous steps is because this blending of animation would not affect the armature at all, nor the previous animations, because each node can have a single animation stored to it (but the calculations are in all bones this way, so mask is good for performance).

More important than mask is priority in final result. E.g. of use:

You play some walking unarmed animation, them you just want to change the arms position, so just need to animate the arms and let the other bones untouched. So you would just play the armed arms animation with higher priority. Also here have space for more future optimizations (not updating bones that will be overriden later).

BGE animation system functionality in logic bricks is nice and simple to understand, but limited because of logic bricks. Maybe would be better to reproduce something like that but with improvements where necessary.

I was looking into Hierarchical FSM some days ago. It is a state machine where the states are other state machines. It would be a handy way to deal with the complex animations. For example, you can set a FSM to be the legs and torso animations and leave a sub fsm that will control the states of the arms, and another fsm inside the later to control the fingers… (thinking better for mutants could be more useful)

Edit: i will try to implement HFSM over that later, because im still illiterate in Uis and even more in python. But i never see no one doing a FSM in Blender, so maybe it couldn’t be possible at all. Maybe a new instance like Ui editor would be easier to do.

2 Likes

This sounds very cool! I like the transition node that (if I understand it correctly) allows you to seemlessly change between animation states like running or climbing for example, right?

My two cents on this:

If realized like proposed above, I wonder if animation trees should be part of a regular logic tree or even have their own editor. This would mean some more work and the current logic node code would benefit from another layer of abstraction above that both tree systems use, but overall it could be a bit cleaner and recycling trees would be easier. On the other hand using the logic trees is much simpler and maybe there are even good ways to combine the animation nodes with logic nodes (that’s probably the better approach).

How should something like this work in detail? Lerping would mean that we have a factor t with which we would calculate the following: Action3 = Action1 * (1 - t) + Action2 * t. This however means that the factor node would need to change both the influence of action 1 and action 2, so for me the design with the factor node in between looks a bit unusual. Maybe I’m just not understanding it correctly.

A priority system sounds really helpful indeed!

2 Likes

How should something like this work in detail? Lerping would mean that we have a factor t with which we would calculate the following: Action3 = Action1 * (1 - t) + Action2 * t . This however means that the factor node would need to change both the influence of action 1 and action 2, so for me the design with the factor node in between looks a bit unusual. Maybe I’m just not understanding it correctly.

Idk exactly. For me the blend input is the same as the factor input we see in shader/mix vector nodes (both are lerp). I got confused because of the transition node in the image. Should not just play the action that was blended?

Currently if we blend an action, it is applied instantly, so we don’t have any control over that and no transition at all. Take this image as example:

The final output there is just another animation that can be played. The Play node just have a input to be executed and a blend time (i will not drawn anymore because you had see how is my skill for it :frowning_face: )

A transition node should be pointless as we can just care about playing the desired animation and specify the blend time, because the blending would happen taking the current animation. But these are just ideas i don’t really know what im talking.

  • The animations blending can be updated just when the respective factor changes, so it is better for performance. And the factor input name is just to stay blender like, it can be named as blend, lerp, etc.

On the other hand using the logic trees is much simpler and maybe there are even good ways to combine the animation nodes with logic nodes (that’s probably the better approach).

I agree with that, we should stay with the logic nodes for while. But after all this time i prefer to get out Blender the most possible to avoid unexpected crashes. I think krom is more stable and lightweight but i may be wrong, but if we do something in Krom, it need to allow for implement FSM to be more reasonable.

These are just ideas so i can feel im helping in anything, you all are the captain of the ship :slight_smile:

1 Like

Thank you for all the insights. Really appreciate it.

Absolutely, That is the goal of this discussion.

Yes, this is also my idea. To have no limit on blending of animations. That is, the 3 nodes that I used can be used in any order and in any number, since they all take in 2 Action inputs and output one Action.

I did not completely get the point here. But, the reason why I wanted to have bone masking is for the cases when you want to blend only certain animation transforms while keeping the rest the same.

For example blending a run animation with gun holding animation. While this can be achieved with simply having only legs animated in one animation and only hands in the other, bone masking is still a nice option to have.

Also, bone masking isn’t that difficult to implement.

That is very cool. But for right now, we could keep the discussion to a bit low level. That is just blending animations and playing them. Switching to other animation trees could come later.

Yes, it allows for switching between two animation trees. For context, it is the simplest form of animation state machine. Just switches animation tree from one to other on input and starts the new animation tree from time t = 0

I too think this is a better approach. This also makes new users understanding nodes a bit easier, rather than to lean a new UI altogether.

I agree that a priority system sounds good, but I don’t think its a substitute for a mask system. Since in a mask system, even if all of the bones are animated, you have to option to choose a particular set of bones for blending.

Whereas, if you only had a priority system, you might have to create a copy of the original animation track and then remove all the unwanted bones.

I believe the image I put up gave some wrong ideas. To make it clear, you can use any number of blend nodes and in any combination. A transition node is optional but can be used any number of times and anywhere in the node tree.

Yes, this is a good idea. The reason I say we need a transition node is to primarily reduce the number of nodes used in each of this animation node trees.

Consider this. We have a walk-run blending on one side. On the other side, we have a walk-crouch blending. And both of these must be then blended with a weapon holding animation, which would be same for both walk-run and walk-crouch.

This can be realized like so:

Looks good enough for me :wink:

Finally, the objective here is we have 3 nodes: Get Action, Blend, and Transition. These nodes can be used in any order and in any number. In the end, we get only one animation to be played.

Say we have a function for each of these nodes like so,

 1. getAction(action: String): Action
 2. blend(Action1: Action, Action2: Action, Factor: Float, mask: Int): Action
 3. transition(Action1: Action, Action2: Action, transitionTime: Float): Action

Is what I just stated realizable? If not, what arguments should we change so that we could realize such a system?

Please share your thoughts.

3 Likes

Looks good enough for me

That was kind of your part!

I don’t understood very much the transition part and how mask can be (or not) used as some kind of priority, but i will wait to see it later…

Is what I just stated realizable? If not, what arguments should we change so that we could realize such a system?

I don’t see any reason why not. This API looks clean and complete.

I’m excited for this and looking forward, but i will hide it to don’t be a shame :slight_smile:

I just can hope you get motivated and get the time needed for that!

2 Likes

Looks good! The only thing that confuses me a bit is that the blend and transition methods return an Action object. What does that object contain? Is it the same as an animation or a new type consisting only of the necessary data for blending? I don’t know much about the animation system, but those two methods should probably work on the pure data to not have unnecessary allocations for some intermediate objects.

Regarding the terminology: blend and transition sound pretty similar and their function might not be obvious if there is no accompanying documentation. Maybe there are more verbose names for transitions, but I can’t think of any right now.

2 Likes

Thanks!

The return type in the get animation node is an interpolated bone transform of the armature. This contains transforms of all the bones in an animation track at a particular point in time. So an array of Mat4 Objects, each Mat4 for a bone.

This the same for Transition and Blend nodes. They take in two arrays of Mat4 and return one array of Mat4.

All the code for Transition, Blend and Get Animation will be in iron. Just called form logic node. I could also try to in-line.

Now that you mention it, I also think so. How about “switch animation” ?
Will have a look at some other alternatives. If you could come up with any in the meantime, please do suggest.

3 Likes

Sounds good, switchState or changeState/setState could work as well. “Animation” might be clearer than “state”.

3 Likes