Newer
Older
TheVengeance-Project-IADE-Unity2D / Assets / Scripts / NPC / Pathfinding / Agent.cs
  1. using System.Collections;
  2. using System.Collections.Generic;
  3. using UnityEngine;
  4. using UnityEngine.EventSystems;
  5. using MyCollections.AI.Pathfinding;
  6. using Grid = MyCollections.AI.Pathfinding.Grid;
  7. public class Agent : MonoBehaviour
  8. {
  9. public float speed = 20f;
  10. public float turnSpeed = 3f;
  11. public float turnDistance = 2f;
  12. public float stoppingDistance = 10f;
  13. public const float pathRequestUpdateTime = 0.2f;
  14. public const float pathUpdateMoveThreshold = 0.2f;
  15. private Path path;
  16. private Vector2 targetDestination;
  17. [SerializeField] private bool stop;
  18. [SerializeField] private Vector2 agentDestination;
  19. [SerializeField] private Vector2 moveDirection;
  20. [SerializeField] private Vector2 velocity;
  21. [SerializeField] private float rDist;
  22. [SerializeField] private Grid grid;
  23. [SerializeField] private PathRequestManager pathRequestManager;
  24. public Vector2 TargetDestination => targetDestination;
  25. public Path Path => path;
  26. public Grid Grid => grid;
  27. public bool agentStop { get => stop; set => stop = value; }
  28. public Vector2 agentVelocity => velocity;
  29. public float remainingDistance => CalculateRemainingDistance();
  30. public Vector2 destination
  31. {
  32. get => agentDestination; set => agentDestination = value;
  33. }
  34. private void Awake()
  35. {
  36. agentDestination = Vector2.zero;
  37. velocity = Vector2.zero;
  38. stop = agentVelocity.normalized.magnitude == 0 ? true : false;
  39. }
  40. private void Start()
  41. {
  42. StartCoroutine(UpdatePath());
  43. }
  44. private void OnEnable()
  45. {
  46. agentDestination = Vector2.zero;
  47. velocity = Vector2.zero;
  48. moveDirection = Vector2.zero;
  49. path = null;
  50. stop = agentVelocity.normalized.magnitude == 0 ? true : false;
  51. StartCoroutine(UpdatePath());
  52. }
  53. private void Update()
  54. {
  55. rDist = CalculateRemainingDistance();
  56. }
  57. public void OnPathFound(Vector2[] waypoints, bool pathSuccessful)
  58. {
  59. if (pathSuccessful)
  60. {
  61. //Debug.Log($"WAYPOINTS: {waypoints.Length}");
  62. path = new Path(waypoints, transform.position, turnDistance, stoppingDistance);
  63. StopCoroutine("FollowPath");
  64. StartCoroutine("FollowPath");
  65. }
  66. else
  67. {
  68. Debug.Log("Path is not successfull!");
  69. }
  70. }
  71. private IEnumerator UpdatePath()
  72. {
  73. while (true)
  74. {
  75. if (agentDestination != Vector2.zero)
  76. {
  77. if (Time.timeSinceLevelLoad < 0.3f)
  78. {
  79. yield return new WaitForSeconds(.3f);
  80. }
  81. pathRequestManager.RequestPath(new PathRequest(transform.position, agentDestination, OnPathFound));
  82. float sqrMoveThreshold = pathUpdateMoveThreshold * pathUpdateMoveThreshold;
  83. Vector2 destinationOldPos = agentDestination;
  84. while (agentDestination != Vector2.zero)
  85. {
  86. yield return new WaitForSeconds(pathRequestUpdateTime);
  87. if ((agentDestination - destinationOldPos).sqrMagnitude > sqrMoveThreshold)
  88. {
  89. pathRequestManager.RequestPath(new PathRequest(transform.position, agentDestination, OnPathFound));
  90. destinationOldPos = agentDestination;
  91. }
  92. }
  93. }
  94. // Wait for a short time before checking the destination again
  95. yield return new WaitForSeconds(0.2f);
  96. }
  97. }
  98. private float CalculateRemainingDistance()
  99. {
  100. if (path == null || path.lookPoints == null || path.lookPoints.Length == 0)
  101. {
  102. return 0f;
  103. }
  104. float distance = 0f;
  105. Vector2 currentPosition = transform.position;
  106. // Calculate distance from current position to the next path point
  107. if (path.turnBoundaries.Length > 0)
  108. {
  109. distance = Vector2.Distance(currentPosition, path.lookPoints[path.turnBoundaries.Length - 1]);
  110. }
  111. // Add distances between all remaining path points
  112. for (int i = path.turnBoundaries.Length - 1; i < path.lookPoints.Length - 1; i++)
  113. {
  114. distance += Vector2.Distance(path.lookPoints[i], path.lookPoints[i + 1]);
  115. }
  116. return distance;
  117. }
  118. private IEnumerator FollowPath()
  119. {
  120. bool followingPath = true;
  121. int pathIndex = 0;
  122. Vector2 previousPosition = transform.position; // Store the previous position
  123. float speedPercent = 1f;
  124. while (followingPath)
  125. {
  126. if (stop)
  127. {
  128. yield return null;
  129. continue;
  130. }
  131. Vector2 position = new Vector2(transform.position.x, transform.position.y);
  132. while (path.turnBoundaries[pathIndex].HasCrossedLine(position))
  133. {
  134. if (pathIndex == path.finishLineIndex)
  135. {
  136. followingPath = false;
  137. break;
  138. }
  139. else
  140. {
  141. pathIndex++;
  142. }
  143. }
  144. if (followingPath)
  145. {
  146. CalculateRemainingDistance();
  147. if (pathIndex >= path.slowDownIndex && stoppingDistance > 0)
  148. {
  149. speedPercent = Mathf.Clamp01(path.turnBoundaries[path.finishLineIndex].DistanceFromPoint(position) / stoppingDistance);
  150. if (speedPercent < 0.01f)
  151. {
  152. followingPath = false;
  153. }
  154. }
  155. Vector2 targetDirection = (path.lookPoints[pathIndex] - position).normalized;
  156. moveDirection = Vector2.Lerp(moveDirection, targetDirection, Time.deltaTime * turnSpeed);
  157. // Update position
  158. position += moveDirection * speed * speedPercent * Time.deltaTime;
  159. transform.position = new Vector3(position.x, position.y, transform.position.z);
  160. // Calculate agent velocity
  161. velocity = (position - previousPosition) / Time.deltaTime; // Velocity is change in position over time
  162. previousPosition = position; // Update previous position
  163. }
  164. yield return null;
  165. }
  166. // If not following the path, ensure velocity is zero
  167. velocity = Vector2.zero;
  168. }
  169. public void SetDestination(Vector2 newDestination) => agentDestination = newDestination;
  170. private void OnDrawGizmos()
  171. {
  172. if (path != null)
  173. {
  174. path.DrawWithGizmos();
  175. }
  176. // Draw a line showing the direction the object is facing
  177. Gizmos.color = Color.red;
  178. Vector3 direction = transform.right; // Assuming the character is facing right by default
  179. Gizmos.DrawLine(transform.position, transform.position + direction * 2);
  180. }
  181. }