Search Unity

Get layer of AnimationClip / improve Unity pls

Discussion in 'Animation' started by thevillagepeople, Jul 16, 2017.

  1. thevillagepeople

    thevillagepeople

    Joined:
    Jun 21, 2017
    Posts:
    10
    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!
     
  2. thevillagepeople

    thevillagepeople

    Joined:
    Jun 21, 2017
    Posts:
    10
    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.
     
  3. thevillagepeople

    thevillagepeople

    Joined:
    Jun 21, 2017
    Posts:
    10
    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.
     
  4. thevillagepeople

    thevillagepeople

    Joined:
    Jun 21, 2017
    Posts:
    10
    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.
     
  5. Baste

    Baste

    Joined:
    Jan 24, 2013
    Posts:
    6,338
    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.
     
  6. AcidArrow

    AcidArrow

    Joined:
    May 20, 2010
    Posts:
    11,792
    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?"
     
    Last edited: Jul 17, 2017
  7. FMark92

    FMark92

    Joined:
    May 18, 2017
    Posts:
    1,243
    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.
     
  8. thevillagepeople

    thevillagepeople

    Joined:
    Jun 21, 2017
    Posts:
    10
    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!
     
    Last edited: Jul 17, 2017
  9. thevillagepeople

    thevillagepeople

    Joined:
    Jun 21, 2017
    Posts:
    10
    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.
     
    Last edited: Jul 17, 2017
  10. SlimMarten

    SlimMarten

    Joined:
    Sep 26, 2017
    Posts:
    4
    @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 :)

    Thanks in advance!
     
  11. fukaken5050

    fukaken5050

    Joined:
    Feb 3, 2016
    Posts:
    4
    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}");
    }
    }