WanderingAI.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. using System.Collections.Generic;
  2. using UnityEngine;
  3. using UnityEngine.AI;
  4. [DefaultExecutionOrder(10)]
  5. [RequireComponent(typeof(InstantiatePrefab))]
  6. public class WanderingAI : MonoBehaviour
  7. {
  8. [Header("Only for Debugging (do not set from here)")]
  9. public Transform[] waypoints;
  10. public List<Transform> waypointsList;
  11. public float[] wanderTimer;
  12. public List<float>[] waitingTimer;
  13. [Header("Scattering around the target")]
  14. public float targetScattering = 5.0f; //Streuung
  15. [Header("Leave Settings")]
  16. public float leaveTimer = 120f;
  17. public Vector3 leavePosition;
  18. // Leave Settings
  19. private float offsetx = 0;
  20. private float offsetz = 0;
  21. private int inRow = 4; // incl 0 - 4
  22. private float[] timer;
  23. private float globalTimer;
  24. private Vector3[][] target;
  25. private int[][] humansPrio;
  26. private GameObject[][] humansGO;
  27. private NavMeshAgent[][] humansNMA;
  28. private Animator[][] humansA;
  29. private const string isWalking = "isWalking";
  30. // Use this for initialization
  31. void Start()
  32. {
  33. // Get initialized Variables from InstantiatePrefab
  34. humansGO = gameObject.GetComponent<InstantiatePrefab>().humanGameObject;
  35. humansNMA = gameObject.GetComponent<InstantiatePrefab>().humanNavMeshAgent;
  36. humansA = gameObject.GetComponent<InstantiatePrefab>().humanAnimator;
  37. wanderTimer = gameObject.GetComponent<InstantiatePrefab>().wanderTimer;
  38. waitingTimer = gameObject.GetComponent<InstantiatePrefab>().waitingTimer;
  39. waypoints = gameObject.GetComponent<InstantiatePrefab>().waypointsArray;
  40. waypointsList = new List<Transform>(waypoints);
  41. humansPrio = gameObject.GetComponent<InstantiatePrefab>().humanPriorities;
  42. // Set length of variables to humanGo.Length
  43. target = new Vector3[humansGO.Length][];
  44. timer = new float[humansGO.Length];
  45. // Initialize size and content
  46. for(int i = 0; i < humansGO.Length; i++)
  47. {
  48. target[i] = new Vector3[humansGO[i].Length];
  49. for(int j = 0; j < humansGO[i].Length; j++)
  50. {
  51. timer[i] = wanderTimer[i];
  52. }
  53. }
  54. globalTimer = 0;
  55. }
  56. //private void FixedUpdate()
  57. //{
  58. // for(int i = 0; i < humansGO.Length; ++i)
  59. // {
  60. // if (timer[i] >= wanderTimer[i])
  61. // {
  62. // if (waypoints.Length == 0) return;
  63. // int currentWP = Random.Range(0, waypointsList.Count);
  64. // target[i][0] = CheckTarget(waypointsList[currentWP].transform.position, targetScattering);
  65. // if(target[i][0].x != float.PositiveInfinity)
  66. // {
  67. // for (int j = 0; j < humansGO[i].Length; ++j)
  68. // {
  69. // target[i][j] = target[i][0];
  70. // if (humansNMA[i][j].isActiveAndEnabled)
  71. // humansNMA[i][j].SetDestination(target[i][j]);
  72. // humansA[i][j].SetBool(isWalking, humansNMA[i][j].velocity.magnitude > 0.01f);
  73. // }
  74. // timer[i] = 0;
  75. // // remove from list to ensure that all WP are visited at the frequency indicated; if list empty fill list with initial WPs
  76. // ReduceWaypoints(currentWP);
  77. // }
  78. // }
  79. // else
  80. // {
  81. // for (int j = 0; j < humansGO[i].Length; ++j)
  82. // {
  83. // humansA[i][j].SetBool(isWalking, humansNMA[i][j].velocity.magnitude > 0.01f);
  84. // // if humans are not walking, then set priority to 0 so that the other humans dont disturb them
  85. // if(humansNMA[i][j].velocity.magnitude <= 0.01f)
  86. // humansNMA[i][j].avoidancePriority = 0;
  87. // else
  88. // humansNMA[i][j].avoidancePriority = humansPrio[i][j];
  89. // }
  90. // }
  91. // timer[i] += Time.deltaTime;
  92. // }
  93. //}
  94. private void FixedUpdate()
  95. {
  96. for (int i = 0; i < humansGO.Length; ++i)
  97. {
  98. if (waypoints.Length == 0) return;
  99. for(int j = 0; j < humansGO[i].Length; ++j)
  100. {
  101. if(target[i][j] == Vector3.zero ||
  102. humansNMA[i][j].velocity.magnitude <= 0.01f ||
  103. humansNMA[i][j].remainingDistance <= humansNMA[i][j].stoppingDistance ||
  104. humansNMA[i][j].pathStatus == NavMeshPathStatus.PathComplete ||
  105. !humansNMA[i][j].hasPath)
  106. {
  107. int currentWP = Random.Range(0, waypointsList.Count);
  108. target[i][j] = CheckTarget(waypointsList[currentWP].transform.position, targetScattering);
  109. if (target[i][0].x != float.PositiveInfinity)
  110. {
  111. if (humansNMA[i][j].isActiveAndEnabled)
  112. humansNMA[i][j].SetDestination(target[i][j]);
  113. humansA[i][j].SetBool(isWalking, humansNMA[i][j].velocity.magnitude > 0.01f);
  114. }
  115. // remove from list to ensure that all WP are visited at the frequency indicated; if list empty fill list with initial WPs
  116. ReduceWaypoints(currentWP);
  117. }
  118. else
  119. {
  120. humansA[i][j].SetBool(isWalking, humansNMA[i][j].velocity.magnitude > 0.01f);
  121. // if humans are not walking, then set priority to 0 so that the other humans dont disturb them
  122. if (humansNMA[i][j].velocity.magnitude <= 0.01f)
  123. humansNMA[i][j].avoidancePriority = 0;
  124. else
  125. humansNMA[i][j].avoidancePriority = humansPrio[i][j];
  126. }
  127. }
  128. timer[i] += Time.deltaTime;
  129. }
  130. }
  131. public static Vector3 CheckTarget(Vector3 target, float dist)
  132. {
  133. Vector3 modifiedTarget = Random.insideUnitSphere * dist + target;
  134. // SamplePosition also checks the y axis. However, this is not relevant for me, so valid positions (x & z) are also discarded.
  135. // 0.0f is the only valid entry for y
  136. modifiedTarget = new Vector3(modifiedTarget.x, 0f, modifiedTarget.z);
  137. NavMeshHit navHit;
  138. NavMesh.SamplePosition(modifiedTarget, out navHit, 1.0f, -1);
  139. return navHit.position;
  140. }
  141. public void ReduceWaypoints(int index)
  142. {
  143. waypointsList.RemoveAt(index);
  144. if(waypointsList.Count <= 0)
  145. waypointsList = new List<Transform>(waypoints);
  146. }
  147. public void LeaveMarket(int i)
  148. {
  149. for (int j = 0; j < humansGO[i].Length; ++j)
  150. {
  151. target[i][j] = new Vector3(leavePosition.x + offsetx, 0, leavePosition.z + offsetz);
  152. // Calculate offset
  153. if (offsetz < inRow * 2)
  154. offsetz += 2;
  155. else
  156. {
  157. offsetz = 0;
  158. offsetx += 2;
  159. }
  160. }
  161. }
  162. private void LateUpdate()
  163. {
  164. for (int i = 0; i < humansGO.Length; ++i)
  165. {
  166. for (int j = 0; j < humansGO[i].Length; ++j)
  167. {
  168. humansA[i][j].speed = 0.5f + (humansNMA[i][j].velocity.magnitude / gameObject.GetComponent<InstantiatePrefab>().speedMinMax.y);
  169. }
  170. }
  171. }
  172. }