Search Unity

  1. We are migrating the Unity Forums to Unity Discussions by the end of July. Read our announcement for more information and let us know if you have any questions.
    Dismiss Notice
  2. Dismiss Notice

AnimatorController null after use AnimatorOverrideController

Discussion in 'Animation' started by Benmaster, Nov 29, 2019.

  1. Benmaster

    Benmaster

    Joined:
    Aug 11, 2016
    Posts:
    39
    Currently im using AnimatorOverrideController for different movement animations based on weapon active.

    to switch the override controller im using this:

    Code (CSharp):
    1.  
    2. AnimatorOverrideController overrider = Resources.Load("Attack1AnimOverride") as AnimatorOverrideController;
    3. animator.runtimeAnimatorController = overrider;
    4. animator.runtimeAnimatorController.name = "OverrideRunTimeController";
    5.  
    This works, and the animations are changed correctly.

    But if i want to access the animatorController properties, i cant after use this, I debug a little and using this:

    Code (CSharp):
    1.        
    2. UnityEditor.Animations.AnimatorController ac = animator.runtimeAnimatorController as UnityEditor.Animations.AnimatorController;
    3. RuntimeAnimatorController acx = animator.runtimeAnimatorController as RuntimeAnimatorController;
    4. Debug.Log(ac);
    5. Debug.Log(acx);
    6.  
    On the start this prints "BaseCharacterAnimator" twice, but when I use the OverrideController of the first lines in this comment, the results are "Null" and "OverrideRunTimeController".

    how can I access the AnimatorController properties after apply a OverrideController ?
     
  2. Benmaster

    Benmaster

    Joined:
    Aug 11, 2016
    Posts:
    39
    Im using right now this, but not sure if is correct.

    Code (CSharp):
    1.         AnimatorOverrideController runtimeController = animator.runtimeAnimatorController as AnimatorOverrideController;
    2.         animatorController = animator.runtimeAnimatorController as AnimatorController;
    3.         if (animatorController == null) {
    4.             animatorController = runtimeController.runtimeAnimatorController as AnimatorController;
    5.         }
    6.  
     
  3. Benmaster

    Benmaster

    Joined:
    Aug 11, 2016
    Posts:
    39
    I have a big issue now.. to use AnimatorController animatorController = overrideController.runtimeAnimatorController as AnimatorController; to get the layers, I need to import using UnityEditor.Animations; , but obviously this is not available in compiled version ¿how can I access de Mecanim layers and states from script in builds??
     
  4. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,596
    You can't. There are a lot of stupid things about the Animator Controller system and this is one of them. The only access you have to states at runtime is via animator.GetCurrentAnimatorStateInfo (and GetNext...). So the only way to do it is to get the details you want using an editor script and serialize them separately so you can access your serialized data at runtime.

    If you're interested in finding a better system, you should check out Animancer (link in my signature). It lets you avoid messing around with Animator Controllers (and override controllers) entirely and just play whatever AnimationClips you want. The Lite version lets you try out all the features for free in the Unity Editor and the Pro version is currently 50% off for the Black Friday sale.
     
  5. Benmaster

    Benmaster

    Joined:
    Aug 11, 2016
    Posts:
    39
    Hi, thanks for the reply!
    Its not the first time I found this kind of things in unity... I use UE4 to, and some times (really many) I feel like the Unity force me to pay for external addons every time to have the same of UE4...
    I want to ask you about the animancer 3 things that I smash to wall and waste many hours with Mecanim, and I want to check if Animancer allow me to do:
    - Can I continue using regular Mecanim and extend funcionality like what I want now (change animation and transition speeds AT RUNTIME)?
    - Can I CHANGE or ADD/REMOVE layer mask (for example to stop leg animations when player is not moving) AT Runtime? (Unity dont allow that wtf...)
    - Can I control the animation states and transitions at runtime? I mean, change speed, animation clip of specific state and transition conditions AT runtime?

    thanks!
     
  6. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,596
    You can use Animancer to play individual clips for some things and have other things grouped inside an Animator Controller (the Animator Controllers/Hybrid example demonstrates this), but the stuff in the Animator Controller will be subject to all the same limitations as without Animancer. It's a black box that simply doesn't give us access to many of its details.

    Layers are entirely configured by your scripts at runtime, not actually set up in the editor at all. So you can change masks or move animations between layers if you need to. The Layers example demonstrates this.

    Same for state and transition details. The Fine Control/Spider Bot example shows how you can control the speed and time of an animation. You technically can change the animation clip of a specific state, but you could just as easily call Play(clip) with the new clip to let it create a new state. You don't create states or transitions upfront, you just tell Animancer what to do when you need it done. So there are no transition conditions as such, you can simply put whatever conditions and logic you want in your code to determine what animation you tell Animancer to play.

    There are also Serializables which group a few other things with the AnimationClip if you want to set the details in the Inspector, but you still have scripting access to all those fields and all the actual decision making logic is handled by your scripts.
     
  7. Benmaster

    Benmaster

    Joined:
    Aug 11, 2016
    Posts:
    39
    I purchase the Pro version after check the examples, but now im not sure how to manage the changes...
    Actually I have 6 animatorOverrideController with BlendTrees inside for the player movement (every state have different animations based on weapon type, duals, 1H, 2H, Bow, etc)

    What I do now, is, based on the weapon equiped, change the animatorOverrideController, and then for the attack, I change the clip of "attack1" animation, and then setTrigger("Attack1") to fire the animation what I want.

    Im thinking in use the Hybrid system, keep my overrideControllers with the movement bledTree, change the controller in the Hybrid Animancer Component, and then execute the attack without any trigger only with the Crossfade(Attack)

    This is because the blendTree for the 6 types, are many, not sure if Animancer have a better way to make blendTrees with this 6 cases without using Hybrid Component.

    EDIT:
    I get this working, but not sure if is "ok", I get all controllers switch correctly and play animations with crossfade, INCLUSIVE I GET CROSSFADE BETWEEN AnimatorController changes.. awesome.

    With this, I change between AnimatorControllers, this keep mechanim working, creating Animancer new states, and setting active with PlayController();

    Code (CSharp):
    1. animancer = baseModel.transform.GetComponent<HybridAnimancerComponent>();
    2. RuntimeAnimatorController overrider = Resources.Load(aoc) as RuntimeAnimatorController;
    3. characterController.animancer.Controller = overrider;
    4. characterController.animancer.PlayController();
    Then to play attacks I use this:

    Code (CSharp):
    1. var state = animancer.CrossFade(ab.animations[0].animation);
    2. state.OnEnd = OnAttackEnd;
    3.  
    4.     private void OnAttackEnd()
    5.     {
    6.         animancer.PlayController();
    7.     }
    8.  
    This execute the animation, and crossfade back to the last AnimatorController()

    Works perfect, now I only need to find how to put some animation in loop (to keep playing while the user keep pressed the key for example), but for now work like I want.

    Only for the feature to change AvatarMask on fly the Animancer is a must have.

    PD: With Unity 2019.3f1, I get an error in the Editor when load the HybridController component, I check the code and appear a problem with the calculation of the component window width, its easy to fix removing "B" from the line "var width = A + B", only FYI.
     
    Last edited: Dec 1, 2019
  8. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,596
    The Spider Bot example I linked earlier shows how you can loop an animation while the user holds a key, then go back to something else.

    Thanks for letting me know about the issue in 2019.3. Your fix for that line will obviously work, but it won't draw the Inspector as it should. Here's how to fix it properly:
    Code (CSharp):
    1.         private static float _ToggleWidth = -1;
    2.  
    3.         private void DoDefaultAnimationField(SerializedProperty playAutomatically)
    4.         {
    5.             var area = AnimancerGUI.LayoutSingleLineRect();
    6.  
    7.             if (_ToggleWidth == -1)
    8.                 _ToggleWidth = GUI.skin.toggle.CalculateWidth(GUIContent.none);
    9.  
    10.             var playAutomaticallyWidth = EditorGUIUtility.labelWidth + _ToggleWidth;
     
    Benmaster likes this.