using System.Collections.Generic; using AOT.PostProcess.BlackArea; using Framework; using Gameplay.Area.BoardView; using Gameplay.Common; using Gameplay.Level; using Gameplay.Unit; using Gameplay.Unit.Data; using Gameplay.Vehicle.Impl; using PhxhSDK; using UnityEngine; namespace Gameplay.Area { public class MoveAreaView { public GameUnit owner; public List moveCellList = new List(); public GameObject rootObj; private bool _needRefresh; private Map _map; private List _teamUnits = new List(); private List _buffCellNotices = new List(); private GameObject _buffNoticeObj; private List _boardViewDataList = new List(); public BoardLineObjPool boardLineObjPool = new BoardLineObjPool(); // 存储所有格子对象的数组 private GameObject[] _cellObjects; // 标记是否已初始化格子对象 private bool _isInitialized = false; public void Init(Map map) { rootObj = new GameObject("[MoveArea]"); _buffNoticeObj = new GameObject("[BuffNotice]"); _map = map; _InitBuffCellNotices(_buffNoticeObj.transform); boardLineObjPool.Init(); // 提前初始化所有格子对象,避免首次刷新时卡顿 _InitializeCellObjects(); } private void _InitBuffCellNotices(Transform parent) { var mapData = _map.MapData; for (int i = 0; i < mapData.showBuffPoints.Count; i++) { var buffPoint = mapData.showBuffPoints[i]; if (string.IsNullOrEmpty(buffPoint.path)) { continue; } var cellIndex = buffPoint.cellIndex; var notice = new BuffCellNotice() { cellIndex = cellIndex, loadPath = buffPoint.path, }; DebugUtil.LogG("BuffCellNotice:" + cellIndex + " " + buffPoint.path); notice.CreateView(parent); _buffCellNotices.Add(notice); } } public void Show(GameUnit setOwner) { owner = setOwner; _UpdateTeamUnits(); _RefreshMoveArea(); _needRefresh = false; _ShowBuffNotices(); rootObj.SetActive(true); _buffNoticeObj.SetActive(true); _RegisterEvent(); } private void _ShowBuffNotices() { for (int i = 0; i < _buffCellNotices.Count; i++) { var notice = _buffCellNotices[i]; if (moveCellList.Contains(notice.cellIndex)) { notice.SetActive(true); } else { notice.SetActive(false); } } } private void _RegisterEvent() { EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, _OnCellIndexChange); EventManager.Instance.Register(EventManager.EventName.INFIGHT_ENTER_UNITCONTAINER, _OnEnterUnitContainer); EventManager.Instance.Register(EventManager.EventName.INFIGHT_EXIT_UNITCONTAINER, _OnExitUnitContainer); EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_REMOVE, _OnUnitRemove); EventManager.Instance.Register(EventManager.EventName.INFIGHT_UNIT_READY, _OnUnitReady); EventManager.Instance.Register(EventManager.EventName.INFIGHT_VEHICLE_DESTROY, _OnVehicleDestroy); EventManager.Instance.Register(EventManager.EventName.INFIGHT_STATE_ENTER_RETREAT, _OnRetreatStateChange); EventManager.Instance.Register(EventManager.EventName.INFIGHT_STATE_EXIT_RETREAT, _OnRetreatStateChange); } private void _UnRegisterEvent() { EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_CELLINDEX_CHANGE, _OnCellIndexChange); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_ENTER_UNITCONTAINER, _OnEnterUnitContainer); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_EXIT_UNITCONTAINER, _OnExitUnitContainer); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_REMOVE, _OnUnitRemove); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_UNIT_READY, _OnUnitReady); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_VEHICLE_DESTROY, _OnVehicleDestroy); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_STATE_ENTER_RETREAT, _OnRetreatStateChange); EventManager.Instance.Unregister(EventManager.EventName.INFIGHT_STATE_EXIT_RETREAT, _OnRetreatStateChange); } private void _OnCellIndexChange(GameUnit unit) { if (unit == owner) return; _needRefresh = true; } private void _OnRetreatStateChange(GameUnit unit) { if (unit == owner) { _needRefresh = true; } } private void _OnVehicleDestroy(GameUnit unit) { _needRefresh = true; } private void _OnUnitReady(GameUnit unit) { _needRefresh = true; } private void _OnUnitRemove(GameUnit unit) { _needRefresh = true; } private void _OnEnterUnitContainer(GameUnit unit) { _needRefresh = true; } private void _OnExitUnitContainer(EDExitUnitContainer ed) { _needRefresh = true; } private void _UpdateTeamUnits() { _teamUnits.Clear(); var allUnits = GameUnitManager.instance.infightUnits.unitList; for (int i = 0; i < allUnits.Count; i++) { var unit = allUnits[i]; if (unit == owner) { continue; } if (unit.commonData.troopId != owner.commonData.troopId) { continue; } // 只要角色和载具 if (unit.gameunitType != EGameUnitType.Character && unit.gameunitType != EGameUnitType.Vehicle) { continue; } _teamUnits.Add(unit); } } public void Hide() { _UnRegisterEvent(); owner = null; if (rootObj != null) { rootObj.SetActive(false); } if (_buffNoticeObj != null) { _buffNoticeObj.SetActive(false); } if (_boardViewDataList != null) { for (int i = 0; i < _boardViewDataList.Count; i++) { var boardViewData = _boardViewDataList[i]; boardViewData.Destroy(LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem); } _boardViewDataList.Clear(); } boardLineObjPool.ReturnAll(); } public void LogicUpdate() { if (owner == null) return; if (_needRefresh) { _needRefresh = false; _RefreshMoveArea(); } } public bool CheckIsInArea(int cellIndex) { return moveCellList.Contains(cellIndex); } private bool _CheckCanPass(int cellIndex) { if (cellIndex < 0) { return false; } if (cellIndex == owner.transData.cellIndex) { return true; } if (!PathFinder.CanPass(cellIndex, owner)) { return false; } if (!BlackAreaManager.instance.CheckIsInLightArea(cellIndex)) { return false; } return true; } private bool _CheckSelfUnits(int cellIndex) { // 判断所有队友在不在这个格子上 // 判断所有队友的targetcell在不在这个格子上 for (int i = 0; i < _teamUnits.Count; i++) { var unit = _teamUnits[i]; if (!unit.statusData.isOnFloor) { continue; } if (unit.statusData.isDead) { if (unit.transData.cellIndex == cellIndex) { return false; } continue; } if (unit.gameunitType == EGameUnitType.Vehicle) { // 载具需要额外判断是否已死亡和是否已满载 var vehicle = unit as NormalVehicle; if (vehicle == null) { continue; } if (vehicle.CheckCanUp(owner)) { continue; } } if (unit.transData.cellIndex == cellIndex) { return false; } if (unit.controlData.targetCellIndex == cellIndex) { return false; } } return true; } private Queue _workList = new Queue(100); private void _UpdateMoveCellList() { var centerIndex = owner.transData.cellIndex; var workList = _workList; workList.Clear(); var mapTgs = LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem; var allCellS = mapTgs.cells; for (int i = 0; i < allCellS.Count; i++) { var iCell = allCellS[i]; iCell.isVisited = false; } var centerCell = mapTgs.cells[centerIndex]; workList.Enqueue(centerCell); centerCell.isVisited = true; while (workList.Count > 0) { var workCell = workList.Dequeue(); // 判断当前格子是否可通行 if (!_CheckCanPass(workCell.index)) { // DebugUtil.LogError("blockedSet.Add:" + lastValue); continue; } // 把自己加入到移动列表 moveCellList.Add(workCell.index); // 把周围的格子加入到工作列表 var neighbors = workCell.neighbours; for (int i = 0; i < neighbors.Count; i++) { var iCell = neighbors[i]; if (iCell.isVisited) { continue; } // 添加到检查过列表中 workList.Enqueue(iCell); iCell.isVisited = true; } } } private void _AutoRemoveSelfUnits() { for (int i = 0; i < _teamUnits.Count; i++) { var unit = _teamUnits[i]; if (!unit.statusData.isOnFloor) { continue; } if (unit.statusData.isDead) { continue; } if (unit.gameunitType == EGameUnitType.Vehicle) { // 载具需要额外判断是否已死亡和是否已满载 var vehicle = unit as NormalVehicle; if (vehicle == null) { continue; } if (vehicle.CheckCanUp(owner)) { continue; } } { var searchIndex = moveCellList.IndexOf(unit.transData.cellIndex); if (searchIndex >= 0) { // fast remove moveCellList[searchIndex] = moveCellList[^1]; moveCellList.RemoveAt(moveCellList.Count - 1); } } { var searchIndex = moveCellList.IndexOf(unit.controlData.targetCellIndex); if (searchIndex >= 0) { // fast remove moveCellList[searchIndex] = moveCellList[^1]; moveCellList.RemoveAt(moveCellList.Count - 1); } } } } private void _AutoAddEnemiesCellIndex() { var units = GameUnitManager.instance.infightUnits.unitList; for (int i = 0; i < units.Count; i++) { var unit = units[i]; if (unit == owner) { continue; } if (unit.commonData.troopId == owner.commonData.troopId) { continue; } var cellIndex = unit.transData.cellIndex; if (!BlackAreaManager.instance.CheckIsInLightArea(cellIndex)) { continue; } if (unit.statusData.canBeAttack) { if (!moveCellList.Contains(cellIndex)) { moveCellList.Add(cellIndex); } } } } private void _RefreshBoardView() { for (int i = 0; i < _boardViewDataList.Count; i++) { var boardViewData = _boardViewDataList[i]; boardViewData.Destroy(LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem); } _boardViewDataList.Clear(); boardLineObjPool.ReturnAll(); BoardViewHelper.GenerateBoard(moveCellList, _boardViewDataList, LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem); for (int i = 0; i < _boardViewDataList.Count; i++) { var boardViewData = _boardViewDataList[i]; boardViewData.CreateBoardSideView(LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem); } } private void _RefreshViewStatus() { var allCellList = LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem.cells; var cellCount = allCellList.Count; // 先将所有单元格标记为未访问 for (int i = 0; i < cellCount; i++) { allCellList[i].isVisited = false; } // 标记可移动格子 for (int i = 0; i < moveCellList.Count; i++) { int cellIndex = moveCellList[i]; allCellList[cellIndex].isVisited = true; } // 更新所有格子的显示状态 for (int i = 0; i < cellCount; i++) { bool canNotMove = !allCellList[i].isVisited; _cellObjects[i].SetActiveEx(canNotMove); } } // 初始化所有格子对象的方法 private void _InitializeCellObjects() { if (_isInitialized) return; var terrainGridSystem = LevelManager.Instance.CurrentLevel.Map.TerrainGridSystem; var cellCount = terrainGridSystem.cells.Count; // 创建对象数组 _cellObjects = new GameObject[cellCount]; // 预加载对象模板 var sampleObj = AssetManager.Instance.GetPreLoadResult(PathDefine.MoveArea.CANNOT_MOVE_AREA_POINT_PATH); // 批量创建所有对象 for (int i = 0; i < cellCount; i++) { _cellObjects[i] = Object.Instantiate(sampleObj, rootObj.transform); // 设置到对应格子的世界位置 _cellObjects[i].transform.position = AreaManager.instance.GetWorldPosByIndex(i); // 初始时全部隐藏 _cellObjects[i].SetActive(false); } _isInitialized = true; } private void _RefreshMoveArea() { moveCellList.Clear(); if (owner.statusData.isRetreat) { // 逃跑状态 // do nothing } else { _UpdateMoveCellList(); } // 刷新显示 // _RefreshBoardView(); // 将队友相关的格子移除 _AutoRemoveSelfUnits(); // 将敌人所在格子加入 _AutoAddEnemiesCellIndex(); _RefreshViewStatus(); } public void Dispose() { Hide(); moveCellList.Clear(); for (int i = 0; i < _buffCellNotices.Count; i++) { var notice = _buffCellNotices[i]; notice.Dispose(); } _buffCellNotices.Clear(); // 清理格子对象 _cellObjects = null; _isInitialized = false; if (rootObj != null) { Object.Destroy(rootObj); rootObj = null; } if (_buffNoticeObj != null) { Object.Destroy(_buffNoticeObj); _buffNoticeObj = null; } boardLineObjPool.Dispose(); boardLineObjPool = null; } } }