Multi-Aim Constraint set source at runtime

Hi! I’m trying to set source at runtime.

        var data = aim.data.sourceObjects;
        data.SetTransform(0, PlayerController.instance.aimTransform);
        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

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

5 Likes

Yeah, that worked, thanks a lot!

1 Like

No problem, glad to help!

1 Like

Hey, would you care to post your code?. I think Build() breaks my constraints
https://imgur.com/P0loEOU
This is what I did:

        foreach (MultiAimConstraint component in GetComponentsInChildren<MultiAimConstraint>())
        {
            var data = component.data.sourceObjects;
            data.SetTransform(0, mainCamera.transform.Find("AimLookAt").transform);
            component.data.sourceObjects = data;
        }
        RigBuilder rigs = GetComponent<RigBuilder>();
        rigs.Build();
2 Likes

Here is my method, where I use Build()

    void SetAimTarget()
    {
        var data = aim.data.sourceObjects;
        data.Clear();
        data.Add(new WeightedTransform(settings.player.aimTransform, 1));
        aim.data.sourceObjects = data;
        rig.Build();
    }
2 Likes

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

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

Thanks !! Could really help to have this in the sourceObject doc… I’ve just lost two hours :x

1 Like

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?

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.

var contraintSource = new ConstraintSource {sourceTransform = camera.transform, weight = 1};
3 Likes

Hey does anyone know why this might not be working?

        MultiAimConstraint multiAimConstraint = lookAtHead.gameObject.AddComponent<MultiAimConstraint>();//Add Multi Aim Constraint
        multiAimConstraint.data.constrainedObject = head;//Head as constrained object
        WeightedTransform weightedTransform = new WeightedTransform {transform = testTarget.transform, weight = 1f};//Create Look at target
        multiAimConstraint.data.sourceObjects.Add(weightedTransform);//Add target to the lookat source bjects
      
        //Add to the Rig Builder
        RigBuilder rigBuilder = GetComponentInParent<RigBuilder>();
        Rig ikRig = ikRigParent.AddComponent<Rig>();
        Rig lookRig = lookAtRigParent.AddComponent<Rig>();
        RigLayer rigLayerIK = new RigLayer(ikRig);
        RigLayer rigLayerLook = new RigLayer(lookRig);
        rigBuilder.layers.Add(rigLayerIK);
        rigBuilder.layers.Add(rigLayerLook);
        rigBuilder.Build();
        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. -

        var sourceObjects = new WeightedTransformArray();
        sourceObjects.Add(weightedTransform);
        multiAimConstraint.data.sourceObjects = sourceObjects;

Man it’s really tedious doing this stuff in runtime. :eyes:

Okay I spoke too soon, the source object is there but the head bone won’t react to the look constraint.
6947645--817070--Mar-18-2021 16-16-44.gif

I can get it to work on a test object but not anything I build at runtime.

        //Add Multi Aim Constraint
        MultiAimConstraint multiAimConstraint = rigParent.gameObject.AddComponent<MultiAimConstraint>();
        multiAimConstraint.data.constrainedObject = constrainedObject.transform;//Set constrained object

        //Create Look at target  
        WeightedTransform weightedTransform = new WeightedTransform {transform = target.transform, weight = 1f};
        var sourceObjects = new WeightedTransformArray {weightedTransform};
        multiAimConstraint.data.sourceObjects = sourceObjects;
  
        //Build Ik rig
        RigBuilder rigBuilder = rigParent.AddComponent<RigBuilder>();
        Rig lookRig = rigParent.AddComponent<Rig>();
        RigLayer rigLayerIK = new RigLayer(lookRig);
        rigBuilder.layers.Add(rigLayerIK);
        rigBuilder.Build();

6947645--817073--Mar-18-2021 16-30-01.gif

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

Thanks,
Pete

Maybe hee animator is overritting the RigBuilder?

Yeah I was thinking that might be it but I can’t even get it to work on a simple box setup. :eyes:
I’m going to have another try today if I can get a simple demo together I’ll post it up.

Well I haven’t had any luck :frowning:
If anyone has a chance to look at it I’ve attached a package. I’ll probably upload that to support too.

    public GameObject rigParent;
    public GameObject constrainedObject;
    public GameObject lookTarget;

    void Start()
    {
        //Add Component
        MultiAimConstraint multiAimConstraint = constrainedObject.gameObject.AddComponent<MultiAimConstraint>();//Add Multi Aim Constraint
        multiAimConstraint.data.constrainedObject = constrainedObject.transform;//Set constrained object
      
        //Add Target
        WeightedTransform weightedTransform = new WeightedTransform {transform = lookTarget.transform, weight = 1f};//Create Look at target
        var sourceObjects = new WeightedTransformArray {weightedTransform};
        multiAimConstraint.data.sourceObjects = sourceObjects;
      
        //Add Rig to Rig Builder and Build Builder
        RigBuilder rigBuilder = rigParent.AddComponent<RigBuilder>();
        Rig lookRig = rigParent.AddComponent<Rig>();
        RigLayer rigLayerIK = new RigLayer(lookRig);
        rigBuilder.layers.Add(rigLayerIK);
        rigBuilder.Build();
    }

6950291–817628–MultiAim Issue.unitypackage (7.66 KB)

@petey
Make sure to complete and assign MultiAimConstraintData struct, ie

multiAimConstraint.data = new MultiAimConstraintData
{
    constrainedObject = constrainedObject.transform,
    constrainedXAxis = true,
    constrainedYAxis = true,
    constrainedZAxis = true,
    limits = new Vector2(-180.0f, 180.0f)
};

or else call Reset() before editing at runtime, as the defaults appear to be “everything off”.

1 Like

Ahhh thank you so much @teutonicus ! That makes sense :slight_smile:

2 Likes

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?

transformchild.GetComponent<MultiAimConstraint>().data.sourceObjects = new WeightedTransformArray{new WeightedTransform(your target's transform,1*)};

*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.

3 Likes

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.

1 Like