1 year ago

#370684

test-img

Salah Rashad

Inverse Kinematics (IK) Foot Placement

I have a problem with my humanoid character's Foot IK.

I'm building an Isometric Top-Down game with NavMesh to move the Player on click, and I wanted to add some life to the characters so I decided to add IK Foot Placement by following this tutorial.

It worked well, but I wanted to go further by making it more sensitive to colliders so the player's foot gets placed on the ground's surface perfectly.

This script below works well when the ground is rotated.

I tried to fix it a lot but it still doesn't work.

[ Preview Images ]

Here's my script:

using UnityEngine;
using UnityEngine.AI;


public class IKFootPlacement : MonoBehaviour
{
    public bool ikActive = false;
    public Animator anim;
    public NavMeshSurface navmesh;

    public LayerMask layerMask;

    public Transform LeftFoot_Transform;
    public Transform RightFoot_Transform;

    public float LeftFoot_DistanceToGround;
    public float RightFoot_DistanceToGround;



    public float footGap = 0.0f;

    private Vector3 L_TargetPosition;
    private Vector3 R_TargetPosition;

    private Ray L_Ray;
    private Ray R_Ray;

    void Start()
    {
        anim = GetComponent<Animator>();
    }

    void OnAnimatorIK(int layerIndex)
    {
        if (anim)
        {

            // Vector3 LeftFoot_position = anim.GetIKPosition(AvatarIKGoal.LeftFoot);
            // Vector3 RightFoot_Position = anim.GetIKPosition(AvatarIKGoal.RightFoot);


            float IKLeftWeight = anim.GetFloat("IKLeftFootWeight");
            anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, IKLeftWeight);
            anim.SetIKRotationWeight(AvatarIKGoal.LeftFoot, IKLeftWeight);

            float IKRightWeight = anim.GetFloat("IKRightFootWeight");
            anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, IKRightWeight);
            anim.SetIKRotationWeight(AvatarIKGoal.RightFoot, IKRightWeight);


            //~ Left Foot
            if (LeftFoot_Transform)
            {
                RaycastHit L_Hit;

                L_Ray = new Ray(LeftFoot_Transform.position + Vector3.up, Vector3.down);
                if (Physics.Raycast(L_Ray, out L_Hit, 2f, layerMask))
                {
                    L_TargetPosition = L_Hit.point;
                    LeftFoot_DistanceToGround = Vector3.Distance(LeftFoot_Transform.position, L_TargetPosition);

                    if (LeftFoot_DistanceToGround > 0.15)
                        L_TargetPosition.y -= LeftFoot_DistanceToGround;
                    else
                        L_TargetPosition.y += LeftFoot_DistanceToGround;


                    L_TargetPosition.y += footGap;




                    anim.SetIKPosition(AvatarIKGoal.LeftFoot, L_TargetPosition);
                    anim.SetIKRotation(AvatarIKGoal.LeftFoot, Quaternion.LookRotation(transform.forward, L_Hit.normal));

                }
            }

            //~ Right Foot
            if (RightFoot_Transform)
            {
                RaycastHit R_Hit;


                R_Ray = new Ray(RightFoot_Transform.position + Vector3.up, Vector3.down);
                if (Physics.Raycast(R_Ray, out R_Hit, 2f, layerMask))
                {
                    R_TargetPosition = R_Hit.point;
                    RightFoot_DistanceToGround = Vector3.Distance(RightFoot_Transform.position, R_TargetPosition);

                    if (RightFoot_DistanceToGround > 0.15)
                        R_TargetPosition.y -= RightFoot_DistanceToGround;
                    else
                        R_TargetPosition.y += RightFoot_DistanceToGround;


                    R_TargetPosition.y += footGap;


                    anim.SetIKPosition(AvatarIKGoal.RightFoot, R_TargetPosition);
                    anim.SetIKRotation(AvatarIKGoal.RightFoot, Quaternion.LookRotation(transform.forward, R_Hit.normal));

                }
            }
        }
    }

    void OnDrawGizmos()
    {
        Gizmos.color = Color.magenta;
        Gizmos.DrawWireSphere(L_TargetPosition, 0.05f);
        Gizmos.DrawWireSphere(R_TargetPosition, 0.05f);

        Gizmos.color = Color.red;
        Gizmos.DrawRay(L_Ray);
        Gizmos.DrawRay(R_Ray);
    }
}

unity-game-engine

game-development

inverse-kinematics

0 Answers

Your Answer

Accepted video resources