Search Unity

Animation rigging package: unable to change weight at runtime

Discussion in 'Animation Rigging' started by supersulu, Aug 16, 2020.

  1. supersulu

    supersulu

    Joined:
    Feb 7, 2019
    Posts:
    6
    So I have a model I rigged with the "two bone IK" constraint, and I want to blend the weight value from 0 to 1 through a script i wrote. However, any modification of this value through script has not had any effect on the actual weight value. The only way I am able to change the weights of these components is through the inspector using the slider with my mouse. In fact I am not able to change any of the public setter values of the animation rigging package through scripts. Does anyone know how to modify these values? Thanks so much!
     
  2. danUnity

    danUnity

    Joined:
    Apr 28, 2015
    Posts:
    229
    You have to access the data property of the constraint component. The data has all the properties you are looking for.
     
  3. simonbz

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    295
    Hi @jakemgarson,

    For TwoBoneIKConstraint and any constraints implementing `IRigConstraint`, you should be able to change your constraint weight by modifying `TwoBoneIKConstraint.weight`.

    Also, there are additional weights set in TwoBoneIKConstraintData (targetPositionWeight, targetRotationWeight and hintWeight) which you can retrieve like @danUnity suggested in TwoBoneIKConstraint.data.

    If this does not work, I would check the following:
    - Are you animating your Rig? If so, make sure that your constraint weight is not animated if you intend to modify it through script.
    - Make sure to modify the constraint weight in `Update` and not `LateUpdate`. The latter will be done after animation has evaluated, and thus will not get picked up when evaluating constraint.
    - Make sure that targetPositionWeight and targetRotationWeight are not set to zero.
     
    Last edited: Aug 19, 2020
    MuhammadAhmadYousaf likes this.
  4. HologramInteractive

    HologramInteractive

    Joined:
    Mar 10, 2015
    Posts:
    1
    But it doesn't do that @simonbz .

    I've got a simple animation referencing the TwoBoneIKConstraint.Weight and it won't budge. I'm sure I can script something to get a workaround going. Am I missing something? Seems like a bug?

    EDIT:
    the workaround is making a script that ref's the constraint's weight, changes its weight at runtime. Then animate the script's weight property. Weird!
     
    Last edited: Oct 14, 2020
  5. danielNTM

    danielNTM

    Joined:
    Mar 1, 2019
    Posts:
    4
    I'm also having trouble with this. I tried directly setting weights through script, and also through animations as mentioned above, but neither worked for me. The only thing that works is manually changing the weight via inspector within the editor at runtime.

    Spent hours trying to debug this. It seems like something is resetting the weight right after I set it. I confirmed my weight change is persisted immediately after my code executes (e.g., following
    leftHandIKRig.GetComponent<Rig>().weight = 0;). However, somewhere between my code execution and the next frame update, the weight gets reset back to what it was before. I tried putting a breakpoint on the setter method in Rig.cs but nothing other than my script is invoking it. Is there any other way to reset that value? Would be nice to have a data breakpoint work with Unity (Something like https://www.jetbrains.com/help/rider/Using_Breakpoints.html#data-breakpoints; if there's a way to make this work please let me know).

    Would appreciate any help resolving this issue.

    Unity Version: 2020.19f1
    Animation Rigging - 0.3.4 preview

    I've upgraded from 2019.4.1f1 LTS recently if that makes any difference. Also on Burst 1.2.0-preview.12 if that matters; I didn't upgrade to 1.3.9 yet as I'm seeing some warning that upgrading may break existing stuff.


    EDIT: I managed to make it work by attaching a custom script directly to the Rig gameobject with a function that can change its weight, then invoking this function from my original external scope. Not sure why this works while manipulating the weight from an external scope doesn't.

    So:
    Some External GameObject -> ReferenceToRigGameObject.RigComponent.weight = newValue; => Doesn't work.
    Some External GameObject -> ReferenceToRigGameObject.CustomRigWeightChangeScript.ChangeWeight(newValue); -> this.gameObject.GetComponenet<Rig>().weight = newValue; => works.

    What am I missing here? Bug or my misunderstanding?
     
    Last edited: Oct 20, 2020
    MuhammadAhmadYousaf likes this.
  6. simonbz

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    295
    Can you submit a bug report using the Unity bug reporter for that? I'm not sure what doesn't work for your use case, and we haven't been able to reproduce a similar issue on our side.

    Be it a bug or not, having a repro case will allow us to better answer you.
     
  7. eliteforcevn

    eliteforcevn

    Joined:
    Oct 25, 2018
    Posts:
    47
    me too, multi aim constraint work with generic avatar but with humanoid it make my character fly away
    and the two bone constraint ik does not work with both humanoid and generic avatar
     
  8. Alessandro_Paciello

    Alessandro_Paciello

    Joined:
    Apr 4, 2020
    Posts:
    2
    I have a multi Parent Constraint rig I'm trying to change the weight of the sourceObject via script but it doesn't allow me to change it, via animation I can
     
    Last edited: Oct 29, 2020
  9. EMartorell

    EMartorell

    Joined:
    Nov 8, 2015
    Posts:
    2
    I've been facing the same problem.
    Saving the target weight value and applying it on every Update() worked for me.
    I have a Multi Aim Constraint and I'm adjusting the weight on the parent Rig script.
     
  10. simonbz

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    295
    Hi, in order to change the weights of a WeightedTransformArray, you need to do the following:

    Code (CSharp):
    1. var sources = parentConstraint.data.sourceObjects;
    2. sources.SetWeight(0, x);
    3. sources.SetWeight(1, y);
    4. aimConstraint.data.sourceObjects = sources;
    WeightedTransformArray is a struct. As such, calling sourceObjects will only retrieve a copy of the array. It needs to be set back in order for the weights to update.
     
  11. MajorParts

    MajorParts

    Joined:
    Sep 27, 2014
    Posts:
    88
    How would you define the source object of a multi-aim constraint with c# please?
     
    quint_unity likes this.
  12. simonbz

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    295
    Similarly to how you set weights:

    Code (CSharp):
    1. var sources = parentConstraint.data.sourceObjects;
    2. sources.SetTransform(0, transform1);
    3. sources.SetTransform(1, transform2);
    4. aimConstraint.data.sourceObjects = sources;
    However, be aware that this will not be applied at runtime. sourceObjects in MultiAim are used to build the constraint job. Modifying these transforms afterwards will not update the job.

    Instead, consider building your constraint ahead of time and use weights to switch from transforms to transforms.
     
    Lorrak likes this.
  13. MajorParts

    MajorParts

    Joined:
    Sep 27, 2014
    Posts:
    88
    Thanks for getting back to me!
    I had what I wanted working while setting it up, as the character being rigged and the target object were present in the scene at the time and dragging the source object from the hierarchy to the inspector was enough. Now, the character being rigged is instantiated and loses the references.
    Your answer sounds like it's not possible to instantiate and then assign.
    I also tried adding a dummy object to the character, then on instantiate, have it reparent itself to the object I wanted as the source. That didn't work either.
     
  14. MajorParts

    MajorParts

    Joined:
    Sep 27, 2014
    Posts:
    88
    what is "aimConstraint" in your answer?

    I had this before...

    Code (CSharp):
    1. void Start()
    2.     {
    3.         player = GameObject.FindGameObjectWithTag("Player");
    4.         playerTarget = player.transform.Find("Root/Hips/Spine_01/Spine_02");
    5.  
    6.         mac = GetComponent<MultiAimConstraint>();
    7.  
    8.         var sources = mac.data.sourceObjects;
    9.  
    10.         sources.SetTransform(0, playerTarget);
    11.  
    12.     }
     
    Last edited: Dec 13, 2020
  15. MajorParts

    MajorParts

    Joined:
    Sep 27, 2014
    Posts:
    88
    I see...adding `mac.data.sourceObjects = sources;` at the end assigns the sources.

    But this still won't make the character aim at the player, right?
     
  16. MajorParts

    MajorParts

    Joined:
    Sep 27, 2014
    Posts:
    88
    This has really knackered me for respawning! I can't have the player as an instantiated prefab (either from scene or assets) on respawn, or else the ai loses reference of what to aim at. Disabling the player on death, moving to spawnpoint and re-enabling messes up the animation rigging positions and disabling the mesh renderers to move to spawn causes him to have seizures. I'm at a loss as to what to try next.
     
  17. KyotoG

    KyotoG

    Joined:
    Jan 18, 2017
    Posts:
    1
    I'm experiencing the same issue where setting the Rig's weight does not stick between updates. In my case, I am using a StateMachineBehaviour that sets the weight in the OnStateUpdate method.
     
  18. simonbz

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    295
    I answered a similar question about Rig weights not so long ago:
    https://forum.unity.com/threads/multi-aim-constraint-set-source-at-runtime.944559/#post-6529880

    Changing the rig weight in a StateMachineBehaviour is past the sync point where we read the scene value in the animation stream for Animation Rigging.

    Like I've said, modified transform references in the aim constraint will not get picked up at runtime. At initialization, the Animation Rigging graph is built with the source transforms you've defined on the constraint and will not update automatically even if you change them.

    Changing the constraint sources means you need to rebuild your animation rigging graph to account for these changes. Have a look at this response I gave on the subject not long ago:
    https://forum.unity.com/threads/generating-rig-at-runtime.935090/#post-6113681
     
  19. JSRemo

    JSRemo

    Joined:
    Jul 26, 2019
    Posts:
    1
    This is old but I was having this problem recently as well, what ended up working for me, was either setting the weight constantly in an update method, or moving the weight changes to a Coroutine, and calling WaitForEndOframe() before setting the weights
    Code (CSharp):
    1. private void DoStuff()
    2. {
    3.     StartCoroutine(TransitionAnimationRigs());
    4. }
    5.  
    6. private IEnumerator TransitionAnimationRigs()
    7. {
    8.     yield return new WaitForEndOfFrame();
    9.     _weaponIdleRig.weight = 0;
    10. }

    Edit:
    That turned out to be somewhat inconsistent when done for many characters, I did end up having to use update, but not constantly, I just primed the rigs to transition by setting a bool _haveRigsTransitioned to false, and calling Update to check:

    if (!_haveRigsTransitioned)
    {
    [INDENT]TransitionRigs();
    _haveRigsTransitioned = true;[/INDENT]
    }


    so it only runs once, tested it for dozens of characters at the same time, and it seems good.
     
    Last edited: Jul 5, 2021
    Valastir, KenjiJU, Rioneer and 2 others like this.
  20. rdcm

    rdcm

    Joined:
    Jan 9, 2017
    Posts:
    5
    Same issue for me:
    Code (CSharp):
    1. namespace Animations
    2. {
    3.     using UnityEngine;
    4.     using UnityEngine.Animations.Rigging;
    5.  
    6.     public class AnimationEventsController : MonoBehaviour
    7.     {
    8.         private RightHandIkController _rightHandIk;
    9.         private WeaponPoseController _weaponPose;
    10.         private RigBuilder _rigBuilder;
    11.  
    12.         void Start()
    13.         {
    14.             _rightHandIk = GetComponentInChildren<RightHandIkController>();
    15.             _weaponPose = GetComponentInChildren<WeaponPoseController>();
    16.             // _rigBuilder = GetComponent<RigBuilder>();
    17.         }
    18.  
    19.         // animation event
    20.         void ThrowGrenade(float value)
    21.         {
    22.             _weaponPose.SetWeight(value);
    23.             _rightHandIk.SetWeight(value);
    24.             // _rigBuilder.Build(); works only after full rebuild
    25.         }
    26.     }
    27. }
    28.  
    29. // RightHandIkController
    30. public void SetWeight(float value)
    31. {
    32.     _twoBoneIKConstrint.weight = value;
    33. }
    34.  
    35. // WeaponPoseController
    36. public void SetWeight(float value)
    37. {
    38.     _multiPositionConstraint.weight = value;
    39. }
    40.  
    How is it possible to avoid rebuild RigBuilder?


    Animation rigging 1.0.3
    Unity - 2020.3.16f1
     
    Last edited: Oct 16, 2021
  21. rdcm

    rdcm

    Joined:
    Jan 9, 2017
    Posts:
    5
    Ok, after detailed reading all of the comments on this topic.
    My fix looks like this:

    Code (CSharp):
    1. namespace Animations
    2. {
    3.     using UnityEngine;
    4.  
    5.     public sealed class AnimationEventsController : MonoBehaviour
    6.     {
    7.         private RightHandIkController _rightHandIk;
    8.         private WeaponPoseController _weaponPose;
    9.         private float _currentWeight = 1.0f;
    10.  
    11.         private void Start()
    12.         {
    13.             _rightHandIk = GetComponentInChildren<RightHandIkController>();
    14.             _weaponPose = GetComponentInChildren<WeaponPoseController>();
    15.         }
    16.  
    17.         // animation event
    18.         private void ThrowGrenade(float value)
    19.         {
    20.             _currentWeight = value;
    21.         }
    22.  
    23.         private void Update()
    24.         {
    25.             _weaponPose.SetWeight(_currentWeight);
    26.             _rightHandIk.SetWeight(_currentWeight);
    27.         }
    28.     }
    29. }
    30.  
     
  22. numbers1234

    numbers1234

    Joined:
    Jan 5, 2019
    Posts:
    31
    What's the deal with this? I am having this issue.
     
  23. Qmansvednetta

    Qmansvednetta

    Joined:
    Mar 8, 2017
    Posts:
    8
    I just made a seperate rig and changed its weight in the update function by toggling a bool from an Animation Behavior Script. As metioned above you cant seem to swtich the weight from an animation Behavior script directly.
     
  24. jisase

    jisase

    Joined:
    Oct 22, 2020
    Posts:
    17
    In 2023 and using Unity 2021.3.7f1 this still happens and what the person to whom I am answering, has raised was the solution, I leave the code I used for this in case someone is useful.

    Code (CSharp):
    1. using UnityEngine;
    2. using UnityEngine.Animations.Rigging;
    3.  
    4. public class RigManager : MonoBehaviour
    5. {
    6.     [Header("References")]
    7.     public Rig handsIkLayer;
    8.     public TwoBoneIKConstraint rightHandIk;
    9.     public TwoBoneIKConstraint leftHandIk;
    10.     public MultiParentConstraint firstWeaponIk;
    11.     public MultiParentConstraint secondWeaponIk;
    12.     public MultiParentConstraint thirdWeaponIk;
    13.  
    14.     [Header("Controllers")]
    15.     [Range(0, 1)] public float handsIkWeight;
    16.     [Range(0, 1)] public float rightHandIkWeight;
    17.     [Range(0, 1)] public float leftHandIkWeight;
    18.     [Range(0, 1)] public float firstWeaponIkWeight;
    19.     [Range(0, 1)] public float secondWeaponIkWeight;
    20.     [Range(0, 1)] public float thirdWeaponIkkWeight;
    21.  
    22.     void Update()
    23.     {
    24.         handsIkLayer.weight = handsIkWeight;
    25.         rightHandIk.weight = rightHandIkWeight;
    26.         leftHandIk.weight = leftHandIkWeight;
    27.         firstWeaponIk.weight = firstWeaponIkWeight;
    28.         secondWeaponIk.weight = secondWeaponIkWeight;
    29.         thirdWeaponIk.weight = thirdWeaponIkkWeight;
    30.     }
    31. }
     
  25. anas1973

    anas1973

    Joined:
    Aug 23, 2017
    Posts:
    4
    Code (CSharp):
    1. public UnityEngine.Animations.Rigging.TwoBoneIKConstraint Hand;
    2.  
    3. void Start()
    4. {
    5.  
    6. Hand.weight = 1;
    7. }
    this is a simple way to do that
     
  26. HwasTaken

    HwasTaken

    Joined:
    Nov 1, 2021
    Posts:
    1
    Something I have found, is that when you have multiple componants (like a rig) instantiated during run time, if those rigs share the same name and parent, they will both be linked together. Meaning that whatever weight value is set on the last one that was instantiated will override the others, and you won't be able to change the weight of the others. The simple solution is to just add a unique number to the end of the name of all the rigs. I'm not sure why this occurs, even if the child objects are different the problem still persists. Hope this helps someone.
     
  27. ofdrykkja

    ofdrykkja

    Joined:
    Jan 17, 2018
    Posts:
    1
    looks like doing rig weight changes during animation transitions is illegal. i've wrap code with weight changes into coroutine with animator.IsInTransion check and now all works like a charm