using BehaviorDesigner.Runtime.Tasks.EnemyAI; using UnityEngine; using UnityEngine.AI; namespace BehaviorDesigner.Runtime.Tasks.Movement { [TaskDescription("Wander using the Unity NavMesh.")] [TaskCategory("YLSJ")] [HelpURL("http://www.opsive.com/assets/BehaviorDesigner/Movement/documentation.php?id=9")] [TaskIcon("Assets/Behavior Designer Movement/Editor/Icons/{SkinColor}WanderIcon.png")] public class ActionAreaWander : NavMeshMovementBase { [Tooltip("目标Object")] public SharedTransform targetObject; [Tooltip("检测目标的层级")] public LayerMask objectLayerMask; [Tooltip("观察角度")] public SharedFloat viewAngle = 360; [Tooltip("观察距离")] public SharedFloat viewDistance = 10; [Tooltip("最小游荡距离")] public SharedFloat minWanderDistance = 3; [Tooltip("最大游荡距离")] public SharedFloat maxWanderDistance = 7; [Tooltip("最小游荡持续时间")] public SharedFloat minWanderDuration = 2; [Tooltip("最大游荡的持续时间")] public SharedFloat maxWanderDuration = 5; [Tooltip("The amount that the agent rotates direction")] public SharedFloat wanderRate = 2; [Tooltip("游荡的类型 0静止1随机 2路径点巡逻,配合WanderPoints使用")] public SharedInt wanderType = 1; [Tooltip("路径点 当wanderType=2时 使用")] public SharedTransformList wanderPoints = null; private int pointIndex = 0; private Vector3 movePos = Vector3.zero; private Vector3 livePos = Vector3.zero; private float curWanderTime = 0; /// /// 出生最大距离 /// private float liveAlertDistance = 0; private BehaviorTree behaviorTree = null; /// /// 是否静止中 /// private bool bIdle = true; // 是否移动中 private bool bMove = false; /// /// 路径点顺序/倒叙 /// private bool bPointAdd = true; /// /// 是否赶往出生点 /// private bool bToLive = false; private Role role = null; public override void OnAwake() { base.OnAwake(); livePos = transform.position; behaviorTree = gameObject.GetComponent(); } public override void OnStart() { base.OnStart(); role = GetComponent(); liveAlertDistance = (float)behaviorTree.GetVariable("liveAlertDistance").GetValue(); if (m_NavMeshAgent.component.isOnNavMesh) { m_NavMeshAgent.component.isStopped = false; } float liveDis = Vector3.Distance(transform.position, livePos); // 距离出生点超过最大范围 回到出生点 if (liveDis >= liveAlertDistance) { bToLive = true; } else { bToLive = false; } curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value); bIdle = true; } // There is no success or fail state with wander - the agent will just keep wandering public override TaskStatus OnUpdate() { if (FindTarget(m_NavMeshAgent.component.transform) != null) { return TaskStatus.Success; } if (wanderType == null) { return TaskStatus.Running; } // 移动中 if (bMove) { // 到达最小停止距离 if (m_NavMeshAgent.component.isOnNavMesh && m_NavMeshAgent.component.remainingDistance <= m_NavMeshAgent.component.stoppingDistance) { bMove = false; // 静止 bIdle = true; curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value); if (bPointAdd) { pointIndex++; } else { pointIndex--; } } } // 静止中 else if (bIdle) { // 当前游荡时间 curWanderTime -= Time.deltaTime; if (curWanderTime <= 0) { bToLive = false; curWanderTime = Random.Range(minWanderDuration.Value, maxWanderDuration.Value); // 游荡类型 switch (wanderType.Value) { case 1: { SetRandomPos(); } break; case 2: { SetTargetPos(); } break; default: { // BOSS一直追人 if (role.roleType == RoleType.Boss) { SetRandomPos(); } else { // 随机移动 SetRandomPos(); } } break; } } } return TaskStatus.Running; } public override void OnEnd() { base.OnEnd(); } /// /// 设置目标点 /// private void SetTargetPos() { if (pointIndex < 0) { pointIndex = 1; bPointAdd = true; } if (pointIndex >= wanderPoints.Value.Count) { pointIndex = wanderPoints.Value.Count - 2; bPointAdd = false; } if (pointIndex >= 0 && pointIndex < wanderPoints.Value.Count) { movePos = wanderPoints.Value[pointIndex].position; SetDestination(movePos); bMove = true; bIdle = false; } } /// /// 设置随机点 /// private void SetRandomPos() { int randomVal = Random.Range(0, 100); // 随机 if (randomVal >= 50) { var direction = transform.forward + Random.insideUnitSphere * wanderRate.Value; movePos = livePos + direction.normalized * Random.Range(minWanderDistance.Value, maxWanderDistance.Value); SetDestination(movePos); bMove = true; bIdle = false; } } public Transform FindTarget(Transform selfTransform) { if (bToLive) { return null; } Transform objectFound = null; var hitColliders = Physics.OverlapSphere(selfTransform.position, viewDistance.Value, objectLayerMask); if (hitColliders != null) { float minAngle = 360; for (int i = 0; i < hitColliders.Length; ++i) { if (hitColliders[i].gameObject.activeSelf == false) { continue; } Role role = hitColliders[i].gameObject.GetComponent(); if (role == null || role.isDie) { continue; } Vector3 v3Dir = hitColliders[i].transform.position - selfTransform.position; v3Dir.Normalize(); float angle = Vector3.Angle(selfTransform.forward, v3Dir); if (angle <= viewAngle.Value * 0.5f) { if (angle < minAngle) { minAngle = angle; objectFound = hitColliders[i].transform; } } if (role.gameObject.layer == LayerMask.NameToLayer("Player")) { // 创建对话气泡框 Role self = this.gameObject.GetComponent(); if (self.bubType == YLBattle.SpawnPoint.BubbleType.Sight && !self.bubEnable) { SceneBubbleWindow buCmpt = self.gameObject.AddComponent(); buCmpt.SetContent(self.bubStr); buCmpt.SetEnableType(self.bubType); self.bubEnable = true; } } } } targetObject.Value = objectFound; return objectFound; } // Reset the public variables public override void OnReset() { wanderRate = 2; minWanderDistance = 3; maxWanderDistance = 7; minWanderDuration = 2; maxWanderDuration = 5; } } }