Get layer of AnimationClip / improve Unity pls

Hi,

I am currently trying to mix animations on my character/mobs, have the lower body do one thing, upper body another and so on. This requires me to use Layers and the RuntimeAnimationController.

I am facing massive issues and want to complain a bit hoping maybe someone from Unity reads it.

So, the RuntimeAnimatorController has an array of AnimationClips. If you have, let’s say, “Walk” in the base layer and again “Walk” in another layer of the Animator (maybe a layer “Full Body” that overrides the rest instead of being overriden by it), then the RuntimeAnimatorController contains two clips with the name “Walk”.

If you have 3 layers and all have the same 3 animations, then the AnimationClips array in the RuntimeAnimatorController contains 9 clips.

Now this could be neat. It could be used to stop animations only on certain layers. Here is problem 1: You have Animator.Start(animName, layer); but you don’t have Animator.Stop(animName, layer).

I cannot store them in a Dictionary<namestring, Animation> either because they often have the same names.

Now I tried to work around this by iterating over the AnimationClips[ ] in the RuntimeAnimatorController, but those clips don’t know what layer they are from. The AnimatorController won’t tell you either.

So my suggestion or even a request is, give the AnimationClips a public int that has their layer in it, get-only.

Maybe even implement Animator.Stop(animName, layer); cause lots of people are going to need that anyway.

If anyone knows how to accomplish the things I currently call impossible, please let me know, thanks!

It looks like that wouldn’t even work.

Animation.Stop() doesnt work, neither does Animator.StopPlayback().

The AnimationClip doesn’t know a stop at all.

Ok now I found AnimationState, AnimationStateInfo, AnimationClipInfo, AnimatorTransifionInfo… and neither of them really have anything useful in them.

My head is bursting.

I am amazed anyone has used Unity for projects with a lot of animations at all.

This must be the worst part of Unity. I’m shocked. You took something that is relatively logical and added 500 layers of abstraction for everything, only to leave it inaccessible and confusing. I’ve wasted days on this. Animation, AnimationClip, AnimationState, AnimationStateInfo… it wouldn’t bother me as much if at least the basic stuff worked.

It isn’t well documented either.

For example the priority of the layers is never mentioned anywhere - the ones that are listed below have higher priority. Would be nice to tell people that.

Why does AnimationStateInfo or whatever have a function “bool IsName(string name)” but not simply an attribute “name”? And so on.

It’s really bad! When you finally figure out all the cumbersomeness, you realize that it’s also super buggy.

The system is not built to play through Animator.Play. It’s built to make stuff play by sending string-messages to the animator controller and having the animator controller’s internal logic figure out how to play stuff. So in your case, you’d have a trigger or bool or whatever that only one layer cares about, and use that to play the thing.

Of course, running animations through a string-based message system was a horrible idea from day 1, and your user code ends up as a buggy mess.

2017.1 comes with a low(er) level access to the animation system - Playables - and while the API is a bit cumbersome, it should be possible to create your own system for playing animations on top of it. I’ve gotten layered animations to play just fine without a single animator controller, so it definitely works.

Yeah, the animator is… weird. I keep feeling that I don’t quite get how its supposed to work and maybe that’s actually the case, but the following situation happens much more often than I’d like:

“Oh this thing I want to implement sounds simple and straightforward enough”

tries to implement it with the animator

“What? WHY?”

Yeah using strings to identify anything should be a heresy.

Took me, oh, like 4 hours to explore an understand the Animators, but goddamn that’s still 4 hours wasted.

I had the same thoughts. And then the things I did understand didn’t look too great.

WHAT. Now some of the posts I read make more sense… well strange, I am using the Animator currently. Maybe my RuntimeAnimatorController isn’t needed then?

I think today I figured out how to blend it how I want. Seems like it will require me to use Coroutines and timers to switch body parts back to the idle animation but it should work.

Never heard of that before. Interesting, but I think I’ll stick to my simple animator solution if I can get it work. Should be sufficient for my mobs, maybe the player character can get a more fancy system later.

EDIT: Now I got it figured out. Didn’t even need timers. Phew! PHEW!

Oh … next I wanted to be in charge of the animation speed of each animation clip. I found a solution using parameters in the editor and more wonky stuff.

Why can’t AnimationClip and/or Animation have a scriptable .speed? Agh.

Well at least it works.

@thevillagepeople Hi I am just trying the exact same thing. I want to get get the LayerIndex of a specific AnimationClip within my animator. You said you figured it out, it would be nice if you’d share your workflow :slight_smile:

Thanks in advance!

var animController = _animator.runtimeAnimatorController as AnimatorController;
for(int i = 0; i < animController.layers.Length; i++)
{
var layer = animController.layers*;*
var mask = layer.avatarMask;
if(mask != null)
{
for(int m = 0; m < mask.transformCount; m++)
{
if(mask.GetTransformActive(m) == true)
{
var trans = _targetObj.transform.Find(mask.GetTransformPath(m));
Debug.Log("avatarMask:{mask.name} transform:{trans.name} layer:{layer.name}");* *}* *}* *}* *foreach(var state in layer.stateMachine.states)* *{* *var animClip = state.state.motion as AnimationClip;* *Debug.Log(“animClip:{animClip.name} layer:{layer.name}”);
}
}