holopy3/Assets/Plugins/RootMotion/FinalIK/IK Solvers/IKSolverVRFootstep.cs
2020-12-10 15:25:12 +01:00

89 lines
3.2 KiB
C#

using UnityEngine;
using System.Collections;
using UnityEngine.Events;
namespace RootMotion.FinalIK {
public partial class IKSolverVR: IKSolver {
[System.Serializable]
public class Footstep {
public float stepSpeed = 3f;
public Vector3 characterSpaceOffset;
public Vector3 position;
public Quaternion rotation = Quaternion.identity;
public Quaternion stepToRootRot = Quaternion.identity;
public bool isStepping { get { return stepProgress < 1f; }}
public bool isSupportLeg;
public float stepProgress { get; private set; }
public Vector3 stepFrom;
public Vector3 stepTo;
public Quaternion stepFromRot = Quaternion.identity;
public Quaternion stepToRot = Quaternion.identity;
private Quaternion footRelativeToRoot = Quaternion.identity;
private float supportLegW;
private float supportLegWV;
public Footstep (Quaternion rootRotation, Vector3 footPosition, Quaternion footRotation, Vector3 characterSpaceOffset) {
this.characterSpaceOffset = characterSpaceOffset;
Reset(rootRotation, footPosition, footRotation);
footRelativeToRoot = Quaternion.Inverse(rootRotation) * rotation;
}
public void Reset(Quaternion rootRotation, Vector3 footPosition, Quaternion footRotation) {
position = footPosition;
rotation = footRotation;
stepFrom = position;
stepTo = position;
stepFromRot = rotation;
stepToRot = rotation;
stepToRootRot = rootRotation;
stepProgress = 1f;
}
public void StepTo(Vector3 p, Quaternion rootRotation, float stepThreshold) {
if (Vector3.Magnitude(p - stepTo) < stepThreshold && Quaternion.Angle(rootRotation, stepToRootRot) < 25f) return;
stepFrom = position;
stepTo = p;
stepFromRot = rotation;
stepToRootRot = rootRotation;
stepToRot = rootRotation * footRelativeToRoot;
stepProgress = 0f;
}
public void UpdateStepping(Vector3 p, Quaternion rootRotation, float speed) {
stepTo = Vector3.Lerp (stepTo, p, Time.deltaTime * speed);
stepToRot = Quaternion.Lerp (stepToRot, rootRotation * footRelativeToRoot, Time.deltaTime * speed);
stepToRootRot = stepToRot * Quaternion.Inverse(footRelativeToRoot);
}
public void UpdateStanding(Quaternion rootRotation, float minAngle, float speed) {
if (speed <= 0f || minAngle >= 180f) return;
Quaternion r = rootRotation * footRelativeToRoot;
float angle = Quaternion.Angle (rotation, r);
if (angle > minAngle) rotation = Quaternion.RotateTowards (rotation, r, Mathf.Min (Time.deltaTime * speed * (1f - supportLegW), angle -minAngle));
}
public void Update(InterpolationMode interpolation, UnityEvent onStep) {
float supportLegWTarget = isSupportLeg ? 1f : 0f;
supportLegW = Mathf.SmoothDamp (supportLegW, supportLegWTarget, ref supportLegWV, 0.2f);
if (!isStepping) return;
stepProgress = Mathf.MoveTowards(stepProgress, 1f, Time.deltaTime * stepSpeed);
if (stepProgress >= 1f) onStep.Invoke ();
float stepProgressSmooth = RootMotion.Interp.Float(stepProgress, interpolation);
position = Vector3.Lerp(stepFrom, stepTo, stepProgressSmooth);
rotation = Quaternion.Lerp(stepFromRot, stepToRot, stepProgressSmooth);
}
}
}
}