XRoom_Unity/Assets/VR Body/IKFootSolver.cs
2025-05-31 10:20:20 +03:30

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;
}
}