Execute the action of ScaleConstraint's Activate button in C#

I want to execute the action of ScaleConstraint’s Activate button in C#.
When I manually press the ScaleConstraint’s ActivateButton, Unity sets an automatic value for scaleOffset.
I wanted to perform this operation from a C# Editor extension, but I couldn’t find a way to operate the ActiveButton from C#.
I tried the following code as an alternative, but it didn’t set scaleOffset.

    private void AddScaleConstraintAndActivate(GameObject target, Transform source)
    {
        ScaleConstraint scaleConstraint = target.AddComponent<ScaleConstraint>();
        ConstraintSource constraintSource = new ConstraintSource()
        {
            sourceTransform = source,
            weight = 1,
        };
        scaleConstraint.AddSource(constraintSource);
        scaleConstraint.constraintActive = true;
        scaleConstraint.enabled = true;
        scaleConstraint.locked = false;
        target.transform.localScale = source.localScale;
        scaleConstraint.locked = true;
        scaleConstraint.enabled = false;
    }

How can I execute the action of ScaleConstraint’s Activate button in C#?

As per documentation this is what Activate does

I don’t know enough about this subject to give you any code, but maybe that offers a clue to what it does.

Thank you for your input!

As the documentation states, when I click the ‘Activate’ button, Unity automatically sets the scaleOffset value. My challenge lies in set this value from a custom script.

I’ve considered two approaches, each with its own drawbacks.

First, I could try to call an official Unity script that recalculates scaleOffset. However, I haven’t been able to locate such a script.

Alternatively, I could implement a script that mimics Unity’s automatic recalculation formula. Unfortunately, the exact formula is currently unknown.

You can see what the button is doing code-wise in the C# source reference: UnityCsReference/Editor/Mono/Inspector/ConstraintEditorBase.cs at master · Unity-Technologies/UnityCsReference · GitHub

Which ends up calling this explicitly implemented interface method: UnityCsReference/Modules/Animation/ScriptBindings/Constraint.bindings.cs at master · Unity-Technologies/UnityCsReference · GitHub

Which ends up calling an external method, so the code behind it is locked behind C++ source code access.

So to call the specific method you would need to use reflection.

Thank you so much for your detailed and informative explanation. Your answer has been incredibly helpful in solving my problem.

I was surprised to learn that Unity’s C# is open-source and that reflection is such a powerful tool.

It looks like I can achieve what I want by executing the following code to dynamically invoke the :

System.Reflection.MethodInfo methodInfo = scaleConstraint.GetType().GetMethod("ActivateAndPreserveOffset");
methodInfo.Invoke(scaleConstraint, null);

I’ll test this solution later and let you know how it goes!

I tried ActivateAndPreserveOffset, which gave me another problem to solve.
Due to requirements from other systems, I need to set ScaleConstraint to enabled=false. and, this makes strange behavior.

    private void SetupScaleConstraint()
    {
        var headBone= _animator.GetBoneTransform(HumanBodyBones.Head);
        var scaleConstraint = headBone.gameObject.AddComponent<ScaleConstraint>();

        ConstraintSource constraintSource = new ConstraintSource();
        constraintSource.sourceTransform = _poseClipperScaleTransfrom;
        constraintSource.weight = 1;
        scaleConstraint.AddSource(constraintSource);

        Type constraintType = typeof(ScaleConstraint);
        MethodInfo activateAndPreserveOffsetMethod = constraintType.GetMethod("ActivateAndPreserveOffset", BindingFlags.Instance | BindingFlags.NonPublic);
        try
        {
            activateAndPreserveOffsetMethod.Invoke(scaleConstraint, null);
        }
        catch { }

        scaleConstraint.enabled = false; //<---This code makes strange behavior.

    }

And, ActivateAndPreserveOffsetMethod.Invoke(scaleConstraint, null); causes a null pointer exception. It seems to work to some extent, but I don’t really know the appropriate solution to this.