123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239 |
- using UnityEngine;
- using System.Collections;
- namespace RootMotion.FinalIK {
-
-
-
- public class HitReactionVRIK : OffsetModifierVRIK {
- public AnimationCurve[] offsetCurves;
-
-
-
- [System.Serializable]
- public abstract class Offset {
- [Tooltip("Just for visual clarity, not used at all")]
- public string name;
- [Tooltip("Linking this hit point to a collider")]
- public Collider collider;
- [Tooltip("Only used if this hit point gets hit when already processing another hit")]
- [SerializeField] float crossFadeTime = 0.1f;
- protected float crossFader { get; private set; }
- protected float timer { get; private set; }
- protected Vector3 force { get; private set; }
- protected Vector3 point { get; private set; }
- private float length;
- private float crossFadeSpeed;
- private float lastTime;
-
- public void Hit(Vector3 force, AnimationCurve[] curves, Vector3 point) {
- if (length == 0f) length = GetLength(curves);
- if (length <= 0f) {
- Debug.LogError("Hit Point WeightCurve length is zero.");
- return;
- }
-
- if (timer < 1f) crossFader = 0f;
- crossFadeSpeed = crossFadeTime > 0f? 1f / crossFadeTime: 0f;
- CrossFadeStart();
-
- timer = 0f;
-
- this.force = force;
- this.point = point;
- }
-
- public void Apply(VRIK ik, AnimationCurve[] curves, float weight) {
- float deltaTime = Time.time - lastTime;
- lastTime = Time.time;
- if (timer >= length) {
- return;
- }
-
- timer = Mathf.Clamp(timer + deltaTime, 0f, length);
-
- if (crossFadeSpeed > 0f) crossFader = Mathf.Clamp(crossFader + (deltaTime * crossFadeSpeed), 0f, 1f);
- else crossFader = 1f;
-
- OnApply(ik, curves, weight);
- }
- protected abstract float GetLength(AnimationCurve[] curves);
- protected abstract void CrossFadeStart();
- protected abstract void OnApply(VRIK ik, AnimationCurve[] curves, float weight);
- }
-
-
-
- [System.Serializable]
- public class PositionOffset: Offset {
-
-
-
- [System.Serializable]
- public class PositionOffsetLink {
- [Tooltip("The FBBIK effector type")]
- public IKSolverVR.PositionOffset positionOffset;
- [Tooltip("The weight of this effector (could also be negative)")]
- public float weight;
- private Vector3 lastValue;
- private Vector3 current;
-
- public void Apply(VRIK ik, Vector3 offset, float crossFader) {
- current = Vector3.Lerp(lastValue, offset * weight, crossFader);
- ik.solver.AddPositionOffset(positionOffset, current);
- }
-
- public void CrossFadeStart() {
- lastValue = current;
- }
- }
- [Tooltip("Offset magnitude in the direction of the hit force")]
- public int forceDirCurveIndex;
- [Tooltip("Offset magnitude in the direction of character.up")]
- public int upDirCurveIndex = 1;
- [Tooltip("Linking this offset to the VRIK position offsets")]
- public PositionOffsetLink[] offsetLinks;
-
- protected override float GetLength(AnimationCurve[] curves) {
- float time1 = curves[forceDirCurveIndex].keys.Length > 0? curves[forceDirCurveIndex].keys[curves[forceDirCurveIndex].length - 1].time: 0f;
- float time2 = curves[upDirCurveIndex].keys.Length > 0? curves[upDirCurveIndex].keys[curves[upDirCurveIndex].length - 1].time: 0f;
- return Mathf.Clamp(time1, time2, time1);
- }
-
- protected override void CrossFadeStart() {
- foreach (PositionOffsetLink l in offsetLinks) l.CrossFadeStart();
- }
-
- protected override void OnApply(VRIK ik, AnimationCurve[] curves, float weight) {
- Vector3 up = ik.transform.up * force.magnitude;
- Vector3 offset = (curves[forceDirCurveIndex].Evaluate(timer) * force) + (curves[upDirCurveIndex].Evaluate(timer) * up);
- offset *= weight;
- foreach (PositionOffsetLink l in offsetLinks) l.Apply(ik, offset, crossFader);
- }
- }
-
-
-
- [System.Serializable]
- public class RotationOffset: Offset {
-
-
-
- [System.Serializable]
- public class RotationOffsetLink {
- [Tooltip("Reference to the bone that this hit point rotates")]
- public IKSolverVR.RotationOffset rotationOffset;
- [Tooltip("Weight of rotating the bone")]
- [Range(0f, 1f)] public float weight;
- private Quaternion lastValue = Quaternion.identity;
- private Quaternion current = Quaternion.identity;
-
- public void Apply(VRIK ik, Quaternion offset, float crossFader) {
- current = Quaternion.Lerp(lastValue, Quaternion.Lerp(Quaternion.identity, offset, weight), crossFader);
- ik.solver.AddRotationOffset(rotationOffset, current);
- }
-
- public void CrossFadeStart() {
- lastValue = current;
- }
- }
- [Tooltip("The angle to rotate the bone around it's rigidbody's world center of mass")]
- public int curveIndex;
- [Tooltip("Linking this hit point to bone(s)")]
- public RotationOffsetLink[] offsetLinks;
- private Rigidbody rigidbody;
-
- protected override float GetLength(AnimationCurve[] curves) {
- return curves[curveIndex].keys.Length > 0? curves[curveIndex].keys[ curves[curveIndex].length - 1].time: 0f;
- }
-
- protected override void CrossFadeStart() {
- foreach (RotationOffsetLink l in offsetLinks) l.CrossFadeStart();
- }
-
- protected override void OnApply(VRIK ik, AnimationCurve[] curves, float weight) {
- if (collider == null) {
- Debug.LogError ("No collider assigned for a HitPointBone in the HitReaction component.");
- return;
- }
- if (rigidbody == null) rigidbody = collider.GetComponent<Rigidbody>();
- if (rigidbody != null) {
- Vector3 comAxis = Vector3.Cross(force, point - rigidbody.worldCenterOfMass);
- float comValue = curves[curveIndex].Evaluate(timer) * weight;
- Quaternion offset = Quaternion.AngleAxis(comValue, comAxis);
- foreach (RotationOffsetLink l in offsetLinks) l.Apply(ik, offset, crossFader);
- }
- }
- }
- [Tooltip("Hit points for the FBBIK effectors")]
- public PositionOffset[] positionOffsets;
- [Tooltip(" Hit points for bones without an effector, such as the head")]
- public RotationOffset[] rotationOffsets;
-
- protected override void OnModifyOffset() {
- foreach (PositionOffset p in positionOffsets) p.Apply(ik, offsetCurves, weight);
- foreach (RotationOffset r in rotationOffsets) r.Apply(ik, offsetCurves, weight);
- }
-
- public void Hit(Collider collider, Vector3 force, Vector3 point) {
- if (ik == null) {
- Debug.LogError("No IK assigned in HitReaction");
- return;
- }
- foreach (PositionOffset p in positionOffsets) {
- if (p.collider == collider) p.Hit(force, offsetCurves, point);
- }
- foreach (RotationOffset r in rotationOffsets) {
- if (r.collider == collider) r.Hit(force, offsetCurves, point);
- }
- }
- }
- }
|