Answered

Animate by blending between keyframes

iv2b 5 years ago updated 5 years ago 5

Hi, i've been trying to mimic overgrowth's approach to animations in unity (you can find the explanation here) and i was wondering if uMotion could help me in achieving that.

In short what this method involves is having very few keyframes and interpolating between them using curves, which is perfect for prototyping. For example a walk loop can be done with only 2 frames.

At first i got this done by splitting keyframes into animations (thus animations with only 1 frame), putting them in a blend tree and switching between them using a script. This however has a few issues: the mecanim graph becomes exceedingly complex over time, i need a script to handle the animations and animation speed is ignored (as the script sets in which point of the animation i'm at every frame).

Using transitions isn't a good solution either since it only provides linear interpolation.

So the only solutions i'm left with are baking keyframes into an animation and dealing with the playables API.

The former method would be handier as it'd allow for quicker development by letting the animator see the changes very quickly when making changes, plus having the final output be contained in an animation file means it's possible to make it work with mecanim as well.

The issue is that each property has its own curve, both in uMotion and in unity's own animator window, meaning that in order to do an "ease in" curve (as an example) i'd need to change the right tangent of every property for the specified node, which for a humanoid character can easily mean changing 50+ curves, while more complex curves would be essentially impossible.

As for using playables, clips do support ease in and ease out curves which can be used alongside single frame animations to get the desired result, but i'm still clueless as to how that would work when putting everything together (such as using them in blend trees for example) and i've yet to see examples of characters controlled via playables that don't involve janky scripts.

The ideal solution would be to have a single interpolation curve within uMotion itself. In a new or imported animation it'd just be a line going from 0 (start of the animation) to 1(end of the animation). It might be better/worse to have a curve for each keyframe.

Or alternatively a "speed" curve that in a new or imported animation would sit at a value of 1, allowing for a very similar effect but in a way that is probably easier to execute (as it'd be a matter of changing how long each frame lasts based on the curve).

In both these cases it'd be possible to quickly create more natural animations (for example making a decent looking jump animation becomes trivial with this approach) while possibly leading to a fully finished animation (overgrowth's character animator uses less than 20 keyframes!) just by refining it.

Is this already possible with uMotion in some way?

If not, would you consider adding this feature? And do you know how i could tackle this animation approach (either through playables or with other software that has the feature i'm looking for)?

Thank you in advance! :)

UMotion Version:
1.19p02 pro
Unity Version:
2019.2.2f1

Answer

Answer
Answered

Hi,

thank you very much for your support request.

Personally, I would go for a custom script based solution. You could use ScriptableObjects to store structs with the single key frame poses (use one quaternion per bone/transform). Another ScriptableObject could define the blending behavior using a simple AnimationCurve. And then a simple script that applied the poses to the character (iterate through the transforms and apply the blended quaternions). I think that's also the way the overgrowth developer used (if I remember correctly he used his own engine).

You can convert existing *.anim files to your custom ScriptableObject's by getting the animation keys of the *.anim with the appropriate API method: https://docs.unity3d.com/ScriptReference/AnimationUtility.GetCurveBindings.html

If you want to use this to animate a lot of characters at the same time, use the job system / ECS to max out performance.

Best regards,
Peter

Answer
Answered

Hi,

thank you very much for your support request.

Personally, I would go for a custom script based solution. You could use ScriptableObjects to store structs with the single key frame poses (use one quaternion per bone/transform). Another ScriptableObject could define the blending behavior using a simple AnimationCurve. And then a simple script that applied the poses to the character (iterate through the transforms and apply the blended quaternions). I think that's also the way the overgrowth developer used (if I remember correctly he used his own engine).

You can convert existing *.anim files to your custom ScriptableObject's by getting the animation keys of the *.anim with the appropriate API method: https://docs.unity3d.com/ScriptReference/AnimationUtility.GetCurveBindings.html

If you want to use this to animate a lot of characters at the same time, use the job system / ECS to max out performance.

Best regards,
Peter

The issue with that approach is that i'm losing all of mecanim's features. I could put all 1-frame animations inside a huge blend tree and that'd be just the same in terms of workflow (if not faster).

Putting all keyframes and their curve inside a single animation file allows me to make full use of mecanim's features and blend both animation styles (for example if i need a regular animation that i can't split into a few keyframes it'd be very tedious to use alongside a custom solution) as needed.

I did achieve a similar effect by playing the animation using my initial script, recording the animation with unity's recorder script and then converting the animation from generic to humanoid using the animation converter tool. However that remains a slow way to tackle this approach (i need to first create the keyframes without being able to see the final animation, then after adjusting the curve i need to record it, convert the animation and finally cut it to match the original).

If some other software allowed me to tweak the animation speed with a curve then it'd at least be faster, but not nearly as much as having that feature built-in (plus i haven't found such software yet).

I'm not sure how difficult it would be to add the feature of controlling the animation speed via a curve (which isn't the same as lerping through keyframes but close enough) or to alter all curves in a frame based on a value (so that the value of each property is multiplied by the value of the curve, this would be ideal as it allows extrapolating, much like the crouching animation in overgrowth at 7:58. I think this might be an easier implementation too), however it'd allow for quick animation prototyping (animators, at least as far as i know, like to keyframe animations and fill in the gaps until it's refined, this feature would them to quickly add an unfinished animation while making it much closer to the finished product, which is impossible when using a custom solution), overgrowth-like animations while still fully benefitting from mecanim and timeline and it allows to fine-tune timing issues in traditional animations with ease (often times moving the keyframes around isn't a perfect solution, this would go hand-in-hand with the features shown in the first video of the asset's page too).

If the feature would be a huge undertaking then i'll keep looking for a better solution, otherwise i'd strongly consider implementing it as it'd provide a wide slew of benefits in a fairly elegant way.

Thank you for your time.

You could still combine the scripted approach with mecanim if you run your scripts in late update. Late update runs after the animator, so the character already has the mecanim defined pose. You can then calculate your scripted pose and blend between them and/or overwrite only a few bones (e.g. only the hips and legs) similar to the "avatar mask feature of the animator".

Unfortunately I currently don't have plans to add a "control everything with one curve" feature to UMotion as it would mean quite a big re-design of some core implementations. I'm sorry.

Best regards,
Peter

If i do that i'll need to run the script on multiple animations at once (if i'm blending between two animations i need to apply different curves to each one) which can get convoluted, plus i can't look at the animation progress to sample the curve (i've been sampling the curve using a float i loop through 0-1, if i were to sample the animation progress that'd produce unwanted results, potentially even causing an endless loop), plus i'd incur in a loss of performance (as i'm running scripts on top instead of just letting mecanim play the animation).

I was hoping multiplying all keyed values by sampling a curve would've been a less drastic undertaking, but i completely understand if that's the case.

Given i've been unable to find a different animation tool with this feature i think i'll attempt to edit the animation file directly, hopefully editing the values of all keys every frame won't be too hard. It's still an imperfect solution as it doesn't let me change the timing on the keyframes but that can be done via umotion itself. Not ideal but at least i won't need additional scripts and unlike the previous recorder approach i will be able to extrapolate poses.

Once again, thank you for your time. :)

Please check out Animation Rigging and Animation C# Jobs, it is a package released by unity that uses the job system to in a highly performant way runtime rig a character. There is also non runtime rigging now as well. Using that you should be able to achieve all the procedural animation you want. On one of the forums someone achieved the overgrowth approach with it.