using BehaviorDesigner.Runtime.Tasks.EnemyAI; using UnityEngine; using UnityEngine.AI; namespace BehaviorDesigner.Runtime.Tasks.Movement { [TaskDescription("追寻目标.")] [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 ActionSeekTarget : NavMeshMovementBase { [Tooltip("追寻的目标")] public SharedTransform target; [Tooltip("追寻成功的距离")] public SharedFloat seekSuccessDistance = 2; [Tooltip("追寻失败的距离(不能超过观察范围,否则永远不会追寻目标)")] public SharedFloat seekFailDistance = 7; [Tooltip("偏移(误差)")] public SharedFloat seekOffsetDistance = 0.5f; [BehaviorDesigner.Runtime.Tasks.Tooltip("攻击射线检测,启用后到达攻击距离会检测中间是否有障碍,有障碍则继续寻路")] public bool attackRayCheck = false; /// /// 出生地的警戒范围 (从出生地算,超出这个范围则不再追击目标) /// private float liveAlertDistance = 0; private BehaviorTree behaviorTree = null; private Role role = null; public override void OnAwake() { base.OnAwake(); behaviorTree = gameObject.GetComponent(); role = gameObject.GetComponent(); } public override void OnStart() { liveAlertDistance = (float)behaviorTree.GetVariable("liveAlertDistance").GetValue(); if (m_NavMeshAgent.component.isOnNavMesh) { m_NavMeshAgent.component.isStopped = false; } //m_NavMeshAgent.component.stoppingDistance = seekSuccessDistance.Value; base.OnStart(); } // There is no success or fail state with wander - the agent will just keep wandering public override TaskStatus OnUpdate() { if (target.Value == null) { return TaskStatus.Failure; } float liveDis = Vector3.Distance(transform.position, role.mLivePos); // 超出 出生地范围,则不再追击 if (liveDis > liveAlertDistance) { // 返回出生地 SetDestination(role.mLivePos); return TaskStatus.Failure; } float dis = Vector3.Distance(m_NavMeshAgent.component.transform.position, target.Value.position); Vector3 dir = target.Value.position - role.transform.position; dir.Normalize(); Debug.DrawRay(role.transform.position + Vector3.up + role.transform.right, dir * dis, Color.red); Debug.DrawRay(role.transform.position + Vector3.up - role.transform.right, dir * dis, Color.red); if (dis <= seekSuccessDistance.Value && IsObstacle(dis) == false) { if (m_NavMeshAgent.component.isOnNavMesh) { m_NavMeshAgent.component.ResetPath(); m_NavMeshAgent.component.isStopped = true; } return TaskStatus.Success; } else if (dis > seekFailDistance.Value + seekOffsetDistance.Value) { if (m_NavMeshAgent.component.isOnNavMesh) { m_NavMeshAgent.component.ResetPath(); m_NavMeshAgent.component.isStopped = true; } return TaskStatus.Failure; } SetDestination(target.Value.position); //// 设置战斗状态 //if (UI_BaseMainWindow.Instance() != null) //{ // UI_BaseMainWindow.Instance().SetFightingState(true); //} return TaskStatus.Running; } /// /// 是否没有障碍 /// /// true没有障碍 false有障碍 private bool IsObstacle(float dis) { if (attackRayCheck) { RaycastHit hit; Vector3 dir = target.Value.position - role.transform.position; dir.Normalize(); bool isHit1 = Physics.Raycast(role.transform.position + Vector3.up + role.transform.right, dir, out hit, dis, 1 << LayerMask.NameToLayer("Stop")); bool isHit2 = Physics.Raycast(role.transform.position + Vector3.up - role.transform.right, dir, out hit, dis, 1 << LayerMask.NameToLayer("Stop")); if (isHit1 == false && isHit2 == false) { return false; } else { return true; } } else { return false; } } public override void OnEnd() { base.OnEnd(); } } }