using UnityEngine; using FSA = UnityEngine.Serialization.FormerlySerializedAsAttribute; namespace Lean.Common { /// This component causes the current Transform to chase the specified position. [HelpURL(LeanHelper.PlusHelpUrlPrefix + "LeanChase")] [AddComponentMenu(LeanHelper.ComponentPathPrefix + "Chase")] public class LeanChase : MonoBehaviour { /// The transform that will be chased. public Transform Destination { set { destination = value; } get { return destination; } } [FSA("Destination")] public Transform destination; /// If Target is set, then this allows you to set the offset in local space. public Vector3 DestinationOffset { set { destinationOffset = value; } get { return destinationOffset; } } [FSA("DestinationOffset")] [SerializeField] protected Vector3 destinationOffset; /// The world space position that will be followed. /// NOTE: If Destination is set, then this value will be overridden. public Vector3 Position { set { position = value; } get { return position; } } [FSA("Position")] [SerializeField] protected Vector3 position; /// The world space offset that will be followed. public Vector3 Offset { set { offset = value; } get { return offset; } } [FSA("Offset")] [SerializeField] protected Vector3 offset; /// This allows you to control how quickly this Transform moves to the target position. /// -1 = Instantly change. /// 0 = No change. /// 1 = Slowly change. /// 10 = Quickly change. public float Damping { set { damping = value; } get { return damping; } } [FSA("Dampening")] [FSA("Damping")] [SerializeField] private float damping = -1.0f; /// This allows you to control how quickly this Transform linearly moves to the target position. /// 0 = No linear movement. /// 1 = One linear position per second. public float Linear { set { linear = value; } get { return linear; } } [FSA("Linear")] [SerializeField] private float linear; /// Ignore Z for 2D? public bool IgnoreZ { set { ignoreZ = value; } get { return ignoreZ; } } [FSA("IgnoreZ")] [SerializeField] protected bool ignoreZ; /// Should the chase keep updating, even if you haven't called the SetPosition method this frame? public bool Continuous { set { continuous = value; } get { return continuous; } } [FSA("Continuous")] [SerializeField] protected bool continuous; /// Automatically set the Position value to the transform.position in Start? public bool SetPositionOnStart { set { setPositionOnStart = value; } get { return setPositionOnStart; } } [FSA("SetPositionOnStart")] [SerializeField] private bool setPositionOnStart = true; [System.NonSerialized] protected bool positionSet; /// This method will override the Position value based on the specified value. public virtual void SetPosition(Vector3 newPosition) { destination = null; position = newPosition; positionSet = true; } /// This method will immediately move this Transform to the target position. [ContextMenu("Snap To Position")] public void SnapToPosition() { UpdatePosition(-1.0f, 0.0f); } protected virtual void Start() { if (setPositionOnStart == true) { position = transform.position; } } protected virtual void Update() { UpdatePosition(damping, linear); } protected virtual void UpdatePosition(float damping, float linear) { if (positionSet == true || continuous == true) { if (destination != null) { position = destination.TransformPoint(destinationOffset); } var currentPosition = transform.position; var targetPosition = position + offset; if (ignoreZ == true) { targetPosition.z = currentPosition.z; } // Get t value var factor = LeanHelper.GetDampenFactor(damping, Time.deltaTime); // Move current value to the target one currentPosition = Vector3.Lerp(currentPosition, targetPosition, factor); currentPosition = Vector3.MoveTowards(currentPosition, targetPosition, linear * Time.deltaTime); // Apply new point transform.position = currentPosition; positionSet = false; } } } } #if UNITY_EDITOR namespace Lean.Common.Editor { using TARGET = LeanChase; [UnityEditor.CanEditMultipleObjects] [UnityEditor.CustomEditor(typeof(TARGET))] public class LeanChase_Editor : LeanEditor { protected override void OnInspector() { TARGET tgt; TARGET[] tgts; GetTargets(out tgt, out tgts); Draw("destination", "The transform that will be chased."); Draw("destinationOffset", "If Target is set, then this allows you to set the offset in local space."); Separator(); Draw("position", "The world space position that will be followed.\n\nNOTE: If Destination is set, then this value will be overridden."); Draw("offset", "The world space offset that will be followed."); Separator(); Draw("damping", "This allows you to control how quickly this Transform moves to the target position.\n\n-1 = Instantly change.\n\n0 = No change.\n\n1 = Slowly change.\n\n10 = Quickly change."); Draw("linear", "This allows you to control how quickly this Transform linearly moves to the target position.\n\n0 = No linear movement.\n\n1 = One linear position per second."); Draw("ignoreZ", "Ignore Z for 2D?"); Draw("continuous", "Should the chase keep updating, even if you haven't called the SetPosition method this frame?"); Draw("setPositionOnStart", "Automatically set the Position value to the transform.position in Start?"); } } } #endif