123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249 |
- using UnityEngine;
- using System.Collections;
- namespace RootMotion.FinalIK {
-
-
-
- public class HitReaction : OffsetModifier {
-
-
-
- [System.Serializable]
- public abstract class HitPoint {
- [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;
- public bool inProgress { get { return timer < length; } }
- 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, Vector3 point) {
- if (length == 0f) length = GetLength();
- 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(IKSolverFullBodyBiped solver, 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(solver, weight);
- }
- protected abstract float GetLength();
- protected abstract void CrossFadeStart();
- protected abstract void OnApply(IKSolverFullBodyBiped solver, float weight);
- }
-
-
-
- [System.Serializable]
- public class HitPointEffector: HitPoint {
-
-
-
- [System.Serializable]
- public class EffectorLink {
- [Tooltip("The FBBIK effector type")]
- public FullBodyBipedEffector effector;
- [Tooltip("The weight of this effector (could also be negative)")]
- public float weight;
- private Vector3 lastValue;
- private Vector3 current;
-
- public void Apply(IKSolverFullBodyBiped solver, Vector3 offset, float crossFader) {
- current = Vector3.Lerp(lastValue, offset * weight, crossFader);
- solver.GetEffector(effector).positionOffset += current;
- }
-
- public void CrossFadeStart() {
- lastValue = current;
- }
- }
- [Tooltip("Offset magnitude in the direction of the hit force")]
- public AnimationCurve offsetInForceDirection;
- [Tooltip("Offset magnitude in the direction of character.up")]
- public AnimationCurve offsetInUpDirection;
- [Tooltip("Linking this offset to the FBBIK effectors")]
- public EffectorLink[] effectorLinks;
-
- protected override float GetLength() {
- float time1 = offsetInForceDirection.keys.Length > 0? offsetInForceDirection.keys[offsetInForceDirection.length - 1].time: 0f;
- float time2 = offsetInUpDirection.keys.Length > 0? offsetInUpDirection.keys[offsetInUpDirection.length - 1].time: 0f;
- return Mathf.Clamp(time1, time2, time1);
- }
-
- protected override void CrossFadeStart() {
- foreach (EffectorLink e in effectorLinks) e.CrossFadeStart();
- }
-
- protected override void OnApply(IKSolverFullBodyBiped solver, float weight) {
- Vector3 up = solver.GetRoot().up * force.magnitude;
- Vector3 offset = (offsetInForceDirection.Evaluate(timer) * force) + (offsetInUpDirection.Evaluate(timer) * up);
- offset *= weight;
- foreach (EffectorLink e in effectorLinks) e.Apply(solver, offset, crossFader);
- }
- }
-
-
-
- [System.Serializable]
- public class HitPointBone: HitPoint {
-
-
-
- [System.Serializable]
- public class BoneLink {
- [Tooltip("Reference to the bone that this hit point rotates")]
- public Transform bone;
- [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(IKSolverFullBodyBiped solver, Quaternion offset, float crossFader) {
- current = Quaternion.Lerp(lastValue, Quaternion.Lerp(Quaternion.identity, offset, weight), crossFader);
- bone.rotation = current * bone.rotation;
- }
-
- public void CrossFadeStart() {
- lastValue = current;
- }
- }
- [Tooltip("The angle to rotate the bone around it's rigidbody's world center of mass")]
- public AnimationCurve aroundCenterOfMass;
- [Tooltip("Linking this hit point to bone(s)")]
- public BoneLink[] boneLinks;
- private Rigidbody rigidbody;
-
- protected override float GetLength() {
- return aroundCenterOfMass.keys.Length > 0? aroundCenterOfMass.keys[aroundCenterOfMass.length - 1].time: 0f;
- }
-
- protected override void CrossFadeStart() {
- foreach (BoneLink b in boneLinks) b.CrossFadeStart();
- }
-
- protected override void OnApply(IKSolverFullBodyBiped solver, float weight) {
- if (rigidbody == null) rigidbody = collider.GetComponent<Rigidbody>();
- if (rigidbody != null) {
- Vector3 comAxis = Vector3.Cross(force, point - rigidbody.worldCenterOfMass);
- float comValue = aroundCenterOfMass.Evaluate(timer) * weight;
- Quaternion offset = Quaternion.AngleAxis(comValue, comAxis);
- foreach (BoneLink b in boneLinks) b.Apply(solver, offset, crossFader);
- }
- }
- }
- [Tooltip("Hit points for the FBBIK effectors")]
- public HitPointEffector[] effectorHitPoints;
- [Tooltip(" Hit points for bones without an effector, such as the head")]
- public HitPointBone[] boneHitPoints;
-
-
-
- public bool inProgress {
- get {
- foreach (HitPointEffector h in effectorHitPoints) {
- if (h.inProgress) return true;
- }
- foreach (HitPointBone h in boneHitPoints) {
- if (h.inProgress) return true;
- }
- return false;
- }
- }
-
- protected override void OnModifyOffset() {
- foreach (HitPointEffector e in effectorHitPoints) e.Apply(ik.solver, weight);
- foreach (HitPointBone b in boneHitPoints) b.Apply(ik.solver, weight);
- }
-
- public void Hit(Collider collider, Vector3 force, Vector3 point) {
- if (ik == null) {
- Debug.LogError("No IK assigned in HitReaction");
- return;
- }
- foreach (HitPointEffector e in effectorHitPoints) {
- if (e.collider == collider) e.Hit(force, point);
- }
- foreach (HitPointBone b in boneHitPoints) {
- if (b.collider == collider) b.Hit(force, point);
- }
- }
- }
- }
|