SetIKRotation for feet on slope

The foot.transform.position.y works OK in my IK feet script, but no matter what I try, I can’t seem to get the rotation right. Here is the script:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Foot_IK : MonoBehaviour
{
    [SerializeField] private GameObject player;
    private Player_Control player_script;
    [SerializeField] private Animator foot_anim;
    [SerializeField] private Transform left_foot;
    [SerializeField] private Transform right_foot;
    [SerializeField] private CapsuleCollider capsule_collider;
    private Vector3 ref_point;
    private float final_angle;
    private RaycastHit hit;

    private float foot_ray()
    {
        if (Physics.Raycast(capsule_collider.bounds.center, -Vector3.up, out hit))
        {
            ref_point = hit.point;
            float Cos_theta = Vector3.Dot(hit.normal.normalized, player.transform.forward.normalized);
            Vector3 projection = hit.normal.normalized - (Cos_theta * player.transform.forward.normalized);
            return Vector3.Angle(projection, player.transform.right);
        }
        else
        {
            return 0f;
        }
    }

    private void OnAnimatorIK(int layerIndex)

    {
        if (player_script.grounded == true)
        {
            foot_anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1);
            foot_anim.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1);
            foot_anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
            foot_anim.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1);

            float half_dist_between_feet = (left_foot.transform.position - right_foot.transform.position).magnitude / 2f;
            float left_pos = ref_point.y - (Mathf.Tan(final_angle) * half_dist_between_feet);
            float right_pos = ref_point.y + (Mathf.Tan(final_angle) * half_dist_between_feet);

//            Quaternion leftFootRot =
//            Quaternion rightFootRot =

            foot_anim.SetIKPosition(AvatarIKGoal.LeftFoot, new Vector3(left_foot.transform.position.x, left_pos, left_foot.transform.position.z));
            foot_anim.SetIKPosition(AvatarIKGoal.RightFoot, new Vector3(right_foot.transform.position.x, right_pos, right_foot.transform.position.z));
//            foot_anim.SetIKRotation(AvatarIKGoal.LeftFoot, leftFootRot);
//            foot_anim.SetIKRotation(AvatarIKGoal.RightFoot, rightFootRot);
        }
    }

    private void LateUpdate()
    {
        final_angle = (foot_ray() - 90f) * (3.1416f / 180f);
    }

    private void Start()
    {
        player_script = player.GetComponent<Player_Control>();
    }

}

In order for it to work, the character must have both feet in the transform.up/transform.right plane (work in progress). What I can’t seem to figure out is the commented parts, i.e. the quaternions involved in the foot angles. Now I have a basic understanding of quaternions, and they are rotations, not set angles. I guess I don’t see why setAngle is not an option. Having the coordinates of feet in mechanim being wonky doesn’t help. How can I fix the commented part of the code? Any help would be greatly appreciated.

I found the following post which helped greatly, though their vector points the wrong way:

Here is the final script which works fairly well:

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Foot_IK : MonoBehaviour
{
    [SerializeField] private GameObject player;
    private Player_Control player_script;
    [SerializeField] private Animator foot_anim;
    [SerializeField] private Transform left_foot;
    [SerializeField] private Transform right_foot;
    [SerializeField] private Transform left_knee;
    [SerializeField] private CapsuleCollider capsule_collider;
    private Vector3 ref_point;
    private float final_angle;
    private RaycastHit hit;

    private float foot_ray()
    {
        if (Physics.Raycast(capsule_collider.bounds.center, -Vector3.up, out hit))
        {
            ref_point = hit.point;
            Plane plane = new Plane(left_foot.transform.position, right_foot.transform.position, left_knee.transform.position);
            float Cos_theta = Vector3.Dot(hit.normal.normalized, plane.normal.normalized); 
            Vector3 projection = hit.normal.normalized - (Cos_theta * plane.normal.normalized); 
            return Vector3.Angle(projection, player.transform.right);
        }
        else
        {
            return 0f;
        }
    }

    private void OnAnimatorIK(int layerIndex)

    {
        if (player_script.grounded == true)
        {
            foot_anim.SetIKPositionWeight(AvatarIKGoal.LeftFoot, 1);
            foot_anim.SetIKRotationWeight(AvatarIKGoal.LeftFoot, 1);
            foot_anim.SetIKPositionWeight(AvatarIKGoal.RightFoot, 1);
            foot_anim.SetIKRotationWeight(AvatarIKGoal.RightFoot, 1);

            float half_dist_between_feet = (left_foot.transform.position - right_foot.transform.position).magnitude / 2f;
            float left_pos = ref_point.y - (Mathf.Tan(final_angle) * half_dist_between_feet);
            float right_pos = ref_point.y + (Mathf.Tan(final_angle) * half_dist_between_feet);

            Vector3 slopeCorrected = -Vector3.Cross(hit.normal, player.transform.right);

            Quaternion leftFootRot = Quaternion.LookRotation(slopeCorrected, hit.normal);
            Quaternion rightFootRot = Quaternion.LookRotation(slopeCorrected, hit.normal);

            foot_anim.SetIKPosition(AvatarIKGoal.LeftFoot, new Vector3(left_foot.transform.position.x, left_pos, left_foot.transform.position.z));
            foot_anim.SetIKPosition(AvatarIKGoal.RightFoot, new Vector3(right_foot.transform.position.x, right_pos, right_foot.transform.position.z));
            foot_anim.SetIKRotation(AvatarIKGoal.LeftFoot, leftFootRot);
            foot_anim.SetIKRotation(AvatarIKGoal.RightFoot, rightFootRot);
        }
    }

    private void LateUpdate()
    {
        final_angle = (foot_ray() - 90f) * (3.1416f / 180f);
    }

    private void Start()
    {
        player_script = player.GetComponent<Player_Control>();
    }

}

Feel free to use it. The trick is to use the shin which is most affected by stance for the inspector assignment to left_knee.

I know this is an older post but I tried to implement the Foot IK into my project. It does appear to move and rotate the foot but it rotates it to always be point the toe facing straight forward. Is there a way to modify it so it takes the original positioning of the foot into account and rotates it based on that to match the ground? I will be the first to admit I know very little about Quaternion’s and rotations in general.

Thanks for any information.