using System; using System.Collections; using UnityEngine; namespace ARLocation.Utils { public class SmoothMove : MonoBehaviour { public enum Mode { Horizontal, Full } [Tooltip("The smoothing factor."), Range(0, 1)] public float Epsilon = 0.5f; [Tooltip("The Precision."), Range(0, 0.1f)] public float Precision = 0.05f; public Vector3 Target { get { return target; } set { target = value; if (co != null) { StopCoroutine(co); } co = MoveTo(target); StartCoroutine(MoveTo(target)); } } [Tooltip("The mode. If set to 'Horizontal', will leave the y component unchanged. Full means the object will move in all 3D coordinates.")] public Mode SmoothMoveMode = Mode.Full; private Vector3 target; private Action onTargetReached; private IEnumerator co; public void Move(Vector3 to, Action callback = null) { onTargetReached = callback; Target = to; } private IEnumerator MoveTo(Vector3 pTarget) { if (SmoothMoveMode == Mode.Horizontal) { Vector2 horizontalPosition = MathUtils.HorizontalVector(transform.position); Vector2 horizontalTarget = MathUtils.HorizontalVector(pTarget); while (Vector2.Distance(horizontalPosition, horizontalTarget) > Precision) { float t = 1.0f - Mathf.Pow(Epsilon, Time.deltaTime); horizontalPosition = Vector3.Lerp(horizontalPosition, horizontalTarget, t); transform.position = MathUtils.HorizontalVectorToVector3(horizontalPosition, transform.position.y); yield return null; } transform.position = MathUtils.HorizontalVectorToVector3(horizontalTarget, transform.position.y); onTargetReached?.Invoke(); onTargetReached = null; } else { while (Vector3.Distance(transform.position, pTarget) > Precision) { float t = 1.0f - Mathf.Pow(Epsilon, Time.deltaTime); transform.position = Vector3.Lerp(transform.position, pTarget, t); yield return null; } transform.position = pTarget; onTargetReached?.Invoke(); onTargetReached = null; } } public static SmoothMove AddSmoothMove(GameObject go, float epsilon) { var smoothMove = go.AddComponent(); smoothMove.Epsilon = epsilon; return smoothMove; } } }