ActionAreaWander.cs 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. using BehaviorDesigner.Runtime.Tasks.EnemyAI;
  2. using UnityEngine;
  3. using UnityEngine.AI;
  4. namespace BehaviorDesigner.Runtime.Tasks.Movement
  5. {
  6. [TaskDescription("Wander using the Unity NavMesh.")]
  7. [TaskCategory("YLSJ")]
  8. [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/Movement/documentation.php?id=9")]
  9. [TaskIcon("Assets/Behavior Designer Movement/Editor/Icons/{SkinColor}WanderIcon.png")]
  10. public class ActionAreaWander : NavMeshMovementBase
  11. {
  12. [Tooltip("目标Object")]
  13. public SharedTransform targetObject;
  14. [Tooltip("检测目标的层级")]
  15. public LayerMask objectLayerMask;
  16. [Tooltip("观察角度")]
  17. public SharedFloat viewAngle = 360;
  18. [Tooltip("观察距离")]
  19. public SharedFloat viewDistance = 10;
  20. [Tooltip("最小游荡距离")]
  21. public SharedFloat minWanderDistance = 3;
  22. [Tooltip("最大游荡距离")]
  23. public SharedFloat maxWanderDistance = 7;
  24. [Tooltip("最小游荡持续时间")]
  25. public SharedFloat minWanderDuration = 2;
  26. [Tooltip("最大游荡的持续时间")]
  27. public SharedFloat maxWanderDuration = 5;
  28. [Tooltip("The amount that the agent rotates direction")]
  29. public SharedFloat wanderRate = 2;
  30. [Tooltip("游荡的类型 0静止1随机 2路径点巡逻,配合WanderPoints使用")]
  31. public SharedInt wanderType = 1;
  32. [Tooltip("路径点 当wanderType=2时 使用")]
  33. public SharedTransformList wanderPoints = null;
  34. private int pointIndex = 0;
  35. private Vector3 movePos = Vector3.zero;
  36. private Vector3 livePos = Vector3.zero;
  37. private float curWanderTime = 0;
  38. /// <summary>
  39. /// 出生最大距离
  40. /// </summary>
  41. private float liveAlertDistance = 0;
  42. private BehaviorTree behaviorTree = null;
  43. /// <summary>
  44. /// 是否静止中
  45. /// </summary>
  46. private bool bIdle = true;
  47. // 是否移动中
  48. private bool bMove = false;
  49. /// <summary>
  50. /// 路径点顺序/倒叙
  51. /// </summary>
  52. private bool bPointAdd = true;
  53. /// <summary>
  54. /// 是否赶往出生点
  55. /// </summary>
  56. private bool bToLive = false;
  57. private Role role = null;
  58. public override void OnAwake()
  59. {
  60. base.OnAwake();
  61. livePos = transform.position;
  62. behaviorTree = gameObject.GetComponent<BehaviorTree>();
  63. }
  64. public override void OnStart()
  65. {
  66. base.OnStart();
  67. role = GetComponent<Role>();
  68. liveAlertDistance = (float)behaviorTree.GetVariable("liveAlertDistance").GetValue();
  69. if (m_NavMeshAgent.component.isOnNavMesh)
  70. {
  71. m_NavMeshAgent.component.isStopped = false;
  72. }
  73. float liveDis = Vector3.Distance(transform.position, livePos);
  74. // 距离出生点超过最大范围 回到出生点
  75. if (liveDis >= liveAlertDistance)
  76. {
  77. bToLive = true;
  78. }
  79. else
  80. {
  81. bToLive = false;
  82. }
  83. curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value);
  84. bIdle = true;
  85. }
  86. // There is no success or fail state with wander - the agent will just keep wandering
  87. public override TaskStatus OnUpdate()
  88. {
  89. if (FindTarget(m_NavMeshAgent.component.transform) != null)
  90. {
  91. return TaskStatus.Success;
  92. }
  93. if (wanderType == null)
  94. {
  95. return TaskStatus.Running;
  96. }
  97. // 移动中
  98. if (bMove)
  99. {
  100. // 到达最小停止距离
  101. if (m_NavMeshAgent.component.isOnNavMesh && m_NavMeshAgent.component.remainingDistance <= m_NavMeshAgent.component.stoppingDistance)
  102. {
  103. bMove = false;
  104. // 静止
  105. bIdle = true;
  106. curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value);
  107. if (bPointAdd)
  108. {
  109. pointIndex++;
  110. }
  111. else
  112. {
  113. pointIndex--;
  114. }
  115. }
  116. }
  117. // 静止中
  118. else if (bIdle)
  119. {
  120. // 当前游荡时间
  121. curWanderTime -= Time.deltaTime;
  122. if (curWanderTime <= 0)
  123. {
  124. bToLive = false;
  125. curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value);
  126. // 游荡类型
  127. switch (wanderType.Value)
  128. {
  129. case 1:
  130. {
  131. SetRandomPos();
  132. }
  133. break;
  134. case 2:
  135. {
  136. SetTargetPos();
  137. }
  138. break;
  139. default:
  140. {
  141. // BOSS一直追人
  142. if (role.roleType == RoleType.Boss)
  143. {
  144. SetRandomPos();
  145. }
  146. else
  147. {
  148. // 随机移动
  149. SetRandomPos();
  150. }
  151. }
  152. break;
  153. }
  154. }
  155. }
  156. return TaskStatus.Running;
  157. }
  158. public override void OnEnd()
  159. {
  160. base.OnEnd();
  161. }
  162. /// <summary>
  163. /// 设置目标点
  164. /// </summary>
  165. private void SetTargetPos()
  166. {
  167. if (pointIndex < 0)
  168. {
  169. pointIndex = 1;
  170. bPointAdd = true;
  171. }
  172. if (pointIndex >= wanderPoints.Value.Count)
  173. {
  174. pointIndex = wanderPoints.Value.Count - 2;
  175. bPointAdd = false;
  176. }
  177. if (pointIndex >= 0 && pointIndex < wanderPoints.Value.Count)
  178. {
  179. movePos = wanderPoints.Value[pointIndex].position;
  180. SetDestination(movePos);
  181. bMove = true;
  182. bIdle = false;
  183. }
  184. }
  185. /// <summary>
  186. /// 设置随机点
  187. /// </summary>
  188. private void SetRandomPos()
  189. {
  190. int randomVal = Random.Range(0, 100);
  191. // 随机
  192. if (randomVal >= 50)
  193. {
  194. var direction = transform.forward + Random.insideUnitSphere * wanderRate.Value;
  195. movePos = livePos + direction.normalized * Random.Range(minWanderDistance.Value, maxWanderDistance.Value);
  196. SetDestination(movePos);
  197. bMove = true;
  198. bIdle = false;
  199. }
  200. }
  201. public Transform FindTarget(Transform selfTransform)
  202. {
  203. if (bToLive)
  204. {
  205. return null;
  206. }
  207. Transform objectFound = null;
  208. var hitColliders = Physics.OverlapSphere(selfTransform.position, viewDistance.Value, objectLayerMask);
  209. if (hitColliders != null)
  210. {
  211. float minAngle = 360;
  212. for (int i = 0; i < hitColliders.Length; ++i)
  213. {
  214. if (hitColliders[i].gameObject.activeSelf == false)
  215. {
  216. continue;
  217. }
  218. Role role = hitColliders[i].gameObject.GetComponent<Role>();
  219. if (role == null || role.isDie)
  220. {
  221. continue;
  222. }
  223. Vector3 v3Dir = hitColliders[i].transform.position - selfTransform.position;
  224. v3Dir.Normalize();
  225. float angle = Vector3.Angle(selfTransform.forward, v3Dir);
  226. if (angle <= viewAngle.Value * 0.5f)
  227. {
  228. if (angle < minAngle)
  229. {
  230. minAngle = angle;
  231. objectFound = hitColliders[i].transform;
  232. }
  233. }
  234. if (role.gameObject.layer == LayerMask.NameToLayer("Player"))
  235. {
  236. // 创建对话气泡框
  237. Role self = this.gameObject.GetComponent<Role>();
  238. if (self.bubType == YLBattle.SpawnPoint.BubbleType.Sight && !self.bubEnable)
  239. {
  240. SceneBubbleWindow buCmpt = self.gameObject.AddComponent<SceneBubbleWindow>();
  241. buCmpt.SetContent(self.bubStr);
  242. buCmpt.SetEnableType(self.bubType);
  243. self.bubEnable = true;
  244. }
  245. }
  246. }
  247. }
  248. targetObject.Value = objectFound;
  249. return objectFound;
  250. }
  251. // Reset the public variables
  252. public override void OnReset()
  253. {
  254. wanderRate = 2;
  255. minWanderDistance = 3;
  256. maxWanderDistance = 7;
  257. minWanderDuration = 2;
  258. maxWanderDuration = 5;
  259. }
  260. }
  261. }