AdvancedUtilities

DelayedFollow

Nov 28th, 2016
265
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C# 5.18 KB | None | 0 0
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3.  
  4. /// <summary>
  5. /// Sets the position and the rotation of this game object's transform to be the position and rotation of another object some amount of time in the past.
  6. /// </summary>
  7. public class DelayedFollow : MonoBehaviour
  8. {
  9.     [Tooltip("The time in seconds that the position and rotation will be delayed by.")]
  10.     public float Delay = 1f;
  11.  
  12.     [Tooltip("The target that this transform will follow.")]
  13.     public Transform Target;
  14.  
  15.     [Tooltip("How you want it to follow.")]
  16.     public DelayedFollowMode Mode = DelayedFollowMode.PositionAndRotation;
  17.  
  18.     [Tooltip("The position and rotation of this GameObject will snap initialize to the position and rotation of the target.")]
  19.     public bool SnapInitialize = true;
  20.  
  21.     /// <summary>
  22.     /// Stores information on the past rotation and position data.
  23.     /// </summary>
  24.     private readonly Queue<PositionAndRotation> _positionRotationData = new Queue<PositionAndRotation>();
  25.  
  26.     /// <summary>
  27.     /// Used for lerping between the time frame in the past, vs the Peek() which will be in the future
  28.     /// [_current.AtTime] -> [Time.time] -> [_positionRotationData.Peek().AtTime]
  29.     /// </summary>
  30.     private PositionAndRotation _current;
  31.  
  32.     void Start ()
  33.     {
  34.         if (Target == null)
  35.         {
  36.             Debug.LogError("There is no target on this DelayedFollow. [Object: " + name + "]");
  37.             this.enabled = false;
  38.             return;
  39.         }
  40.  
  41.         _current = new PositionAndRotation(Target);
  42.  
  43.         if (SnapInitialize)
  44.         {
  45.             switch (Mode)
  46.             {
  47.                 case DelayedFollowMode.PositionOnly:
  48.                     this.transform.position = Target.position;
  49.                     break;
  50.                 case DelayedFollowMode.RotationOnly:
  51.                     this.transform.rotation = Target.rotation;
  52.                     break;
  53.                 case DelayedFollowMode.PositionAndRotation:
  54.                     this.transform.position = Target.position;
  55.                     this.transform.rotation = Target.rotation;
  56.                     break;
  57.             }
  58.         }
  59.     }
  60.    
  61.     // Update is called once per frame
  62.     void Update ()
  63.     {
  64.         _positionRotationData.Enqueue(new PositionAndRotation(Target));
  65.  
  66.         // Don't let the Delay be negative
  67.         if (Delay < 0)
  68.         {
  69.             Delay = -Delay;
  70.         }
  71.  
  72.         // This is our adjusted time, we want the positional data for this time frame
  73.         float delayedTime = Time.time - Delay;
  74.  
  75.         while (_positionRotationData.Peek().AtTime < delayedTime)
  76.         {
  77.             _current = _positionRotationData.Dequeue();
  78.         }
  79.  
  80.         // We are still at the beginning before the delay has initially past.
  81.         if (_current.AtTime > delayedTime)
  82.         {
  83.             switch (Mode)
  84.             {
  85.                 case DelayedFollowMode.PositionOnly:
  86.                     this.transform.position = _current.Position;
  87.                     break;
  88.                 case DelayedFollowMode.RotationOnly:
  89.                     this.transform.rotation = _current.Rotation;
  90.                     break;
  91.                 case DelayedFollowMode.PositionAndRotation:
  92.                     this.transform.position = _current.Position;
  93.                     this.transform.rotation = _current.Rotation;
  94.                     break;
  95.             }
  96.         }
  97.         else
  98.         {
  99.             PositionAndRotation peek = _positionRotationData.Peek();
  100.             float t = (Time.time - _current.AtTime) / (peek.AtTime - _current.AtTime);
  101.             switch (Mode)
  102.             {
  103.                 case DelayedFollowMode.PositionOnly:
  104.                     this.transform.position = Vector3.Lerp(_current.Position, peek.Position, t);
  105.                     break;
  106.                 case DelayedFollowMode.RotationOnly:
  107.                     this.transform.rotation = Quaternion.Lerp(_current.Rotation, peek.Rotation, t);
  108.                     break;
  109.                 case DelayedFollowMode.PositionAndRotation:
  110.                     this.transform.position = Vector3.Lerp(_current.Position, peek.Position, t);
  111.                     this.transform.rotation = Quaternion.Lerp(_current.Rotation, peek.Rotation, t);
  112.                     break;
  113.             }
  114.         }
  115.     }
  116.    
  117.     /// <summary>
  118.     /// Represents the position and rotation of a transform at a given time.
  119.     /// </summary>
  120.     private class PositionAndRotation
  121.     {
  122.         /// <summary>
  123.         /// The position at the given time.
  124.         /// </summary>
  125.         public readonly Vector3 Position;
  126.  
  127.         /// <summary>
  128.         /// The rotation at the given time.
  129.         /// </summary>
  130.         public readonly Quaternion Rotation;
  131.  
  132.         /// <summary>
  133.         /// The time that this position and rotation occured at.
  134.         /// </summary>
  135.         public readonly float AtTime;
  136.  
  137.         public PositionAndRotation(Transform transform)
  138.         {
  139.             Position = transform.position;
  140.             Rotation = transform.rotation;
  141.             AtTime = Time.time;
  142.         }
  143.     }
  144.  
  145.     /// <summary>
  146.     /// How you want it to follow
  147.     /// </summary>
  148.     public enum DelayedFollowMode
  149.     {
  150.         PositionAndRotation,
  151.         PositionOnly,
  152.         RotationOnly
  153.     }
  154. }
Advertisement
Add Comment
Please, Sign In to add comment