Search Unity

Is it possible to dynamically change the mask applied to animation layers in Mecanim?

Discussion in 'Animation' started by Gibbster2, Jun 15, 2015.

  1. Gibbster2

    Gibbster2

    Joined:
    Jun 15, 2015
    Posts:
    14
    In the legacy system it was possible to add mixing transforms dynamically. Is it possible to do the same in Mecanim?
    For example, suppose you had a full-body sword swipe anim. When the player is stationary, I want to play the animation wholesale i.e. on the whole body. When the player is running around, I just want to play the animation on the upper body only.
    Can it be done? I haven't come across anything that suggests I can dynamically change the mask for an animation layer or would that not be the way to go?
    Cheers.
     
  2. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    No, it not possible to dynamically change the mask at runtime
     
  3. Viniterra

    Viniterra

    Joined:
    Dec 4, 2014
    Posts:
    193
    Hi, this page on the manual could lead to some misinterpretation:

    "Mask assets can be used in Animator Controllers, when specifying Animation Layers to apply masking at runtime, ..."
    https://docs.unity3d.com/Manual/class-AvatarMask.html

    What does that statement means in fact?

    Just to note, as a workaround I have tried to change the active body parts of a mask at runtime (on LateUpdate function), but it seems to mess with the animator, loosing its reference after deactivating some body parts.
     
  4. Mecanim-Dev

    Mecanim-Dev

    Joined:
    Nov 26, 2012
    Posts:
    1,675
    yup I agree this is not quite clear.
    Mask asset can be used in your controller's layers when you build a controller. see image below

    If you need to change the mask at runtime, then you should try to use the new playable API which has the AnimationLayerMixerPlayable

    mask.png
     
  5. AKQJ10

    AKQJ10

    Joined:
    Feb 9, 2012
    Posts:
    33
    Hi, I am trying to assign AvatarMask in code, not at runtime. But it doesn't work, the newly created layer has no mask. the other layer parameters are correct. And srcBoneMask is not null. I'd really appreciate it if you can give me a hint? Thanks in advance.

    srcAnimatorController.AddLayer(newLayerName);
    AnimatorControllerLayer newLayer = srcAnimatorController.layers[srcAnimatorController.layers.Length - 1];
    newLayer.defaultWeight =0f;
    newLayer.blendingMode = AnimatorLayerBlendingMode.Override;
    newLayer.iKPass = false;
    newLayer.avatarMask = srcBoneMask;
     
    helenemlrb likes this.
  6. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    Try putting
    srcAnimatorController.layers[srcAnimatorController.layers.Length - 1] = newLayer;
    at the end so it knows you have actually modified the layer.

    If that doesn't work, try
    srcAnimatorController.layers = srcAnimatorController.layers;
    .

    I definitely recommend the Playables API though. There's really no reason why this sort of thing should need to be locked in before runtime.
     
  7. AKQJ10

    AKQJ10

    Joined:
    Feb 9, 2012
    Posts:
    33
    Thanks a lot, SilentSin. That method works like a charm.
     
  8. wechat_os_Qy098xGWGAJvxCeQXNlQS8ySc

    wechat_os_Qy098xGWGAJvxCeQXNlQS8ySc

    Joined:
    Jul 30, 2020
    Posts:
    2
    is it possible to change the animation update frequency in Animancer. for example when a NPC is far away i only want to update its anim 5 times per second

    sorry for posting the question here, I only know you seem to be the author of Animancer.
     
  9. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    animancer.Playable.PauseGraph will prevent it from updating on its own, then you can call animancer.Evaluate(deltaTime) whenever you want.
     
  10. wechat_os_Qy098xGWGAJvxCeQXNlQS8ySc

    wechat_os_Qy098xGWGAJvxCeQXNlQS8ySc

    Joined:
    Jul 30, 2020
    Posts:
    2
    great!
     
  11. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    34
    I'm instantiating a prefab animation controller at runtime. But the runtimeAnimationController doesn't seem to allow any addlayer command, or even access to the layers. How can I set an AvatarMask when I instantiate my animation controller at runtime?

    Code (CSharp):
    1.  
    2. animator = myParentObj.AddComponent<Animator>();
    3. animator.runtimeAnimatorController = Resources.Load(animationContollerPaths[def.animationControllerID]) as RuntimeAnimatorController;
    4. animator.avatar = myAvatar;
    5.  
    6. var b = agentDat.animator.layerCount;
    7.  
    8. // till here it works and animates.
    9. // now i want to add code to animate the 'extra bones' availavble in both the model and the animations.
    10.  
    11. animator.AddLayer -> doesn't exist
    12. animator.runtimeAnimationController.AddLayer -> doesn't exist
    13. animator.AnimationController -> doesn't exist
    14. animator.GetAnimationController -> doesn't exist
    15.  
     
  12. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    You can't. It's not possible to change the masks of an Animator Controller at runtime.
     
  13. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    34
    Ah, thanks. So then I'll try adding the avatarmask to the prefab of the animationcontroller which is set as runtimeAnimationController. In the prefab I see the layer with the mask set, but at runtime the new layer dissapears from the controller. Any idea what is happening?
     

    Attached Files:

  14. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    That looks like two completely different Animator Controllers since the states are in different places.
     
  15. unitylepi

    unitylepi

    Joined:
    May 21, 2018
    Posts:
    34
    Ah, yes, I had a depicated one lying around. Anyway, put it on the right one but extra bones won't actually animate unless I set the avatarmask directly in the import settings of each of the animation clips :(
     
  16. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    If you want the ability to change layer masks at runtime, you can try out Animancer (link in my signature) or make your own system using the Playables API. Otherwise yeah, you'll have to come up with clunky manual workarounds to simple problems if you keep using Animator Controllers.
     
  17. eliteforcevn

    eliteforcevn

    Joined:
    Oct 25, 2018
    Posts:
    47
    for me it is very important to be able to change the avatar mask layer for the animation controller because my weapons share the same transition logic but the weapons have a lot of extended bones so it is quite complicated to create multiple animaiton clones controller will be very difficult to manage them
     
  18. AlundraFlint

    AlundraFlint

    Joined:
    May 3, 2016
    Posts:
    6
    maybe I'm stupid, but how are you using this code if not in runtime? Where do you write it?
     
  19. AlundraFlint

    AlundraFlint

    Joined:
    May 3, 2016
    Posts:
    6
    but is it possible to do it in editor with code? How do you select the mask variable then?
     
  20. Kybernetik

    Kybernetik

    Joined:
    Jan 3, 2013
    Posts:
    2,570
    var animatorController = animator.runtimeAnimatorController as UnityEditor.AnimatorController;


    That gives you access to the Editor-only stuff.
     
    AlundraFlint likes this.