FinalIK integration - (manage) Limbs Action

Note: This AC action allows you to manage finalIK Limbs.

> I've been working to create custom actions that allow for direct access to the FBBIK component through Adventure Creator. So far I've developed one for the Body and another for Limbs. I haven't tested them exhaustively or anything but they appear to actually work.
>
>

To use it replace the text in a .cs file named FinalIK\_Limb with this text, or create a new blank text file, then paste the text and rename the file FinalIK\_Limb.cs. Then drop the file into the folder named actions inside the Adventure creator folder. Then, just use the action in an action list.

Script:

```
using UnityEngine;
using System.Collections;

using RootMotion.FinalIK;

#if UNITY_EDITOR
using UnityEditor;
#endif

 namespace AC
 {
     [System.Serializable]
    public class FinalIK_Limb : Action
     {
         public bool isPlayer;
        public FullBodyBipedIK targetchar;

         //End Effector (Hand/Foot)
        //The target Transform (optional, you can use the position instead. Position will not impact this target)
        public GameObject target;

        //Set the effector position to a point in world space. This has no effect if the effector's positionWeight is 0 and only has an effect if no target is specified.
        public Vector3 position;

        //Weight of the effector position
        public float positionWeight;

        //Weight of the effector rotation
        public float rotationWeight;

        //Keeps the node position relative to the triangle defined by the plane bones (applies only to end-effectors)
        public float maintainRelativePositionWeight;

        //Start Effector (Shoulder/Thigh)
        //The target Transform (optional, you can use just the position and rotation instead).
        public GameObject startEffectorTarget;

        //The effector position weight
        public float startEffectorPositionWeight;

        //Mapping
        //The slerp weight of rotating the limb to it's IK pose
        public float mappingWeight;

        //The weight of maintaining the bone's animated rotation in world space
        public float maintainRotationWeight;

        //Chain
         //The FBBIK chain type
        public FullBodyBipedChain limb;

        //When all chains have pull equal to 1, pull weight is distributed equally between the limbs. That means reaching all effectors is not quaranteed if they are very far from each other. However, when for instance the left arm chain has pull weight equal to 1 and all others have 0, you can pull the character from it's left hand to Infinity without losing contact.
        public float pull;

        //Increasing this value will make the limb pull the body closer to the target
        public float reach;

        //The weight of the end-effector pushing the first node
        public float push;

        //The amount of push force transferred to the parent (from hand or foot to the body)
        public float pushParent;

        //Smoothing the effect of the reach with the expense of some accuracy
        public FBIKChain.Smoothing reachSmoothing;

        //Smoothing the effect of the Push
        public FBIKChain.Smoothing pushSmoothing;

        //The bend goal GameObject. The limb will be bent in the direction towards this GameObject
        public GameObject bendGoal;

        //The weight of bending the limb towards the Bend Goal
        public float bendGoalWeight;

        public FinalIK_Limb()
        {
             this.isDisplayed = true;
            category = ActionCategory.Custom;
            title = "Final IK - Limb";
            description = "Manages a FullBodyBipedIK limb";
            isPlayer = true;

        }

         override public float Run()
        {
             if (isPlayer)
            {
                 targetchar = KickStarter.player.GetComponent<FullBodyBipedIK>();

                if (targetchar == null)
                {
                    Debug.LogWarning("FinalIK_BodyEffector: No FBBIK component found on Player.");
                    return 0f;
                }
            }

             var effector = targetchar.solver.GetEndEffector(limb);
            var chain = targetchar.solver.GetChain(limb);
            var mapping = targetchar.solver.GetLimbMapping(limb);
            var startEffector = targetchar.solver.GetEffector(GetStartEffector(limb));

            pull = Mathf.Clamp(pull, 0f, 1f);
            reach = Mathf.Clamp(reach, 0f, 1f);
            push = Mathf.Clamp(push, 0f, 1f);
            pushParent = Mathf.Clamp(pushParent, -1f, 1f);

            positionWeight = Mathf.Clamp(positionWeight, 0f, 1f);
            rotationWeight = Mathf.Clamp(rotationWeight, 0f, 1f);
            maintainRelativePositionWeight = Mathf.Clamp(maintainRelativePositionWeight, 0f, 1f);

            startEffectorPositionWeight = Mathf.Clamp(startEffectorPositionWeight, 0f, 1f);

            maintainRotationWeight = Mathf.Clamp(maintainRotationWeight, 0f, 1f);
            mappingWeight = Mathf.Clamp(mappingWeight, 0f, 1f);

            chain.pull = pull;
            chain.reach = reach;
            chain.push = push;
            chain.pushParent = pushParent;
            chain.reachSmoothing = reachSmoothing;
            chain.pushSmoothing = pushSmoothing;
            chain.bendConstraint.bendGoal = bendGoal == null ? null : bendGoal.transform;
            chain.bendConstraint.weight = bendGoalWeight;

            effector.target = target == null ? null : target.transform;
            effector.position = position;
            effector.positionWeight = positionWeight;
            effector.rotationWeight = rotationWeight;
            effector.maintainRelativePositionWeight = maintainRelativePositionWeight;

            startEffector.target = startEffectorTarget == null ? null : startEffectorTarget.transform;
            startEffector.positionWeight = startEffectorPositionWeight;

            mapping.maintainRotationWeight = maintainRotationWeight;
            mapping.weight = mappingWeight;
            return 1f;
        }

         private static FullBodyBipedEffector GetStartEffector(FullBodyBipedChain chain)
        {
             switch (chain)
            {
                 case FullBodyBipedChain.LeftArm: return FullBodyBipedEffector.LeftShoulder;
                case FullBodyBipedChain.RightArm: return FullBodyBipedEffector.RightShoulder;
                case FullBodyBipedChain.LeftLeg: return FullBodyBipedEffector.LeftThigh;
                default: return FullBodyBipedEffector.RightThigh;
            }
         }

         override public void Skip()
        {

         }

 #if UNITY_EDITOR
        override public void ShowGUI()
        {
             isPlayer = EditorGUILayout.Toggle("Is player?", isPlayer);

            if (!isPlayer)
            {
                 targetchar = (FullBodyBipedIK)EditorGUILayout.ObjectField("Character:", targetchar, typeof(FullBodyBipedIK), true);
            }

             limb = (FullBodyBipedChain)EditorGUILayout.EnumPopup("Limb:", limb);

            //End Effector
            target = (GameObject)EditorGUILayout.ObjectField("Hand or Foot Target:", target, typeof(GameObject), true);
            position = (Vector3)EditorGUILayout.Vector3Field("Position:", position);
            positionWeight = EditorGUILayout.Slider("Position Weight:", positionWeight, 0f, 1f);
            rotationWeight = EditorGUILayout.Slider("Rotation Weight:", rotationWeight, 0f, 1f);
            maintainRelativePositionWeight = EditorGUILayout.Slider("Maintain Relative Position Weight:", maintainRelativePositionWeight, 0f, 1f);

            //No mid Effector (Thigh, shoulder, etc.) included in this action yet.

            //Chain
            pull = EditorGUILayout.Slider("Pull:", pull, 0f, 1f);
            reach = EditorGUILayout.Slider("Reach:", reach, 0f, 1f);
            push = EditorGUILayout.Slider("Push:", push, 0f, 1f);
            pushParent = EditorGUILayout.Slider("Push Parent:", pushParent, -1f, 1f);
            reachSmoothing = (FBIKChain.Smoothing)EditorGUILayout.EnumPopup("Reach Smoothing:", reachSmoothing);
            pushSmoothing = (FBIKChain.Smoothing)EditorGUILayout.EnumPopup("Push Smoothing:", pushSmoothing);
            bendGoal = (GameObject)EditorGUILayout.ObjectField("Bend Goal:", bendGoal, typeof(GameObject), true);
            bendGoalWeight = EditorGUILayout.Slider("Bend Goal Weight:", bendGoalWeight, 0f, 1f);

            //Mapping
            mappingWeight = EditorGUILayout.Slider("Mapping Weight:", mappingWeight, 0f, 1f);
            maintainRotationWeight = EditorGUILayout.Slider("Maintain Hand Rotation:", maintainRotationWeight, 0f, 1f);

                AfterRunningOption();
            }
 #endif
     }
 }

```

[Script provided by user Larsos]