using BehaviorDesigner.Runtime.Tasks; using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.AI; using BehaviorDesigner.Runtime.Tasks.EnemyAI; namespace BehaviorDesigner.Runtime.Tasks { [TaskDescription("近战警戒。前后游走")] [TaskCategory("YLSJ")] public class ActionSurroundAlert : NavMeshMovementBase { [Tooltip("围绕的目标")] public SharedTransform target; [Tooltip("警戒的最小总时间")] public SharedFloat alertMinTime = 6.0f; [Tooltip("警戒的最大总时间")] public SharedFloat alertMaxTime = 12.0f; [Tooltip("在当前位置后退的最小距离(比如攻击距离是2,后退的距离是1,怪物和人物之间的实际距离是2+1=3,实际距离不要超过alertDistance距离)")] public SharedFloat backMinDis = 1; [Tooltip("在当前位置后退的最大距离(比如攻击距离是2,后退的距离是3,怪物和人物之间的实际距离是2+3=5,实际距离不要超过alertDistance距离)")] public SharedFloat backMaxDis = 3; [Tooltip("警戒的最大范围,超过这个范围则进行追逐)")] public SharedFloat alertDistance = 6; [Tooltip("停留的最小时间(后退完成/围绕完成 都会停留一小段时间)")] public SharedFloat stayMinTime = 0.5f; [Tooltip("停留的最大时间(后退完成/围绕完成 都会停留一小段时间)")] public SharedFloat stayMaxTime = 1.0f; [Tooltip("围绕片断的最小时间")] public SharedFloat aroundFragmentMinTime = 2.0f; [Tooltip("围绕片断的最大时间")] public SharedFloat aroundFragmentMaxTime = 5.0f; [Tooltip("旋转速度(看向目标的旋转速度)")] public float rotationToTargetSpeed = 3; /// /// 出生地的警戒范围 (从出生地算,超出这个范围则不再追击目标) /// private float liveAlertDistance = 0; private float attackDistance = 0; /// /// 是否后退中 /// private bool backing = true; /// /// 是否顺时针围绕 /// private int clockwiseAround = 1; private float curAroundTotalTime = 0; private float curStayTime = 0; private float curAroundFragmentTime = 0; private float curBackDis = 0; private BehaviorTree behaviorTree = null; private Role role = null; private bool bSeek = false; public override void OnAwake() { base.OnAwake(); behaviorTree = gameObject.GetComponent(); role = gameObject.GetComponent(); } public override void OnStart() { base.OnStart(); liveAlertDistance = (float)behaviorTree.GetVariable("liveAlertDistance").GetValue(); attackDistance = (float)behaviorTree.GetVariable("attackDistance").GetValue(); curAroundTotalTime = Random.Range(alertMinTime.Value, alertMaxTime.Value); backing = true; bSeek = false; m_NavMeshAgent.component.updateRotation = false;//禁用旋转 m_NavMeshAgent.component.isStopped = false; Vector3 dir = target.Value.position - m_NavMeshAgent.component.transform.position; dir.Normalize(); curBackDis = Random.Range(backMinDis.Value, backMaxDis.Value); Vector3 backPos = m_NavMeshAgent.component.transform.position - dir * curBackDis; SetDestination(backPos); } public override TaskStatus OnUpdate() { // 目标死亡 if (target.Value == null) { return TaskStatus.Success; } // 时间到达 curAroundTotalTime -= time.deltaTime; if (curAroundTotalTime <= 0) { return TaskStatus.Success; } float liveDis = Vector3.Distance(transform.position, role.mLivePos); float targetDis = Vector3.Distance(transform.position, target.Value.position); // 超出出生地活动范围 if (liveDis > liveAlertDistance) { return TaskStatus.Success; } Vector3 centerPos = target.Value.position; Vector3 dir = transform.position - centerPos; float dis = Vector3.Distance(transform.position, centerPos); dir.Normalize(); dir.y = 0; // 超出 警戒范围 if (targetDis > alertDistance.Value) { backing = false; bSeek = true; m_NavMeshAgent.component.updateRotation = true; m_NavMeshAgent.component.speed = (float)behaviorTree.GetVariable("runSpeed").GetValue(); } // 停留期间不做任何处理 if (curStayTime > 0) { if (m_NavMeshAgent.component.isOnNavMesh && m_NavMeshAgent.component.isStopped != true) { m_NavMeshAgent.component.isStopped = true; } curStayTime -= time.deltaTime; return TaskStatus.Running; } else { if (m_NavMeshAgent.component.isOnNavMesh && m_NavMeshAgent.component.isStopped != false) { m_NavMeshAgent.component.isStopped = false; } } // 后退 if (backing) { if (HasArrived()) { backing = false; ResetAround(); } } // 围绕目标 else { if (bSeek == false) { // 旋转 transform.rotation = Quaternion.Lerp(transform.rotation, Quaternion.LookRotation(-dir), rotationToTargetSpeed * Time.deltaTime); curAroundFragmentTime -= time.deltaTime; if (curAroundFragmentTime > 0) { Vector3 aroundPos = target.Value.position + dir * dis + transform.right * clockwiseAround; SetDestination(aroundPos); } else { ResetAround(); } } else { if (targetDis > curBackDis + attackDistance) { Vector3 targetDir = target.Value.position - m_NavMeshAgent.component.transform.position; targetDir.Normalize(); SetDestination(target.Value.position + targetDir * (curBackDis + attackDistance)); } else { bSeek = false; m_NavMeshAgent.component.updateRotation = false; m_NavMeshAgent.component.speed = (float)behaviorTree.GetVariable("moveSpeed").GetValue(); } } } return TaskStatus.Running; } /// /// 重置围绕 /// private void ResetAround() { int clockwiseRan = Random.Range(0, 2); if (clockwiseRan == 0) { clockwiseAround = -1; } else { clockwiseAround = 1; } curStayTime = Random.Range(stayMinTime.Value, stayMaxTime.Value); curAroundFragmentTime = Random.Range(aroundFragmentMinTime.Value, aroundFragmentMaxTime.Value); } public override void OnEnd() { base.OnEnd(); if (m_NavMeshAgent.component != null && m_NavMeshAgent.component.isOnNavMesh && role.isDie == false) { m_NavMeshAgent.component.isStopped = true; m_NavMeshAgent.component.updateRotation = true; } } } }