Animancer - Less Animator Controller, More Animator Control

So sorry to keep bothering you, but now it seems my events aren’t triggering :frowning:
The events are on a ControllerState. It’s animating, 100% weight, etc. No events though

controllerState = new ControllerState(animancer.GetLayer(0), controller);
controllerState.Play();

I’m not seeing any issues with animation events triggered by ControllerStates.

What Unity version are you using? I tested in 2018.1.

Go to the Animation Events/Other Events example and make sure it’s working normally.

If it is, make the following changes in the FootstepEvents script:

public AnimancerComponent animancer;
public RuntimeAnimatorController controller;

private void Awake()
{
var state = new ControllerState(animancer, controller);
animancer.Play(state);
}

Then create an Animator Controller, drag in the Humanoid-Walk-Footsteps clip as its default state, and assign those new references in the Inspector.

Let me know if it works like that.

The original example worked, as does the one with changes.

Turns out running state.Play() doesn’t trigger events, but animancer.Play(state) does. Is this on purpose?

I see the problem now.

Layers all start at 0 weight by default.

Calling Play on the AnimancerComponent / AnimancerPlayable / AnimancerLayer when the layer is at 0 weight sets it to 1.

But calling Play on an individual state doesn’t affect anything other than that state so it won’t stop anything else from playing or change the layer weight.

So your state was at 1 weight, but the layer was still at 0. It seems that the internal AnimationLayerMixerPlayable decides to completely ignore the weight when there is only one layer connected but the Animation Event system still checks the weight properly so you see it playing but its events don’t get fired. I’m going to report that as a Unity bug.

1 Like

Great package, i’m pretty impressed with Animancer, though i havent used it for more than an hour …
One thing though i noticed is that events sitting at the very end AFTER the last keyframe do not trigger most of the time ( tested on spriteanims using PlayAnimationsInSequence() on a NamedAnimancerComponent ).
All other events trigger just fine ( at start, and during the whole animclip timespan ).
It’s just the end event that sits after the last keyframe that doesnt fire
So the fact that there’s an event after the last keyframe is worthy of discussion, though i previously had those animations controlled by mecanim, and mecanim fires those events just fine. And i have a lot of anims that are set up this way ( arround 1.5k )
BTW: Same was true for the pre V3.0, but still is true for the recently released V3 version …

Thanks, I’m glad you like it.

That’s an odd issue. I just did a quick test and found such events to work perfectly fine. There shouldn’t be much room for such a bug because Animation Events are handled entirely by the Playables API without any direct contact with Animancer so Mecanim should work exactly the same because it uses Playables as well.

I assume events within the animation timeframe work fine?

Which Unity version are you using?

Have you checked the layer weight in the Inspector in case it’s the same issue @joshcamas just had a few posts ago?

@Kybernetik quick question for ya, how easy to switch between Root Motion ON & OFF? I often want Root Motion ON when attacking, and OFF when walking. Thanks.

1 Like

I don’t use root motion much myself, but it should just be a matter of setting the applyRootMotion property via the AnimancerComponent’s reference to the Animator. I.E. animancer.Animator.applyRootMotion = …

Can you do an example scene about it? It sounds a bit confusing to me. I think it would be useful for others as well. Thanks.

Is there a way to detect when a clip / controllerstate has faded out during a crossfade? (Completely faded out)

EDIT: I guess one way is to check every frame if the weight is at 0

@ikemen_blueD Something like this:

[SerializeField]
private AnimancerComponent _Animancer;

[SerializeField]
private AnimationClip _Walk;

[SerializeField]
private AnimationClip _Attack;

public void Attack()
{
    _Animancer.Play(_Attack);
    _Animancer.Animator.applyRootMotion = true;
}

public void Walk()
{
    _Animancer.Play(_Walk);
    _Animancer.Animator.applyRootMotion = false;
}

Here’s a more complete example which uses a custom serializable so you can specify whether you want root motion alongside each animation in the inspector along the same lines as the Basics/Sequence Coroutine example.

@joshcamas when an animation fades out it gets stopped so you could also check its IsPlaying flag, but yeah, checking something every frame is pretty much the only way to do it.

1 Like

Is there a way to make “container” states? Aka states inside of states?

Mixers could be considered “container” states along the same lines as sub-state machines in an Animator Controller. What are you actually trying to achieve?

I think I might be able to use the mixer.

I’m wanting to build my animator to have a higher up state machine that has 3 states: “base”, “weapon”, and “dead”.

Each state has its own complex logic on what should happen when that state is entered. And I feel like having them in a container of sorts makes things a lot more modular - especially since different states may have different layers and stuff.

In other words, imagine each state being a ControllerState. But instead of a controller asset, its a… controller built from animancer.

1 Like

That sounds like you need a separate state machine system like the one demonstrated in the State Machines examples. “Dead” is just an animation, but “Weapon” isn’t an animation, it’s a complex state (or group of states) in your state machine system which involves several animations. So there isn’t really any reason for the animation system to know about the “Weapon” group, only about the specific animations that actually need to be played.

Yeah, that’s pretty much what Mixers are, though all the included ones are geared towards acting like Blend Trees except for ManualMixerState which just lets you control all its children manually. If you do want to take that approach, it should have pretty much everything you need except for Play and CrossFade methods (because all other mixers inherit from manual and it doesn’t really make sense to have those methods in any of the others). You could easily create your own subclass and add the methods you need though (you could probably just copy them straight from AnimancerLayer).

This is one of those secret gems on the store that just makes life easier. Top work, @Kybernetik

3 Likes

I just reread your post and saw this. PlayAnimationsInSequence will stop each animation when it reaches the end to play the next animation, so any events after the last keyframe will not trigger unless the last frame that was rendered had enough delta time to jump the animation past both the end and the event in question in one go. So I would expect that to sometimes trigger events that are right after the end and sometimes not.

1 Like

Does this system get along well with an already-working animator controller? For example, some other store asset has a big hairy machine graph that’s 99% working the way I want it, but they forgot to insert a few little things like reach-for-doorknob actions. I could try to figure out how to use Unity’s PITA machine editor, or I could just play a separate animation on my own with code and then let it resume control.

I haven’t done it much myself, but that sort of thing can be achieved with ControllerStates.

There aren’t currently example scenes that show exactly what you’re looking for, but the Locomotion/Linear Blending example shows how to play a controller containing a Blend Tree and it should be pretty easy to see how to play separate animations as well like any of the other examples. Feel free to ask if there’s anything you can’t figure out.

I’m planning on making a new example scene to show how to use controllers like that (and a few others) once I’m done with Inspector Gadgets v6.0 . I don’t have a solid release date planned yet, but I expect it to fall within 1 to 2 months.

2 Likes

Thanks for keeping this up-to-date …
your analysis sounds plausible , will keep posting new findings as soon i’m back dealing with animation stuff again