using System; using Gameplay; using Framework; using Gameplay.AI; using UnityEngine; using Gameplay.Unit; using Gameplay.Level; using Gameplay.BT.Variables; using Cysharp.Threading.Tasks; using System.Collections.Generic; using BehaviorDesigner.Runtime.Tasks; using Action = BehaviorDesigner.Runtime.Tasks.Action; public class BTMoveAround : Action { public SharedBattleInfo SharedBattleInfo; private GameUnit _owner; private GameUnit _target; private Map map; private EStage _stage = EStage.None; private int _stageTargetCellIndex = -1; private int _targetCellIndex = -1; private int attackDistance; private Vector2Int targetV2; private Vector2Int ownerV2; private bool needCheck; // 格子,原来的通行等级 private Dictionary crossLevelCells = new Dictionary(); private bool _isRegistered; private enum EStage { None, Stage1, Stage2, } public override void OnStart() { if (!_isRegistered) { EventManager.Instance.Register(EventManager.EventName.INFIGHT_CHARACTER_AI_FINDPATH, ResetCells); _isRegistered = true; } _owner = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.ownerId); _target = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.theChosenOneId); map = LevelManager.Instance.CurrentLevel.Map; _stageTargetCellIndex = -1; _targetCellIndex = -1; } public override TaskStatus OnUpdate() { if (_owner == null) return TaskStatus.Failure; // 避开其他AI AvoidOtherUnit(); if (SharedBattleInfo.Value.theChosenOneId != Constants.INVALID_UINT_ID) { if (_owner?.controlData.targetEnemy == null && _stage == EStage.Stage2) { // 继续追击目标 var enemy = GameUnitManager.instance.infightUnits.Search(SharedBattleInfo.Value.theChosenOneId); if (enemy != null && !enemy.statusData.isDead) { if (_targetCellIndex != enemy.transData.cellIndex) { _target = enemy; _targetCellIndex = -1; } } else { ResetCells(); SharedBattleInfo.Value.theChosenOneId = Constants.INVALID_UINT_ID; return TaskStatus.Failure; } } if (HasTargetMoved()) { RememberTarget(); switch (_stage) { case EStage.None: _stageTargetCellIndex = GetStageTargetCell(); _stage = EStage.Stage1; AIUtils.CheckAndMove(_owner, _stageTargetCellIndex); break; case EStage.Stage1: _stageTargetCellIndex = GetStageTargetCell(); AIUtils.CheckAndMove(_owner, _stageTargetCellIndex); break; case EStage.Stage2: _stageTargetCellIndex = _target.transData.cellIndex; AIUtils.CheckAndMove(_owner, _target.transData.cellIndex); break; default: throw new ArgumentOutOfRangeException(); } return TaskStatus.Running; } if (HasStageArrived() && !AIUtils.IsNeedStop(_owner)) { switch (_stage) { case EStage.Stage1: _stage = EStage.Stage2; _stageTargetCellIndex = _target.transData.cellIndex; AIUtils.CheckAndMove(_owner, _target.transData.cellIndex); break; } } return TaskStatus.Running; } return TaskStatus.Failure; } private int GetStageTargetCell() { attackDistance = _target.fightData.attackDistance / 2; targetV2 = map.TGSCellIndex2BlockPosition(_target.transData.cellIndex); ownerV2 = map.TGSCellIndex2BlockPosition(_owner.transData.cellIndex); var correctPos = targetV2; if (targetV2.y > ownerV2.y && targetV2.x > ownerV2.x) //左下 { var x = targetV2.x + attackDistance; var y = targetV2.y + attackDistance + 1; while (x >= map.MapData.Height) { x--; } while (y >= map.MapData.Width) { y--; } correctPos = new Vector2Int(x, y); // DebugUtil.Log("在目标的左下方,获取到的正确位置是:{0}", correctPos); } if (targetV2.y > ownerV2.y && targetV2.x < ownerV2.x) //左上 { var x1 = targetV2.x - attackDistance; var y1 = targetV2.y + attackDistance + 1; while (x1 < 0) { x1++; } while (y1 >= map.MapData.Width) { y1--; } correctPos = new Vector2Int(x1, y1); // DebugUtil.LogError("在目标的左上方,获取到的正确位置是:{0}", correctPos); } if (targetV2.y < ownerV2.y && targetV2.x > ownerV2.x) //右下 { var x = targetV2.x + attackDistance; var y = targetV2.y - attackDistance + 1; while (x >= map.MapData.Height) { x--; } while (y < 0) { y++; } correctPos = new Vector2Int(x, y); // DebugUtil.LogError("在目标的右下方,获取到的正确位置是:{0}", correctPos); } if (targetV2.y < ownerV2.y && targetV2.x < ownerV2.x) //右上 { var x1 = targetV2.x - attackDistance; var y2 = targetV2.y - attackDistance + 1; while (x1 < 0) { x1++; } while (y2 < 0) { y2++; } correctPos = new Vector2Int(x1, y2); // DebugUtil.LogError("在目标的右上方,获取到的正确位置是:{0}", correctPos); } var targetCellIndex = map.BlockPosition2TGSCellIndex(correctPos); if (!AIUtils.CheckPathExits(_owner, targetCellIndex)) { targetCellIndex = AIUtils.GetCanReachCellAround(map, _owner, targetCellIndex); if (targetCellIndex == -1) targetCellIndex = _owner.transData.cellIndex; } return targetCellIndex; } private bool HasTargetMoved() { return _targetCellIndex != _target.transData.cellIndex; } private void RememberTarget() { _targetCellIndex = _target.transData.cellIndex; if (_stage == EStage.Stage2) return; // 目标未移动 if (_owner.controlData.targetEnemy != null && _owner.controlData.targetEnemy.GetID() == _target.GetID()) return; // 将敌人周围一圈的通行级别设高 var cells = AIUtils.SetCellCrossLevel(map, _owner, _targetCellIndex); foreach (var cell in cells) { crossLevelCells[cell.Key] = cell.Value; } } private bool HasStageArrived() { return _stageTargetCellIndex == _owner?.transData.cellIndex; } private void ResetCells() { // 还原通行级别 AIUtils.SetCellCrossLevel(map, crossLevelCells); crossLevelCells.Clear(); } private async void AvoidOtherUnit() { if (AIUtils.IsNeedStop(_owner)) return; if (_owner.statusData.isMoveing && !needCheck) { needCheck = true; } if (needCheck && !_owner.statusData.isMoveing && _owner.controlData.targetCellIndex == -1) { needCheck = false; ResetCells(); // 随机等待 防止同步 var randomDelay = UnityEngine.Random.Range(0f, 1f); await UniTask.Delay((int)(randomDelay * 1000)); AIUtils.CheckAreaIsOtherEnemyUnit(_owner, SharedBattleInfo.Value.theChosenOneId); } } public override void OnEnd() { if (!_isRegistered) return; EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_CHARACTER_AI_FINDPATH, ResetCells); _isRegistered = false; } public override void OnBehaviorComplete() { if (!_isRegistered) return; EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_CHARACTER_AI_FINDPATH, ResetCells); _isRegistered = false; } }