Guest User

Untitled

a guest
Jan 3rd, 2018
187
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 8.14 KB | None | 0 0
  1. using UnityEngine;
  2. using System.Collections;
  3. using System.Collections.Generic;
  4. using Pathfinding.RVO;
  5.  
  6. namespace Pathfinding.RVO
  7. {
  8. /* [HelpURL("http://arongranberg.com/astar/docs/class_pathfinding_1_1_examples_1_1_r_v_o_example_agent.php")]*/
  9.  
  10. [RequireComponent(typeof(RVOController))]
  11. [RequireComponent(typeof(Seeker))]
  12. public class RVOUnitSimplePathMovement : MonoBehaviour,IRVOMovement
  13. {
  14.  
  15. #region variables
  16. public float repathRate = 1;
  17.  
  18. private float nextRepath = 0;
  19.  
  20. private Vector3 target;
  21. private bool canSearchAgain = true;
  22.  
  23. private RVOController controller;
  24. public float maxSpeed = 10;
  25.  
  26. private Path path = null;
  27.  
  28. private List<Vector3> vectorPath;
  29. private int wp;
  30.  
  31. public float moveNextDist = 1;
  32. public float slowdownDistance = 1;
  33. public LayerMask groundMask;
  34.  
  35. private Seeker seeker;
  36.  
  37. // Vlad's extra edit
  38. public float rotationSpeed = 200.0f;
  39. // private float _initialMaxSpeed;
  40. // private bool _isSlownDown = false;
  41. // private float _minRotationAngle = 46;
  42. #endregion variables
  43.  
  44.  
  45.  
  46. #region init
  47. public void Awake()
  48. {
  49. seeker = GetComponent<Seeker>();
  50. controller = GetComponent<RVOController>();
  51. }
  52.  
  53. public virtual void Start()
  54. {
  55. // _initialMaxSpeed = maxSpeed;
  56. }
  57.  
  58. /** Set the point to move to */
  59. public void SetTarget(Vector3 target)
  60. {
  61. this.target = target;
  62. RecalculatePath();
  63. }
  64. #endregion init
  65.  
  66.  
  67. #region on path find
  68. public void RecalculatePath()
  69. {
  70. canSearchAgain = false;
  71. nextRepath = Time.time + repathRate * (Random.value + 0.5f);
  72. seeker.StartPath(transform.position, target, OnPathComplete);
  73. }
  74.  
  75. public void OnPathComplete(Path _p)
  76. {
  77. ABPath p = _p as ABPath;
  78.  
  79. canSearchAgain = true;
  80.  
  81. if (path != null) path.Release(this);
  82. path = p;
  83. p.Claim(this);
  84.  
  85. if (p.error)
  86. {
  87. wp = 0;
  88. vectorPath = null;
  89. return;
  90. }
  91.  
  92.  
  93. Vector3 p1 = p.originalStartPoint;
  94. Vector3 p2 = transform.position;
  95. p1.y = p2.y;
  96. float d = (p2 - p1).magnitude;
  97. wp = 0;
  98.  
  99. vectorPath = p.vectorPath;
  100. Vector3 waypoint;
  101.  
  102. if (moveNextDist > 0)
  103. {
  104. for (float t = 0; t <= d; t += moveNextDist * 0.6f)
  105. {
  106. wp--;
  107. Vector3 pos = p1 + (p2 - p1) * t;
  108.  
  109. do
  110. {
  111. wp++;
  112. waypoint = vectorPath[wp];
  113. } while (controller.To2D(pos - waypoint).sqrMagnitude < moveNextDist * moveNextDist && wp != vectorPath.Count - 1);
  114. }
  115. }
  116. }
  117. #endregion on path find
  118.  
  119.  
  120.  
  121. #region update
  122. public void Update()
  123. {
  124. if (Time.time >= nextRepath && canSearchAgain)
  125. {
  126. RecalculatePath();
  127. }
  128.  
  129. Vector3 pos = transform.position;
  130.  
  131. if (vectorPath != null && vectorPath.Count != 0)
  132. {
  133. while ((controller.To2D(pos - vectorPath[wp]).sqrMagnitude < moveNextDist * moveNextDist && wp != vectorPath.Count - 1) || wp == 0)
  134. {
  135. wp++;
  136. }
  137.  
  138. // Current path segment goes from vectorPath[wp-1] to vectorPath[wp]
  139. // We want to find the point on that segment that is 'moveNextDist' from our current position.
  140. // This can be visualized as finding the intersection of a circle with radius 'moveNextDist'
  141. // centered at our current position with that segment.
  142. var p1 = vectorPath[wp - 1];
  143. var p2 = vectorPath[wp];
  144.  
  145. // Calculate the intersection with the circle. This involves some math.
  146. var t = VectorMath.LineCircleIntersectionFactor(controller.To2D(transform.position), controller.To2D(p1), controller.To2D(p2), moveNextDist);
  147. // Clamp to a point on the segment
  148. t = Mathf.Clamp01(t);
  149. Vector3 waypoint = Vector3.Lerp(p1, p2, t);
  150.  
  151. // Calculate distance to the end of the path
  152. float remainingDistance = controller.To2D(waypoint - pos).magnitude + controller.To2D(waypoint - p2).magnitude;
  153. for (int i = wp; i < vectorPath.Count - 1; i++) remainingDistance += controller.To2D(vectorPath[i + 1] - vectorPath[i]).magnitude;
  154.  
  155. // Set the target to a point in the direction of the current waypoint at a distance
  156. // equal to the remaining distance along the path. Since the rvo agent assumes that
  157. // it should stop when it reaches the target point, this will produce good avoidance
  158. // behavior near the end of the path. When not close to the end point it will act just
  159. // as being commanded to move in a particular direction, not toward a particular point
  160. var rvoTarget = (waypoint - pos).normalized * remainingDistance + pos;
  161. // When within [slowdownDistance] units from the target, use a progressively lower speed
  162. var desiredSpeed = Mathf.Clamp01(remainingDistance / slowdownDistance) * maxSpeed;
  163. Debug.DrawLine(transform.position, waypoint, Color.red);
  164. controller.SetTarget(rvoTarget, desiredSpeed, maxSpeed);
  165. } else {
  166. // Stand still
  167. controller.SetTarget(pos, maxSpeed, maxSpeed);
  168. }
  169.  
  170. // Get a processed movement delta from the rvo controller and move the character.
  171. // This is based on information from earlier frames.
  172. var movementDelta = controller.CalculateMovementDelta(Time.deltaTime);
  173. AdjustSpeedOnRotation(movementDelta);
  174.  
  175. /*float crtAng = RotateInThisDirection(movementDelta);
  176. float targetAng = Mathf.Atan2(movementDelta.y, movementDelta.x) * Mathf.Rad2Deg;
  177. if (targetAng < 0) { targetAng += 360; }
  178. float outComeAngle = Mathf.Abs(targetAng - crtAng);
  179.  
  180. if (outComeAngle < _minRotationAngle || (360 - outComeAngle) < _minRotationAngle)
  181. {
  182. if (_isSlownDown)
  183. {
  184. _isSlownDown = false;
  185. maxSpeed = _initialMaxSpeed;
  186. }
  187. } else {
  188. if (!_isSlownDown)
  189. {
  190. _isSlownDown = true;
  191. maxSpeed = 0.1f;
  192. }
  193. }*/
  194.  
  195.  
  196. pos += movementDelta;
  197.  
  198. // Rotate the character if the velocity is not extremely small
  199. if (controller.movementPlane == MovementPlane.XZ)
  200. {
  201. RaycastHit hit;
  202. if (Physics.Raycast(pos + Vector3.up, Vector3.down, out hit, 2, groundMask))
  203. {
  204. pos.y = hit.point.y;
  205. }
  206. }
  207.  
  208. transform.position = pos;
  209. }
  210. #endregion update
  211.  
  212.  
  213. #region override
  214. public virtual void AdjustSpeedOnRotation(Vector3 movementDelta)
  215. {
  216. RotateInThisDirection(movementDelta);
  217. }
  218. #endregion override
  219.  
  220.  
  221.  
  222. #region redirect / rotate
  223. public float RotateInThisDirection(Vector3 direction)
  224. {
  225. float angle = Mathf.Atan2(direction.y, direction.x) * Mathf.Rad2Deg;
  226. Quaternion targetRotation = Quaternion.AngleAxis(angle, Vector3.forward);
  227. transform.rotation = Quaternion.RotateTowards(transform.rotation, targetRotation, rotationSpeed * Time.deltaTime);
  228.  
  229. return transform.rotation.eulerAngles.z;
  230. }
  231. #endregion redirect / rotate
  232. }
  233. }
Advertisement
Add Comment
Please, Sign In to add comment