Playing animator animations on TOP of timeline animations

Is there a way to set timeline animations to play on a certain layer of the animator controller? This way, I can play other animations in a layer on TOP of the timeline. Alternatively, is there a way to set the weight of the timeline animations programmatically, independently of the data that exists in the timeline itself? (ie. not just using the ease in and out on the animation track).

So my actual use case:
1. I'm having a number of characters animate as multiple tracks on a single timeline.
2. The player is in control of the progress of the playhead. Essentially the playhead only progresses on user input.
3. When the player stops moving the playhead, I want to blend idle animations in on the characters that play on TOP of the timeline animation (which at this point would just be a frozen frame, as the playhead isn't moving).

Thanks! :)

Haven't tried it but you might be able to use an override track in timeline and put an Avatar Mask to it. Ofc, add nothing to the normal track as it would override the Base Layer.

EDIT: tried it. No dice.

If there's no better way, I'd probably try a custom Playable track which mimics the AnimationTrack.

Links that can help:
https://docs.unity3d.com/Manual/Playables-Examples.html (Check Blend an Animator Clip with an Animator Controller)
and the https://github.com/UnityAssetPackages/DefaultPlayables whose wizard can help you generate some of the boilerplate for the track and the clips etc. Although you might want to set the track to use AnimationClips instead of custom type clips.
As a way to debug you can use the GraphVisualizer(you might need to search a bit to find it, for some reason Unity has removed it from PackageManager in recent versions). It will show you how things are blending.
Also you'll need some info on https://docs.unity3d.com/ScriptReference/Animations.AnimationLayerMixerPlayable.html as it's what Animator uses to blend between Layers.

Disclaimer: it might be more involved than I might think. I've created a similar thing as a Monobehaviour and it's rather easy using the Playables Examples.

UPDATE2: Scratch that, the first solution with the mask on the track works fine, but only when you use Generic rigs. It doesn't work with Humanoids. You need an Override track with the clip you want to "layer" over it, but it basically overrides the animation of anything the Avatar Mask you set on the track allows. Additive blending hasn't been added yet on Animation Tracks.

7577791--938935--upload_2021-10-16_21-15-58.png

You can see the animator controller on the bot only runs a looping idle animation, while the override track in timeline has the guitar playing animation (which uses the whole body, check mixamo) and if you see closely, the mask icon is on. I've set the mask to override the transforms from shoulders to fingers.

2 Likes

Thanks a lot npatch! :smile: That's awesome!

Sadly our animation setup for all our characters is on Humanoid, which I guess means this won't work? :(

If you like a challenge.... maybe you could build your own custom track implementation. If you don't need multiple override layers (just a single simple animation clip), I assume you could read out of the animation clip yourself, programmatically merge in any changes you want to make (e.g. idle animation), then feed that into the animator component.

https://github.com/gpsnmeajp/EasyVirtualMotionCaptureForUnity might have useful snippets of code. It reads VMC wire protocol then updates an animator object. There are probably other code samples around too...?

BUT! As soon as you want to pause the timeline but have an idle animation playing, it feels like you need to control things pretty closely. I mean if the timeline stops playing it wont be generating frame updates, right? But you still want your idle animation clip in effect.

Another idea (no idea if feasible!), could you add your own component that reads an idle animation clip, reads the current animator values (if possible!!), then adds deltas to the animator values? I was hoping LateUpdate() or similar could be used. I was looking at "Animation update loop"
https://docs.unity3d.com/Manual/ExecutionOrder.html#AnimationUpdateLoop - but I think that is mechanim stuff, not Timeline (all the talk of state machine transitions). But no idea if it would work sorry.

But the fact that EVMC4U and EasyMotionRecorder exist gives me hope that APIs are available to read and write animation properties.

You could also look into hooking on PlayableDirector events for pause/play and programmatically connect/disconnect an idle clip playable on the AnimatorController for each character. If memory serves there's no additive blending yet within Timeline so using override layers won't work, but you could work with the AnimatorController who has such a thing. Perhaps you could use OverrideAnimatorControllers with the idle you want which ignore any other stuff and somehow connect a playable to it dynamically which will sample the pose from timeline and try to mix it in with the rest. Since you're using Humanoid, there's this (https://docs.unity3d.com/ScriptReference/HumanPoseHandler.html) which might be helpful.
At any rate, mostly custom solutions will work for you.

1 Like

Awesome! Thanks a lot! Looks like I do need to make a custom track type and then dig more into the playables system :)

1 Like