WaypointProgressTracker.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using System;
  2. using UnityEngine;
  3. #pragma warning disable 649
  4. namespace UnityStandardAssets.Utility
  5. {
  6. public class WaypointProgressTracker : MonoBehaviour
  7. {
  8. // This script can be used with any object that is supposed to follow a
  9. // route marked out by waypoints.
  10. // This script manages the amount to look ahead along the route,
  11. // and keeps track of progress and laps.
  12. [SerializeField] private WaypointCircuit circuit; // A reference to the waypoint-based route we should follow
  13. [SerializeField] private float lookAheadForTargetOffset = 5;
  14. // The offset ahead along the route that the we will aim for
  15. [SerializeField] private float lookAheadForTargetFactor = .1f;
  16. // A multiplier adding distance ahead along the route to aim for, based on current speed
  17. [SerializeField] private float lookAheadForSpeedOffset = 10;
  18. // The offset ahead only the route for speed adjustments (applied as the rotation of the waypoint target transform)
  19. [SerializeField] private float lookAheadForSpeedFactor = .2f;
  20. // A multiplier adding distance ahead along the route for speed adjustments
  21. [SerializeField] private ProgressStyle progressStyle = ProgressStyle.SmoothAlongRoute;
  22. // whether to update the position smoothly along the route (good for curved paths) or just when we reach each waypoint.
  23. [SerializeField] private float pointToPointThreshold = 4;
  24. // proximity to waypoint which must be reached to switch target to next waypoint : only used in PointToPoint mode.
  25. public enum ProgressStyle
  26. {
  27. SmoothAlongRoute,
  28. PointToPoint,
  29. }
  30. // these are public, readable by other objects - i.e. for an AI to know where to head!
  31. public WaypointCircuit.RoutePoint targetPoint { get; private set; }
  32. public WaypointCircuit.RoutePoint speedPoint { get; private set; }
  33. public WaypointCircuit.RoutePoint progressPoint { get; private set; }
  34. public Transform target;
  35. private float progressDistance; // The progress round the route, used in smooth mode.
  36. private int progressNum; // the current waypoint number, used in point-to-point mode.
  37. private Vector3 lastPosition; // Used to calculate current speed (since we may not have a rigidbody component)
  38. private float speed; // current speed of this object (calculated from delta since last frame)
  39. // setup script properties
  40. private void Start()
  41. {
  42. // we use a transform to represent the point to aim for, and the point which
  43. // is considered for upcoming changes-of-speed. This allows this component
  44. // to communicate this information to the AI without requiring further dependencies.
  45. // You can manually create a transform and assign it to this component *and* the AI,
  46. // then this component will update it, and the AI can read it.
  47. if (target == null)
  48. {
  49. target = new GameObject(name + " Waypoint Target").transform;
  50. }
  51. Reset();
  52. }
  53. // reset the object to sensible values
  54. public void Reset()
  55. {
  56. progressDistance = 0;
  57. progressNum = 0;
  58. if (progressStyle == ProgressStyle.PointToPoint)
  59. {
  60. target.position = circuit.Waypoints[progressNum].position;
  61. target.rotation = circuit.Waypoints[progressNum].rotation;
  62. }
  63. }
  64. private void Update()
  65. {
  66. if (progressStyle == ProgressStyle.SmoothAlongRoute)
  67. {
  68. // determine the position we should currently be aiming for
  69. // (this is different to the current progress position, it is a a certain amount ahead along the route)
  70. // we use lerp as a simple way of smoothing out the speed over time.
  71. if (Time.deltaTime > 0)
  72. {
  73. speed = Mathf.Lerp(speed, (lastPosition - transform.position).magnitude/Time.deltaTime,
  74. Time.deltaTime);
  75. }
  76. target.position =
  77. circuit.GetRoutePoint(progressDistance + lookAheadForTargetOffset + lookAheadForTargetFactor*speed)
  78. .position;
  79. target.rotation =
  80. Quaternion.LookRotation(
  81. circuit.GetRoutePoint(progressDistance + lookAheadForSpeedOffset + lookAheadForSpeedFactor*speed)
  82. .direction);
  83. // get our current progress along the route
  84. progressPoint = circuit.GetRoutePoint(progressDistance);
  85. Vector3 progressDelta = progressPoint.position - transform.position;
  86. if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
  87. {
  88. progressDistance += progressDelta.magnitude*0.5f;
  89. }
  90. lastPosition = transform.position;
  91. }
  92. else
  93. {
  94. // point to point mode. Just increase the waypoint if we're close enough:
  95. Vector3 targetDelta = target.position - transform.position;
  96. if (targetDelta.magnitude < pointToPointThreshold)
  97. {
  98. progressNum = (progressNum + 1)%circuit.Waypoints.Length;
  99. }
  100. target.position = circuit.Waypoints[progressNum].position;
  101. target.rotation = circuit.Waypoints[progressNum].rotation;
  102. // get our current progress along the route
  103. progressPoint = circuit.GetRoutePoint(progressDistance);
  104. Vector3 progressDelta = progressPoint.position - transform.position;
  105. if (Vector3.Dot(progressDelta, progressPoint.direction) < 0)
  106. {
  107. progressDistance += progressDelta.magnitude;
  108. }
  109. lastPosition = transform.position;
  110. }
  111. }
  112. private void OnDrawGizmos()
  113. {
  114. if (Application.isPlaying)
  115. {
  116. Gizmos.color = Color.green;
  117. Gizmos.DrawLine(transform.position, target.position);
  118. Gizmos.DrawWireSphere(circuit.GetRoutePosition(progressDistance), 1);
  119. Gizmos.color = Color.yellow;
  120. Gizmos.DrawLine(target.position, target.position + target.forward);
  121. }
  122. }
  123. }
  124. }