title: Inverse Kinematics (IK) Foot Placement
body: <p>I have a problem with my humanoid character's <strong>Foot IK</strong>.</p>
  <p>I'm building an Isometric Top-Down game with <code>NavMesh</code> to move the Player on click, and I wanted to add some life to the characters so I decided to add <strong>IK Foot Placement</strong> by following this <a href="https://www.youtube.com/watch?v=rGB1ipH6DrM" rel="nofollow noreferrer">tutorial</a>.</p>
  <p>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.</p>
  <p>This script below works well when the ground is rotated.</p>
  <p>I tried to fix it a lot but it still doesn't work.</p>
  <p><a href="https://imgur.com/a/mrDwR1J" rel="nofollow noreferrer">[ Preview Images ]</a></p>
  <p>Here's my script:</p>
  <pre class="lang-cs prettyprint-override"><code>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&lt;Animator&gt;();
      }
  
      void OnAnimatorIK(int layerIndex)
      {
          if (anim)
          {
  
              // Vector3 LeftFoot_position = anim.GetIKPosition(AvatarIKGoal.LeftFoot);
              // Vector3 RightFoot_Position = anim.GetIKPosition(AvatarIKGoal.RightFoot);
  
  
              float IKLeftWeight = anim.GetFloat(&quot;IKLeftFootWeight&quot;);
              anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, IKLeftWeight);
              anim.SetIKRotationWeight(AvatarIKGoal.LeftFoot, IKLeftWeight);
  
              float IKRightWeight = anim.GetFloat(&quot;IKRightFootWeight&quot;);
              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 &gt; 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 &gt; 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);
      }
  }
  </code></pre>