Allrighty I think I got foot rotation based on ground worked out. It is not perfect, but should do the job. Works on both objects AND planes so long as they are tagged ground. Should be easy to swap to another identifying method other than tags though.
The planes have a bit of an odd deal with how they handle themselves so the rotation on them is really jerky atm. Can be fixed with some slerping, Also you might need to tweak some variables in the foot roll assistants to get it just right.
Replace the x,y,z of the * Quaternion.Euler at the bottom of each FootRollAsistant with the wonderful floats provided call magic1,2, and 3 for easy tweaking from the inspector. I call em magic because you really never know what is gonna happen with em, tho generally two of em mess with the roll and one changes the yaw, you shouldn’t need to worry about yaw though. That should set itself correctly automatically (if you are using this part of the code on feet).
Depending on how the bones are oriented in your model you might have to swap a right with a forward or something similar. (My cats wrist bones right is oriented to the actual right of his wrist while he is standing. Depending on bone roll, yours might be different.)
I have not tried it yet but should also be able to apply this to any other bone in your chars body (Hint hint).
Anyway here it is so far. (we still got a long way to go, but tis the reality of making a custom rig IK system.)
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class Controler : MonoBehaviour
{
public GameObject RootBone;
public Transform[] Bones;
private Animator Anim;
public float Magic3;
public float Magic2;
public float Magic1;
private Quaternion FootIkProductFL;
public Vector3 FootRollAsistantFL;
private Quaternion FootIkProductFR;
public Vector3 FootRollAsistantFR;
private Quaternion FootIkProductBL;
public Vector3 FootRollAsistantBL;
private Quaternion FootIkProductBR;
public Vector3 FootRollAsistantBR;
private void Awake()
{
Anim = GetComponent<Animator>();
List<Transform> childs = new List<Transform>();
Utilities.GetAllChildren(RootBone.transform, ref childs);
foreach (Transform t in childs)
{
Debug.Log(t.transform);
Debug.Log(t.transform.childCount + "Children");
}
Bones = childs.ToArray();
}
void Start()
{
}
private void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
Debug.Log("MySawmp");
Anim.SetInteger("Button", 1);
}
if (Input.GetKeyUp(KeyCode.Space))
{
Anim.SetInteger("Button", 0);
}
}
private void LateUpdate()
{
RaycastHit hit;
Ray IkRayFL = new Ray(Bones[36].position + Vector3.up, Vector3.down * 1);
Ray IkRayFR = new Ray(Bones[44].position + Vector3.up, Vector3.down * 1);
Ray IkRayBL = new Ray(Bones[61].position + Vector3.up, Vector3.down * 1);
Ray IkRayBR = new Ray(Bones[66].position + Vector3.up, Vector3.down * 1);
// Front Left Paw
if (Physics.Raycast(IkRayFL, out hit, 10f))
{
if (hit.transform.tag == "Ground")
{
Debug.DrawLine(hit.point, hit.point + hit.normal, Color.green);
FootIkProductFL = Quaternion.LookRotation(new Vector3(Bones[36].forward.x, Bones[36].forward.y + FootRollAsistantFL.y, Bones[36].forward.z), Vector3.Cross(Bones[36].forward, -hit.normal));
FootRollAsistantFL = Quaternion.LookRotation(Bones[36].right, Vector3.Cross(Bones[36].right, -hit.normal)) * Quaternion.Euler(new Vector3(-90, 0, 0)) * new Vector3(1, 1, 1);
Bones[36].rotation = FootIkProductFL;
}
}
//Front Right Paw
if (Physics.Raycast(IkRayFR, out hit, 10f))
{
if (hit.transform.tag == "Ground")
{
// Debug.Log(hit.point);
// Debug.Log(hit.normal);
Debug.DrawLine(hit.point, hit.point + hit.normal, Color.green);
FootIkProductFR = Quaternion.LookRotation(new Vector3(Bones[44].forward.x, Bones[44].forward.y + FootRollAsistantFR.y, Bones[44].forward.z), Vector3.Cross(Bones[44].forward, hit.normal));
FootRollAsistantFR = Quaternion.LookRotation(Bones[44].right, Vector3.Cross(Bones[44].right, -hit.normal)) * Quaternion.Euler(new Vector3(0, 0, 0)) * new Vector3(1, 1, 1);
Bones[44].rotation = FootIkProductFR;
}
}
//Back Left Paw
if (Physics.Raycast(IkRayBL, out hit, 10f))
{
if (hit.transform.tag == "Ground")
{
// Debug.Log(hit.point);
// Debug.Log(hit.normal);
Debug.DrawLine(hit.point, hit.point + hit.normal, Color.green);
FootIkProductBL = Quaternion.LookRotation(new Vector3(Bones[61].forward.x, Bones[61].forward.y + FootRollAsistantBL.y, Bones[61].forward.z), Vector3.Cross(Bones[61].forward, -hit.normal));
FootRollAsistantBL = Quaternion.LookRotation(Bones[61].right, Vector3.Cross(Bones[61].right, -hit.normal)) * Quaternion.Euler(new Vector3(0 , -70 , 0)) * new Vector3(1, 1, 1);
Bones[61].rotation = FootIkProductBL;
}
//Back Right Paw
if (Physics.Raycast(IkRayBR, out hit, 10f))
{
if (hit.transform.tag == "Ground")
{
// Debug.Log(hit.point);
// Debug.Log(hit.normal);
Debug.DrawLine(hit.point, hit.point + hit.normal, Color.green);
FootIkProductBR = Quaternion.LookRotation(new Vector3(Bones[66].forward.x, Bones[66].forward.y + FootRollAsistantBR.y, Bones[66].forward.z), Vector3.Cross(Bones[66].forward, hit.normal));
FootRollAsistantBR = Quaternion.LookRotation(-Bones[66].right, Vector3.Cross(-Bones[66].right, hit.normal)) * Quaternion.Euler(new Vector3(0 , -30, 0)) * new Vector3(1, 1, 1);
Bones[66].rotation = FootIkProductBR;
}
}
}
}
static class Utilities
{
public static void GetAllChildren(Transform parent, ref List<Transform> transforms)
{
foreach (Transform t in parent)
{
transforms.Add(t);
GetAllChildren(t, ref transforms);
}
}
}
}
I hope you can make use of some of this. Ima start messing with making the rest of the legs react to ground position. (Is gonna be tricky, but since the feet stay lvl no matter where the rest of the body goes I think I can work it out with some clamped rotation and a bit trial and error.)
EDIT: No wait, I think I missed something. The foot roll is not being effected by body roll… Darn I thought I had it there. Well, I am not messing with it more tonight. But if you have any ideas feel free to toss em out there.
No such thing as a bad idea, you would not imagine how many versions of this I went through to get here, lol.