108 lines
3.1 KiB
C#
108 lines
3.1 KiB
C#
using System.Collections;
|
|
using System.Collections.Generic;
|
|
using UnityEngine;
|
|
|
|
public class IKFootSolver : MonoBehaviour
|
|
{
|
|
public bool isMovingForward;
|
|
|
|
[SerializeField] LayerMask terrainLayer = default;
|
|
[SerializeField] Transform body = default;
|
|
[SerializeField] IKFootSolver otherFoot = default;
|
|
[SerializeField] float speed = 4;
|
|
[SerializeField] float stepDistance = .2f;
|
|
[SerializeField] float stepLength = .2f;
|
|
[SerializeField] float sideStepLength = .1f;
|
|
|
|
[SerializeField] float stepHeight = .3f;
|
|
[SerializeField] Vector3 footOffset = default;
|
|
|
|
public Vector3 footRotOffset;
|
|
public float footYPosOffset = 0.1f;
|
|
|
|
public float rayStartYOffset = 0;
|
|
public float rayLength = 1.5f;
|
|
|
|
float footSpacing;
|
|
Vector3 oldPosition, currentPosition, newPosition;
|
|
Vector3 oldNormal, currentNormal, newNormal;
|
|
float lerp;
|
|
|
|
private void Start()
|
|
{
|
|
footSpacing = transform.localPosition.x;
|
|
currentPosition = newPosition = oldPosition = transform.position;
|
|
currentNormal = newNormal = oldNormal = transform.up;
|
|
lerp = 1;
|
|
}
|
|
|
|
// Update is called once per frame
|
|
|
|
void Update()
|
|
{
|
|
transform.position = currentPosition + Vector3.up * footYPosOffset;
|
|
transform.localRotation = Quaternion.Euler(footRotOffset);
|
|
|
|
Ray ray = new Ray(body.position + (body.right * footSpacing) + Vector3.up * rayStartYOffset, Vector3.down);
|
|
|
|
Debug.DrawRay(body.position + (body.right * footSpacing) + Vector3.up * rayStartYOffset, Vector3.down);
|
|
|
|
if (Physics.Raycast(ray, out RaycastHit info, rayLength, terrainLayer.value))
|
|
{
|
|
if (Vector3.Distance(newPosition, info.point) > stepDistance && !otherFoot.IsMoving() && lerp >= 1)
|
|
{
|
|
lerp = 0;
|
|
Vector3 direction = Vector3.ProjectOnPlane(info.point - currentPosition,Vector3.up).normalized;
|
|
|
|
float angle = Vector3.Angle(body.forward, body.InverseTransformDirection(direction));
|
|
|
|
isMovingForward = angle < 50 || angle > 130;
|
|
|
|
if(isMovingForward)
|
|
{
|
|
newPosition = info.point + direction * stepLength + footOffset;
|
|
newNormal = info.normal;
|
|
}
|
|
else
|
|
{
|
|
newPosition = info.point + direction * sideStepLength + footOffset;
|
|
newNormal = info.normal;
|
|
}
|
|
|
|
}
|
|
}
|
|
|
|
if (lerp < 1)
|
|
{
|
|
Vector3 tempPosition = Vector3.Lerp(oldPosition, newPosition, lerp);
|
|
tempPosition.y += Mathf.Sin(lerp * Mathf.PI) * stepHeight;
|
|
|
|
currentPosition = tempPosition;
|
|
currentNormal = Vector3.Lerp(oldNormal, newNormal, lerp);
|
|
lerp += Time.deltaTime * speed;
|
|
}
|
|
else
|
|
{
|
|
oldPosition = newPosition;
|
|
oldNormal = newNormal;
|
|
}
|
|
}
|
|
|
|
private void OnDrawGizmos()
|
|
{
|
|
|
|
Gizmos.color = Color.red;
|
|
Gizmos.DrawSphere(newPosition, 0.1f);
|
|
}
|
|
|
|
|
|
|
|
public bool IsMoving()
|
|
{
|
|
return lerp < 1;
|
|
}
|
|
|
|
|
|
|
|
}
|