123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151 |
- using UnityEngine;
- using System.Collections;
- namespace RootMotion.FinalIK {
- public class LookAtController : MonoBehaviour {
- public LookAtIK ik;
- [Header("Target Smoothing")]
- [Tooltip("The target to look at. Do not use the Target transform that is assigned to LookAtIK. Set to null if you wish to stop looking.")]
- public Transform target;
- [Range(0f, 1f)] public float weight = 1f;
- public Vector3 offset;
- [Tooltip("The time it takes to switch targets.")]
- public float targetSwitchSmoothTime = 0.3f;
- [Tooltip("The time it takes to blend in/out of LookAtIK weight.")]
- public float weightSmoothTime = 0.3f;
- [Header("Turning Towards The Target")]
- [Tooltip("Enables smooth turning towards the target according to the parameters under this header.")]
- public bool smoothTurnTowardsTarget = true;
- [Tooltip("Speed of turning towards the target using Vector3.RotateTowards.")]
- public float maxRadiansDelta = 3f;
- [Tooltip("Speed of moving towards the target using Vector3.RotateTowards.")]
- public float maxMagnitudeDelta = 3f;
- [Tooltip("Speed of slerping towards the target.")]
- public float slerpSpeed = 3f;
- [Tooltip("The position of the pivot that the look at target is rotated around relative to the root of the character.")]
- public Vector3 pivotOffsetFromRoot = Vector3.up;
- [Tooltip("Minimum distance of looking from the first bone. Keeps the solver from failing if the target is too close.")]
- public float minDistance = 1f;
- [Header("RootRotation")]
- [Tooltip("Character root will be rotate around the Y axis to keep root forward within this angle from the look direction.")]
- [Range(0f, 180f)]
- public float maxRootAngle = 45f;
- private Transform lastTarget;
- private float switchWeight, switchWeightV;
- private float weightV;
- private Vector3 lastPosition;
- private Vector3 dir;
- private bool lastSmoothTowardsTarget;
- void Start() {
- lastPosition = ik.solver.IKPosition;
- dir = ik.solver.IKPosition - pivot;
- }
- void LateUpdate () {
-
- if (target != lastTarget) {
- if (lastTarget == null && target != null && ik.solver.IKPositionWeight <= 0f) {
- lastPosition = target.position;
- dir = target.position - pivot;
- ik.solver.IKPosition = target.position + offset;
- } else {
- lastPosition = ik.solver.IKPosition;
- dir = ik.solver.IKPosition - pivot;
- }
- switchWeight = 0f;
- lastTarget = target;
- }
-
- float targetWeight = target != null ? weight : 0f;
- ik.solver.IKPositionWeight = Mathf.SmoothDamp(ik.solver.IKPositionWeight, targetWeight, ref weightV, weightSmoothTime);
- if (ik.solver.IKPositionWeight >= 0.999f && targetWeight > ik.solver.IKPositionWeight) ik.solver.IKPositionWeight = 1f;
- if (ik.solver.IKPositionWeight <= 0.001f && targetWeight < ik.solver.IKPositionWeight) ik.solver.IKPositionWeight = 0f;
- if (ik.solver.IKPositionWeight <= 0f) return;
-
- switchWeight = Mathf.SmoothDamp(switchWeight, 1f, ref switchWeightV, targetSwitchSmoothTime);
- if (switchWeight >= 0.999f) switchWeight = 1f;
- if (target != null) {
- ik.solver.IKPosition = Vector3.Lerp(lastPosition, target.position + offset, switchWeight);
- }
-
- if (smoothTurnTowardsTarget != lastSmoothTowardsTarget) {
- dir = ik.solver.IKPosition - pivot;
- lastSmoothTowardsTarget = smoothTurnTowardsTarget;
- }
- if (smoothTurnTowardsTarget) {
- Vector3 targetDir = ik.solver.IKPosition - pivot;
- dir = Vector3.Slerp(dir, targetDir, Time.deltaTime * slerpSpeed);
- dir = Vector3.RotateTowards(dir, targetDir, Time.deltaTime * maxRadiansDelta, maxMagnitudeDelta);
- ik.solver.IKPosition = pivot + dir;
- }
-
- ApplyMinDistance();
-
- RootRotation();
- }
-
- private Vector3 pivot {
- get {
- return ik.transform.position + ik.transform.rotation * pivotOffsetFromRoot;
- }
- }
-
- void ApplyMinDistance() {
- Vector3 aimFrom = pivot;
- Vector3 direction = (ik.solver.IKPosition - aimFrom);
- direction = direction.normalized * Mathf.Max(direction.magnitude, minDistance);
-
- ik.solver.IKPosition = aimFrom + direction;
- }
-
- private void RootRotation() {
- float max = Mathf.Lerp(180f, maxRootAngle, ik.solver.IKPositionWeight);
- if (max < 180f) {
- Vector3 faceDirLocal = Quaternion.Inverse(ik.transform.rotation) * (ik.solver.IKPosition - pivot);
- float angle = Mathf.Atan2(faceDirLocal.x, faceDirLocal.z) * Mathf.Rad2Deg;
- float rotation = 0f;
- if (angle > max) {
- rotation = angle - max;
- }
- if (angle < -max) {
- rotation = angle + max;
- }
- ik.transform.rotation = Quaternion.AngleAxis(rotation, ik.transform.up) * ik.transform.rotation;
- }
- }
- }
- }
|