using System.Collections.Generic; using cfg.AICfg; using cfg.SkillCfg; using Framework; using Gameplay.Area; using Gameplay.Character; using Gameplay.Level; using Gameplay.Skill; using UnityEngine; namespace Gameplay.Unit.AI { public class UnitAIManager { public GameUnit owner; public DataAISkillControll rawConfig; private SkillHandle _skillHandle; private float _remainCheckTime; private int _checkDistance; private bool _requireSort; private int _prelockCellIndex; private List _preSelectUnits; public UnitAIManager(GameUnit owner) { this.owner = owner; _preSelectUnits = new List(); } public void Init() { _Init(); } private void _LoadRawConfig() { var skillUnitManager = SkillManager.instance.GetUnitSkillManager(owner); if (skillUnitManager == null) { return; } var pSkill = skillUnitManager.positiveSkill; if (pSkill == null) { return; } var skillConfig = pSkill.runtimeData.configData; if (skillConfig == null) { return; } var aiControlId = skillConfig.AIControllId; if (aiControlId == 0) { return; } rawConfig = TableManager.Instance.Tables.AISkillControlCfg.Get(aiControlId); _skillHandle = pSkill; } private void _Init() { _LoadRawConfig(); if (rawConfig == null) { return; } _InitRuntimeData(); } private void _InitRuntimeData() { _checkDistance = rawConfig.CheckDistance; if (_checkDistance == -1) { _checkDistance = _skillHandle.runtimeData.configData.ReleaseArea; } _requireSort = rawConfig.HpCheck != HPCheckType.None; } public void LogicUpdate(float dt) { if (rawConfig == null) { return; } // 全局跳帧 if (SkillManager.instance.inSkillingUnitAI != null) { return; } if (_skillHandle.runtimeData.remainCDTime > 0) return; // 逃跑过程中不释放技能 if (_skillHandle.owner.statusData.isRetreat) return; // 死亡不释放技能 if (_skillHandle.owner.statusData.isDead) return; // 检测是否在战斗中 var inFight = (LevelManager.Instance.CurrentLevel.LevelTime - owner.commonData.lastInFightSeconds) > 3; if (rawConfig.OnlyReleaseInAttack && inFight) return; _remainCheckTime -= dt; if (_remainCheckTime > 0) { return; } _remainCheckTime = rawConfig.CheckTime; var canRelease = _CheckLogic(); if (canRelease) { if (owner.commonData.troopId != ETroopsId.Self) { // 非己方单位,需要记录到AI释放列表中,防止多个AI一起释放技能 SkillManager.instance.inSkillingUnitAI = owner; } _UseSkill(); } } private void _UseSkill() { switch (rawConfig.AIReleasePos) { case EAIReleasePosType.Self: // 对自己释放 _skillHandle.Use(owner.transData.cellIndex); break; case EAIReleasePosType.TargetCell: // 对目标释放 _skillHandle.Use(_prelockCellIndex); break; case EAIReleasePosType.AroundTargetCellEmpty: // 对目标周围空位释放 _ReleaseToAroundEmpty(); break; default: DebugUtil.LogError("暂未实现的AI释放位置类型:{0}", rawConfig.AIReleasePos); break; } } private void _ReleaseToAroundEmpty() { var aroundCellIndexs = AreaManager.instance.GetCellIndexsAround(_prelockCellIndex, 1); for (int i = 0; i < aroundCellIndexs.Count; i++) { var cellIndex = aroundCellIndexs[i]; if (AreaManager.instance.IsCellEmpty(cellIndex)) { _skillHandle.Use(cellIndex); return; } } DebugUtil.LogError("周围没有空位:" + _prelockCellIndex); } private bool _CheckLogic() { var checkTargetType = rawConfig.CheckTargetType; switch (checkTargetType) { case ETargetType.AnyCell: // 默认锁定自己 _prelockCellIndex = owner.transData.cellIndex; return true; case ETargetType.SelfSide: return _CheckSelfSide(); case ETargetType.EnemySide: return _CheckEnemySide(); } DebugUtil.LogError("暂未实现的AI逻辑检测类型:{0}", checkTargetType); return false; } private bool _CheckEnemySide() { _preSelectUnits.Clear(); var enemyTroopId = owner.commonData.troopId == ETroopsId.Self ? ETroopsId.Enemy1 : ETroopsId.Self; var allEnemySideUnits = GameUnitManager.instance.infightUnits.GetListByTroop(enemyTroopId); for (int i = 0; i < allEnemySideUnits.Count; i++) { var unit = allEnemySideUnits[i]; if (unit == owner) continue; if (rawConfig.RequireTargetAlive && unit.statusData.isDead) continue; var distance = AreaManager.instance.GetDistance(unit.transData.cellIndex, owner.transData.cellIndex); if (distance < _checkDistance) { // 满足需求 if (_requireSort) { _preSelectUnits.Add(unit); } else { // 直接使用这个 _prelockCellIndex = unit.transData.cellIndex; return true; } } } // 第二次筛选 if (_preSelectUnits.Count > 0) { return _ReSelectUnits(); } return false; } private bool _CheckSelfSide() { _preSelectUnits.Clear(); var selfTroopId = owner.commonData.troopId; var allSelfSideUnits = GameUnitManager.instance.infightUnits.GetListByTroop(selfTroopId); for (int i = 0; i < allSelfSideUnits.Count; i++) { var unit = allSelfSideUnits[i]; if (unit == owner) continue; if (rawConfig.RequireTargetAlive && unit.statusData.isDead) continue; var distance = AreaManager.instance.GetDistance(unit.transData.cellIndex, owner.transData.cellIndex); if (distance < _checkDistance) { // 满足需求 if (_requireSort) { _preSelectUnits.Add(unit); } else { // 直接使用这个 _prelockCellIndex = unit.transData.cellIndex; return true; } } } // 第二次筛选 if (_preSelectUnits.Count > 0) { return _ReSelectUnits(); } return false; } private bool _ReSelectUnits() { switch (rawConfig.HpCheck) { case HPCheckType.HpPercentMax: _SelectHPPercentMax(); break; case HPCheckType.HpPercentMin: _SelectHPPercentMin(); break; case HPCheckType.HpPercentLowerThan: return _SelectMatchLowerThan(); default: DebugUtil.LogError("暂未实现的AI血量检测类型:{0}", rawConfig.HpCheck); return false; } return true; } private bool _SelectMatchLowerThan() { var lowerThan = _TryGetFloatParam(0); for (int i = 0; i < _preSelectUnits.Count; i++) { var unit = _preSelectUnits[i]; var percent = unit.aliveData.currentHp / (unit.aliveData.maxHp * 1f); if (percent < lowerThan) { _prelockCellIndex = unit.transData.cellIndex; return true; } } return false; } private void _SelectHPPercentMin() { var minUnit = _preSelectUnits[0]; var minPercent = minUnit.aliveData.currentHp / (minUnit.aliveData.maxHp * 1f); for (int i = 1; i < _preSelectUnits.Count; i++) { var unit = _preSelectUnits[i]; var percent = unit.aliveData.currentHp / (unit.aliveData.maxHp * 1f); if (percent < minPercent) { minPercent = percent; minUnit = unit; } } _prelockCellIndex = minUnit.transData.cellIndex; } private void _SelectHPPercentMax() { var maxUnit = _preSelectUnits[0]; var maxPercent = maxUnit.aliveData.currentHp / (maxUnit.aliveData.maxHp * 1f); for (int i = 1; i < _preSelectUnits.Count; i++) { var unit = _preSelectUnits[i]; var percent = unit.aliveData.currentHp / (unit.aliveData.maxHp * 1f); if (percent > maxPercent) { maxPercent = percent; maxUnit = unit; } } _prelockCellIndex = maxUnit.transData.cellIndex; } private float _TryGetFloatParam(int index) { if (rawConfig.FloatParams.Count <= index) { DebugUtil.LogError("AI参数不足: " + rawConfig.Id + " " + index); return 0; } return rawConfig.FloatParams[index]; } private int _TryGetIntParam(int index) { var floatVal = _TryGetFloatParam(index); return Mathf.RoundToInt(floatVal); } } }