namespace Zinnia.Tracking.Follow.Modifier.Property { using UnityEngine; using UnityEngine.Events; using Zinnia.Extension; public abstract class SmoothedRestrictableTransformPropertyModifier : RestrictableTransformPropertyModifier { [Header("Smoothing Settings")] [Tooltip("The tolereance to consider the source and target property equal.")] [SerializeField] private float equalityTolerance = float.Epsilon; /// /// The tolereance to consider the source and target property equal. /// public float EqualityTolerance { get { return equalityTolerance; } set { equalityTolerance = value; } } [Tooltip("The approximate duration of transition for the smoothing operation.")] [SerializeField] private float transitionDuration = 0f; /// /// The approximate duration of transition for the smoothing operation. /// public float TransitionDuration { get { return transitionDuration; } set { transitionDuration = value; } } [Tooltip("The maximum speed the object can move between the smoothed distances.")] [SerializeField] private float maxSpeed = Mathf.Infinity; /// /// The maximum speed the object can move between the smoothed distances. /// public float MaxSpeed { get { return maxSpeed; } set { maxSpeed = value; } } [Header("Smoothing Events")] /// /// Emitted when the smoothing transition has completed. /// public UnityEvent Transitioned = new UnityEvent(); /// /// The reference to the output velocity. /// public Vector3 Velocity => velocity; private Vector3 velocity; /// /// The reference to the output angulaer velocity. /// public Quaternion AngularVelocity => angularVelocity; private Quaternion angularVelocity; /// /// Whether the velocity is currently being smoothed. /// protected bool isVelocitySmoothing; /// /// Whether the angular velocity is currently being smoothed. /// protected bool isAngularVelocitySmoothing; /// /// Gradually changes a towards a desired goal over time. /// /// The current position. /// The position we are trying to reach. /// The smoothed value. protected virtual Vector3 Smooth(Vector3 current, Vector3 final) { if (TransitionDuration.ApproxEquals(0f) || current.ApproxEquals(final, EqualityTolerance)) { if (isVelocitySmoothing) { Transitioned?.Invoke(); } isVelocitySmoothing = false; return final; } isVelocitySmoothing = true; return Vector3.SmoothDamp(current, final, ref velocity, TransitionDuration, MaxSpeed, Time.deltaTime); } /// /// Gradually changes a towards a desired goal over time. /// /// The current position. /// The position we are trying to reach. /// The smoothed value. protected virtual Quaternion Smooth(Quaternion current, Quaternion final) { if (TransitionDuration.ApproxEquals(0f) || current.ApproxEquals(final, EqualityTolerance)) { if (isAngularVelocitySmoothing) { Transitioned?.Invoke(); } isAngularVelocitySmoothing = false; return final; } isAngularVelocitySmoothing = true; return QuaternionExtensions.SmoothDamp(current, final, ref angularVelocity, TransitionDuration); } } }