using System.Collections.Generic; using UnityEngine; /// /// 每隔一段时间检测周围目标脚本 /// public class Bhv_FindEnemy : MonoBehaviour { [Tooltip("清空锁定目标的距离")] public float reSetLockTargetDist; [Tooltip("重新确定当前对象的距离")] public float reFindSelectTargetDist; [Tooltip("每次重新检测的间隔事件")] public float reDoInterval = 0.3f; private float m_LastChkTime; private void Start() { FuncConfigConfig _funcConfig = FuncConfigConfig.Get("MaxTargetRange"); reSetLockTargetDist = float.Parse(_funcConfig.Numerical1); JobSetupConfig _jobConfig = JobSetupConfig.Get(PlayerDatas.Instance.baseData.Job); reFindSelectTargetDist = _jobConfig.MaxSwitchTargetDist * Constants.F_DELTA; } private void Update() { if (Time.time - m_LastChkTime < reDoInterval) { return; } m_LastChkTime = Time.time; GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero == null) { return; } if (_hero.LockTarget != null && !(_hero.LockTarget is GA_NpcCollect) && !(_hero.LockTarget.ActorInfo.faction == 1)) { // 判断是否要清空锁定目标 DoIfClearLockTarget(); return; } if (!_hero.aiHandler.IsAuto() || _hero.aiHandler.IsPause()) { // 只有当前主角没有锁定目标的时候才进行搜怪 DoReFindSelectTarget(); } } private void DoIfClearLockTarget() { GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero.LockTarget is GA_NpcFightBoss || _hero.LockTarget is GA_NpcClientFightBoss || _hero.LockTarget is GActorNpcNoFight) { return; } Vector3 _targetPos = _hero.LockTarget.Pos; Vector3 _heroPos = _hero.Pos; float _distSqrt = MathUtility.DistanceSqrtXZ(_targetPos, _heroPos); if (_distSqrt > Mathf.Pow(reSetLockTargetDist, 2) || StatusMgr.Instance.IsInvisible(_hero.LockTarget.ServerInstID)) { _hero.LockTarget = null; } } private void DoReFindSelectTarget() { GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero.SelectTarget == null) { var _actor = GAMgr.Instance.FindAtkTarget(_hero.Pos, reSetLockTargetDist); if (!(_actor is GActorFight)) { _hero.SelectTarget = _actor; } else { if (_actor.CanAtked()) { _hero.SelectTarget = _actor; } } } else { Vector3 _targetPos = _hero.SelectTarget.Pos; Vector3 _heroPos = _hero.Pos; float _distSqrt = MathUtility.DistanceSqrtXZ(_targetPos, _heroPos); var _chkDis = reFindSelectTargetDist; if (PlayerDatas.Instance.baseData.MapID == 31340 && _hero.SelectTarget is GA_NpcCollect) { _chkDis += 1; } if (_distSqrt > Mathf.Pow(_chkDis, 2)) { var _actor = GAMgr.Instance.FindAtkTarget(_hero.Pos, reSetLockTargetDist); if (!(_actor is GActorFight)) { _hero.SelectTarget = _actor; } else { if (_actor.CanAtked()) { _hero.SelectTarget = _actor; if (_actor is GA_NpcFightBoss && _hero.LockTarget == null) { _hero.LockTarget = _actor; } } } } } } #region 界面切换目标 private List m_SelectedTarget = new List(); public void SwitchTarget() { GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero == null) { return; } if (_hero.IsRushing) { return; } if (_hero.SelectTarget != null) { if (!m_SelectedTarget.Contains(_hero.SelectTarget.ServerInstID)) { m_SelectedTarget.Add(_hero.SelectTarget.ServerInstID); } } GActorFight _fight = null; uint _curResultID = 0; uint _bestPlayerID = 0; uint _bestNpcID = 0; uint _bestTargetID = 0;// 有可能找不到的最优解, 此时用上面变量来决定最优解 if (PlayerDatas.Instance.baseData.AttackMode == (int)E_AttackMode.All || PlayerDatas.Instance.baseData.AttackMode == (int)E_AttackMode.Family || PlayerDatas.Instance.maliciousAtkPlayer.Count > 0) { //Debug.LogFormat("当前模式: {0}, 开始搜索Player对象...", (E_AttackMode)PlayerDatas.Instance.baseData.AttackMode); List _actorList = GAMgr.Instance.GetGroupList(E_ActorGroup.Player); if (_actorList != null) { _actorList.Sort(CompareDistance); for (int i = 0; i < _actorList.Count; ++i) { _fight = _actorList[i] as GActorFight; if (_fight == null || !_fight.CanAtked()) { continue; } if (MathUtility.DistanceSqrtXZ(_hero.Pos, _fight.Pos) > Mathf.Pow(reSetLockTargetDist, 2)) { continue; } if (_bestPlayerID == 0) { _bestPlayerID = _fight.ServerInstID; } // 排除之前选择过的 if (m_SelectedTarget.Contains(_fight.ServerInstID)) { continue; } // 确定此次解 _curResultID = _fight.ServerInstID; break; } if (_curResultID != 0) { //Debug.LogFormat(" |-- 此次有最优解: {0}", _curResultID); _bestTargetID = _curResultID; } //else if (_bestPlayerID != 0) //{ // //Debug.LogFormat(" |-- 此次没有最优解, 使用所有Player里面的最优解: {0}", _bestPlayerID); // _bestTargetID = _bestPlayerID; // // 清空过滤列表 // m_SelectedTarget.Clear(); //} } } // 在上面的角色选择中选不到目标, 即场上可见范围内是没有任何玩家的 // 开始判断NPC if (_bestTargetID == 0) { //Debug.Log("没有找到任何Player对象, 开始搜索NPC对象"); List _actorList = GAMgr.Instance.GetGroupList(E_ActorGroup.Enemy); if (_actorList != null) { _actorList.Sort(CompareDistance); for (int i = 0; i < _actorList.Count; ++i) { _fight = _actorList[i] as GActorFight; if (_fight == null || !_fight.CanAtked()) { continue; } if (MathUtility.DistanceSqrtXZ(_hero.Pos, _fight.Pos) > Mathf.Pow(reSetLockTargetDist, 2)) { continue; } if (_bestNpcID == 0) { _bestNpcID = _fight.ServerInstID; } // 排除之前选择过的 if (m_SelectedTarget.Contains(_fight.ServerInstID)) { continue; } // 确定此次解 _curResultID = _fight.ServerInstID; break; } if (_curResultID != 0) { //Debug.LogFormat(" |-- 此次有最优解: {0}", _curResultID); _bestTargetID = _curResultID; } } } // 最后进行判断取哪个值 // 如果出现都选不中的情况, 有可能是所有的怪都被遍历了一遍了 if (_bestTargetID == 0) { // 这里判断是不是还有最优选中对象 if (_bestPlayerID != 0) { _bestTargetID = _bestPlayerID; //Debug.LogFormat(" |-- 此次没有最优解, 使用所有Player里面的最优解: {0}", _bestPlayerID); } else if (_bestNpcID != 0) { _bestTargetID = _bestNpcID; //Debug.LogFormat(" |-- 此次没有最优解, 使用所有NPC里面的最优解: {0}", _bestNpcID); } // 清空过滤列表 m_SelectedTarget.Clear(); } if (_bestTargetID != 0) { _hero.LockTarget = GAMgr.Instance.GetBySID(_bestTargetID); _hero.SelectTarget = _hero.LockTarget; m_SelectedTarget.Add(_bestTargetID); if (_hero.LockTarget != null) { GA_Hero.CallLockTargetChanged(_hero.LockTarget.ServerInstID); } } } public int CompareDistance(GActor a1, GActor a2) { GA_Hero _hero = PlayerDatas.Instance.hero; if (_hero == null) { return 0; } float _chk1 = MathUtility.DistanceSqrtXZ(a1.Pos, _hero.Pos); float _chk2 = MathUtility.DistanceSqrtXZ(a2.Pos, _hero.Pos); if (_chk1 < _chk2) { return -1; } else if (_chk1 > _chk2) { return 1; } return 0; } #endregion }