Search Unity

Multi-Aim Constraint set source at runtime

Discussion in 'Animation Rigging' started by luvjungle, Aug 3, 2020.

  1. luvjungle

    luvjungle

    Joined:
    Dec 18, 2017
    Posts:
    59
    Hi! I'm trying to set source at runtime.
    Code (CSharp):
    1.         var data = aim.data.sourceObjects;
    2.         data.SetTransform(0, PlayerController.instance.aimTransform);
    3.         aim.data.sourceObjects = data;
    Here is my code, but I've tried with sourceObjects.Add() too. The thing is, I am seeing my new source in editor, but it is completely ignored by constraint.
    I am using 0.2.7 package and Unity 2019.4
    Please help
     
  2. danUnity

    danUnity

    Joined:
    Apr 28, 2015
    Posts:
    229
    Yes, it's a common issue that comes up when setting sources at runtime. The rigbuilder animation graph is already built by the time you change the source objects so that won't work by itself.

    Try rebuilding the rig builder graph at the end:

    rigbuilder.Build();

    Let me know if that works
     
  3. luvjungle

    luvjungle

    Joined:
    Dec 18, 2017
    Posts:
    59
    Yeah, that worked, thanks a lot!
     
    david_t7 likes this.
  4. danUnity

    danUnity

    Joined:
    Apr 28, 2015
    Posts:
    229
    No problem, glad to help!
     
    manishpro65 likes this.
  5. BlueJohn

    BlueJohn

    Joined:
    Feb 12, 2018
    Posts:
    1
    Hey, would you care to post your code?. I think Build() breaks my constraints
    https://imgur.com/P0loEOU
    This is what I did:
    Code (CSharp):
    1.         foreach (MultiAimConstraint component in GetComponentsInChildren<MultiAimConstraint>())
    2.         {
    3.             var data = component.data.sourceObjects;
    4.             data.SetTransform(0, mainCamera.transform.Find("AimLookAt").transform);
    5.             component.data.sourceObjects = data;
    6.         }
    7.         RigBuilder rigs = GetComponent<RigBuilder>();
    8.         rigs.Build();
    9.  
     
    Last edited: Oct 1, 2020
    octaviotastico and Zii104 like this.
  6. luvjungle

    luvjungle

    Joined:
    Dec 18, 2017
    Posts:
    59
    Here is my method, where I use Build()
    Code (CSharp):
    1.     void SetAimTarget()
    2.     {
    3.         var data = aim.data.sourceObjects;
    4.         data.Clear();
    5.         data.Add(new WeightedTransform(settings.player.aimTransform, 1));
    6.         aim.data.sourceObjects = data;
    7.         rig.Build();
    8.     }
     
    GodModeTech and Zii104 like this.
  7. Harsh-NJ

    Harsh-NJ

    Joined:
    May 1, 2020
    Posts:
    315
    Does setting weight only works in Update() Method. I tried a callback method for setting weights but it didn't sets the weight on the Constraint. When I copied the whole block into Update() method, it worked
     
  8. simonbz

    simonbz

    Unity Technologies

    Joined:
    Sep 28, 2015
    Posts:
    295
    Hi,

    The Constraints and Rigs weights are animatable properties that are bound to the Animator. However, to make sure they are updated with scene values when they are not directly animated by a clip, we sync the scene values in the animation stream during animation evaluation (ProcessAnimation).

    What this means is that if you change the weight after the value has been synced, you will most likely lose your modifications after the animation system has finished writing back to scene.

    Therefore, the best entry point where you should do weight changes is in the `Update` function before the animation system evaluates.

    For reference here is the full order of execution in Unity: https://docs.unity3d.com/Manual/ExecutionOrder.html
     
  9. Qhuhuit

    Qhuhuit

    Joined:
    Feb 17, 2018
    Posts:
    39
    Thanks !! Could really help to have this in the sourceObject doc.. I've just lost two hours :x
     
    easycardgame likes this.
  10. btschumy

    btschumy

    Joined:
    Jul 31, 2019
    Posts:
    93
    I've just run into this same issue (at least I think it is the same). I have a Prefab that I need to set aim constraints on the Text object contained within. I want the text to always stay oriented to the camera. This was working fine until I made the composite GameObject a Prefab. This lost the connections to the camera.

    Here is what I've tried.


    galacticAxesObj = (GameObject) Instantiate(galacticAxesPrefab);
    // Need to set the aim constraint of all the labels
    var comps = galacticAxesObj.GetComponentsInChildren<AimConstraint>();
    foreach (var comp in comps)
    {
    comp.worldUpObject = camera.transform;
    var contraintSource = new ConstraintSource {sourceTransform = camera.transform};
    comp.SetSource(0, contraintSource);
    }


    It seems like this should be working but it has no effect. I am not using animations here so I don't understand how the RigBuilder would come into play. Is there something else I need to be calling?
     
  11. btschumy

    btschumy

    Joined:
    Jul 31, 2019
    Posts:
    93
    I did finally figure out my issue. When creating the constraintSource above, I also needed to set the "weight" to 1. Apparently it defaults to 0.

    Code (csharp):
    1.                
    2. var contraintSource = new ConstraintSource {sourceTransform = camera.transform, weight = 1};
    3.  
     
  12. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Hey does anyone know why this might not be working?

    Code (CSharp):
    1.         MultiAimConstraint multiAimConstraint = lookAtHead.gameObject.AddComponent<MultiAimConstraint>();//Add Multi Aim Constraint
    2.         multiAimConstraint.data.constrainedObject = head;//Head as constrained object
    3.         WeightedTransform weightedTransform = new WeightedTransform {transform = testTarget.transform, weight = 1f};//Create Look at target
    4.         multiAimConstraint.data.sourceObjects.Add(weightedTransform);//Add target to the lookat source bjects
    5.      
    6.         //Add to the Rig Builder
    7.         RigBuilder rigBuilder = GetComponentInParent<RigBuilder>();
    8.         Rig ikRig = ikRigParent.AddComponent<Rig>();
    9.         Rig lookRig = lookAtRigParent.AddComponent<Rig>();
    10.         RigLayer rigLayerIK = new RigLayer(ikRig);
    11.         RigLayer rigLayerLook = new RigLayer(lookRig);
    12.         rigBuilder.layers.Add(rigLayerIK);
    13.         rigBuilder.layers.Add(rigLayerLook);
    14.         rigBuilder.Build();
    15.         animator.enabled = true;//This stops the rig builder from crashing...
    I just can't get assign the mutli aim source objects at runtime, they always come up empty.

    Ughhhh I had to add it like this. -
    Code (CSharp):
    1.         var sourceObjects = new WeightedTransformArray();
    2.         sourceObjects.Add(weightedTransform);
    3.         multiAimConstraint.data.sourceObjects = sourceObjects;
    Man it's really tedious doing this stuff in runtime. o_O
     
  13. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Okay I spoke too soon, the source object is there but the head bone won't react to the look constraint.
    Mar-18-2021 16-16-44.gif

    I can get it to work on a test object but not anything I build at runtime.
    Code (CSharp):
    1.         //Add Multi Aim Constraint
    2.         MultiAimConstraint multiAimConstraint = rigParent.gameObject.AddComponent<MultiAimConstraint>();
    3.         multiAimConstraint.data.constrainedObject = constrainedObject.transform;//Set constrained object
    4.  
    5.         //Create Look at target  
    6.         WeightedTransform weightedTransform = new WeightedTransform {transform = target.transform, weight = 1f};
    7.         var sourceObjects = new WeightedTransformArray {weightedTransform};
    8.         multiAimConstraint.data.sourceObjects = sourceObjects;
    9.  
    10.         //Build Ik rig
    11.         RigBuilder rigBuilder = rigParent.AddComponent<RigBuilder>();
    12.         Rig lookRig = rigParent.AddComponent<Rig>();
    13.         RigLayer rigLayerIK = new RigLayer(lookRig);
    14.         rigBuilder.layers.Add(rigLayerIK);
    15.         rigBuilder.Build();
    Mar-18-2021 16-30-01.gif

    I'm doing rigBuilder.Build() at the end is there something else I'm missing?

    Thanks,
    Pete
     
  14. danUnity

    danUnity

    Joined:
    Apr 28, 2015
    Posts:
    229
    Maybe hee animator is overritting the RigBuilder?
     
  15. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Yeah I was thinking that might be it but I can’t even get it to work on a simple box setup. o_O
    I’m going to have another try today if I can get a simple demo together I’ll post it up.
     
  16. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Well I haven't had any luck :(
    If anyone has a chance to look at it I've attached a package. I'll probably upload that to support too.

    Code (CSharp):
    1.     public GameObject rigParent;
    2.     public GameObject constrainedObject;
    3.     public GameObject lookTarget;
    4.  
    5.     void Start()
    6.     {
    7.         //Add Component
    8.         MultiAimConstraint multiAimConstraint = constrainedObject.gameObject.AddComponent<MultiAimConstraint>();//Add Multi Aim Constraint
    9.         multiAimConstraint.data.constrainedObject = constrainedObject.transform;//Set constrained object
    10.      
    11.         //Add Target
    12.         WeightedTransform weightedTransform = new WeightedTransform {transform = lookTarget.transform, weight = 1f};//Create Look at target
    13.         var sourceObjects = new WeightedTransformArray {weightedTransform};
    14.         multiAimConstraint.data.sourceObjects = sourceObjects;
    15.      
    16.         //Add Rig to Rig Builder and Build Builder
    17.         RigBuilder rigBuilder = rigParent.AddComponent<RigBuilder>();
    18.         Rig lookRig = rigParent.AddComponent<Rig>();
    19.         RigLayer rigLayerIK = new RigLayer(lookRig);
    20.         rigBuilder.layers.Add(rigLayerIK);
    21.         rigBuilder.Build();
    22.     }
     

    Attached Files:

  17. teutonicus

    teutonicus

    Joined:
    Jul 4, 2012
    Posts:
    71
    @petey
    Make sure to complete and assign MultiAimConstraintData struct, ie
    Code (CSharp):
    1. multiAimConstraint.data = new MultiAimConstraintData
    2. {
    3.     constrainedObject = constrainedObject.transform,
    4.     constrainedXAxis = true,
    5.     constrainedYAxis = true,
    6.     constrainedZAxis = true,
    7.     limits = new Vector2(-180.0f, 180.0f)
    8. };
    or else call Reset() before editing at runtime, as the defaults appear to be "everything off".
     
    petey likes this.
  18. petey

    petey

    Joined:
    May 20, 2009
    Posts:
    1,824
    Ahhh thank you so much @teutonicus! That makes sense :)
     
  19. QuarterMillion

    QuarterMillion

    Joined:
    Jul 18, 2020
    Posts:
    10
    I realize this is a fairly old post but I realize that there really aren't any good Scripting Api documented examples for setting source objects at runtime. The few I've seen in the forum tend to use a copy of the component itself and more than one line to do it. Surely there's a simpler way, right? I mean must it always be var this and that?

    Anyway here's my solution:

    The following is specifically for Animation Rigging version (1.0.3) though you may get mileage out of it as well

    First define and name your target gameObject(s).

    Then when you're ready to assign your target to your rig's MultiAimConstraint child sourceObjects?

    Code (CSharp):
    1.  
    2.  
    3. transformchild.GetComponent<MultiAimConstraint>().data.sourceObjects = new WeightedTransformArray{new WeightedTransform(your target's transform,1*)};
    4.  
    5.  
    *this number represents its weight of influence 1 being the highest influence and 0 being none at all.
    Despite the fact that in the editor it looks like a list I came to a realization. Its not a list its an array. How would you define an array?

    You still want to do all the other stuff suggested previously though. But at least setting the source Objects should be simpler now.
     
    Last edited: Feb 15, 2022
  20. Jex714

    Jex714

    Joined:
    Apr 8, 2017
    Posts:
    1
    A simple solution that I just found was to create an empty object as a child of the object that you want to control the aim for. Call it "aim_target" and assign that as the source in the inspector. Simply change the aim_target's transform.position at runtime from for instance "nearest_enemy.transform.position" to "object_of_interest.transform.position"... I'm satisfied with it as a simple work-around.
     
    ejsingson likes this.
  21. SoYouSay

    SoYouSay

    Joined:
    Feb 21, 2023
    Posts:
    2
    splendid!
     
  22. Oldman_Sam

    Oldman_Sam

    Joined:
    Sep 21, 2019
    Posts:
    1
    Hello! I'm having a similar issue but with the multi-parent constraint.

    I've tested the script and running it OnEnable or Update doesn't really do anything.

    I essentially create the weighted transform and assign it a transform from a list, then use the sourceObjects.Add() to pop it in.

    However, it doesn't seem to actually add anything to the source list, I get no errors being thrown and the BuildI() method above doesn't seem to make a difference to me.

    Any help is appreciated. Using Unity 2021.3.13f1, Animation Rigging version 1.1.1
     
  23. generatedname

    generatedname

    Joined:
    Sep 15, 2015
    Posts:
    7
    this solved my problem. thank you!
     
    petey likes this.
  24. RogueStargun

    RogueStargun

    Joined:
    Aug 5, 2018
    Posts:
    296
    It's generally better to have a dummy transform than to change source objects at runtime imo. The dummy transform can mirror the position or positions of targeted transforms

    I found that even though there's a cost to this, it allows you to lerp between successive targets. For example, I have a turret animation rig using a multiaim constraint, and when a target is destroyed, you don't want the turret head to immediately snap to the next target
     
    Lorrak likes this.