using HxGame; using HxGame.Data; using System; using System.Collections; using System.Collections.Generic; using TMPro; using UnityEditor; using UnityEngine; using UnityEngine.EventSystems; using UnityEngine.UI; public partial class MapManager : MonoBehaviour { public enum EditCellType { None, ReturnCell, //回城点 TeleportCell, //传送点 NpcCell, //NPC PathNodeCell, //路点 NpcPath, //npc巡逻路径 MonsterPath, //怪物巡逻路径 AudioTrigger, //音效触发 TriggerCell, //触发点 ReliveCell, //复活点 SellArea, //摆摊区 MonsterArea, //怪物 FuBenArea, //副本 JuBaoArea, //聚宝 } public struct CenterPoint { public int areaIdx; public int radius; //半径 } public struct TriggerPoint { public int areaIdx; public int radius; //半径 public string text; } public struct MonsterPoint { public int areaIdx; public int radius; //半径 public int id; //刷怪ID public int num; //刷怪数量 } //记录已生成的地形网格 private List _activeTerrainCells = new List(); private const int IGNORECELLSIZE = 15; private EditCellType _curEditCellType = EditCellType.None; private int _teleportPointSize = 0; //传送点个数 private int _curTeleportPointIdx = 0; //当前编辑传送点索引 private int _npcPointSize = 0; //npc个数 private int _curNpcPointIdx = 0; //当前编辑npc索引 private int _pathNodePointSize = 0; //路点个数 private int _curPathNodePointIdx = 0; //当前编辑路点索引 private int _triggerPointSize = 0; //触发点个数 private int _curTriggerPointIdx = 0; //当前编辑触发点索引 //npc路径数量map private Dictionary _dicNpcPathPointSize = new Dictionary(); //怪物路径数量map private Dictionary _dicMonsterPathPointSize = new Dictionary(); private CenterPoint _curAudioTriggerCenterPoint = new CenterPoint(); //当前编辑音效区索引 private TriggerPoint _curTriggerCenterPoint = new TriggerPoint(); //当前编辑触发区索引 private CenterPoint _curReliveCenterPoint = new CenterPoint(); //当前编辑复活点索引 private CenterPoint _curSellAreaCenterPoint = new CenterPoint(); //当前编辑摆摊区索引 private MonsterPoint _curMonsterPoint = new MonsterPoint(); //刷怪索引 private MonsterPoint _curFuBenPoint = new MonsterPoint(); //副本刷怪索引 private MonsterPoint _curJuBaoPoint = new MonsterPoint(); //聚宝索引 public CellNode[] cellsNode; private Dictionary> _layCellsMap = new Dictionary>(); public void SetEditCellType(EditCellType type) { _curEditCellType = type; } //传送点 public int AddTeleportPointSize() { return ++_teleportPointSize; } public void RemoveTeleportPointSize(int idx) { _curTeleportPointIdx = idx; RemoveSpecialPoint(EditCellType.TeleportCell); } public void SetCurTeleportPointIdx(int idx) { _curTeleportPointIdx = idx; } //NPC public int AddNpcPointSize() { return ++_npcPointSize; } public void RemoveNpcPointSize(int idx) { _curNpcPointIdx = idx; RemoveSpecialPoint(EditCellType.NpcCell); //还要删除该npc路径 int size = _dicNpcPathPointSize[_curNpcPointIdx]; for (int i = 1; i <= size; i++) { RemoveSpecialPoint(EditCellType.NpcPath, i); } } public void SetCurNpcPointIdx(int idx) { _curNpcPointIdx = idx; } //路点 public void ZeroNodePathSize() { _pathNodePointSize = 0; } public int AddPathNodePointSize() { return ++_pathNodePointSize; } public void RemovePathNodePointSize(int idx) { _curPathNodePointIdx = idx; RemoveSpecialPoint(EditCellType.PathNodeCell); } public void SetCurPathNodePointIdx(int idx) { _curPathNodePointIdx = idx; } //音效触发 public void SetCurAudioTriggerCenterPoint(int idx, int radius) { _curAudioTriggerCenterPoint.areaIdx = idx; _curAudioTriggerCenterPoint.radius = radius; } public void RemoveAudioTriggerCenterPoint(int idx) { _curAudioTriggerCenterPoint.areaIdx = idx; RemoveSpecialPoint(EditCellType.AudioTrigger); } //触发区 public void SetCurTriggerCenterPoint(int idx, int radius, TriggerMode mode) { _curTriggerCenterPoint.areaIdx = idx; _curTriggerCenterPoint.radius = radius; switch(mode) { case TriggerMode.KillMonster: _curTriggerCenterPoint.text = "杀怪触发"; break; case TriggerMode.UseItem: _curTriggerCenterPoint.text = "道具触发"; break; case TriggerMode.Task: _curTriggerCenterPoint.text = "任务触发"; break; case TriggerMode.Npc: _curTriggerCenterPoint.text = "NPC触发"; break; } } public void RemoveTriggerCenterPoint(int idx) { _curTriggerCenterPoint.areaIdx = idx; RemoveSpecialPoint(EditCellType.TriggerCell); } //复活点 public void SetReliveCenterPoint(int idx, int radius) { _curReliveCenterPoint.areaIdx = idx; _curReliveCenterPoint.radius = radius; } public void RemoveReliveCenterPoint(int idx) { _curReliveCenterPoint.areaIdx = idx; RemoveSpecialPoint(EditCellType.ReliveCell); } //摆摊区 public void SetCurSellCenterPoint(int idx, int radius) { _curSellAreaCenterPoint.areaIdx = idx; _curSellAreaCenterPoint.radius = radius; } public void RemoveSellCenterPoint(int idx) { _curSellAreaCenterPoint.areaIdx = idx; RemoveSpecialPoint(EditCellType.SellArea); } //怪物 public void SetMonsterPoint(int idx, int radius, int id, int num) { _curMonsterPoint.areaIdx = idx; _curMonsterPoint.radius = radius; _curMonsterPoint.id = id; _curMonsterPoint.num = num; } public void RemoveMonsterPoint(int idx) { _curMonsterPoint.areaIdx = idx; RemoveSpecialPoint(EditCellType.MonsterArea); //还要删除该npc路径 if (!_dicMonsterPathPointSize.ContainsKey(_curMonsterPoint.areaIdx)) return; int size = _dicMonsterPathPointSize[_curMonsterPoint.areaIdx]; for (int i = 1; i <= size; i++) { RemoveSpecialPoint(EditCellType.MonsterPath, i); } } public void ShowMonsterPoint(int idx) { Transform cellsTrans = UIWindow.Instance.mapTrans.Find("CellsNode"); if (cellsTrans == null) { UIWindow.Instance.ShowMessage("没有找到CellsNode节点"); return; } string cellName = $"怪物区{idx}"; var t = cellsTrans.Find(cellName); if (t == null) return; t.gameObject.SetActive(true); } public void HideMonsterPoint(int idx) { Transform cellsTrans = UIWindow.Instance.mapTrans.Find("CellsNode"); if (cellsTrans == null) { UIWindow.Instance.ShowMessage("没有找到CellsNode节点"); return; } string cellName = $"怪物区{idx}"; var t = cellsTrans.Find(cellName); if (t == null) return; t.gameObject.SetActive(false); } //npc巡逻路径 public int AddNpcPathSize() { if (!_dicNpcPathPointSize.ContainsKey(_curNpcPointIdx)) return 1; return _dicNpcPathPointSize[_curNpcPointIdx]++; } public void SetCurNpcPathIdx(int idx) { if (_dicNpcPathPointSize.ContainsKey(_curNpcPointIdx)) return; _dicNpcPathPointSize.Add(_curNpcPointIdx, idx); } public int GetCurNpcPathIdx() { if (!_dicNpcPathPointSize.ContainsKey(_curNpcPointIdx)) return 0; return _dicNpcPathPointSize[_curNpcPointIdx]; } //monster巡逻路径 public int AddMonsterPathSize() { if (!_dicMonsterPathPointSize.ContainsKey(_curMonsterPoint.areaIdx)) return 1; return _dicMonsterPathPointSize[_curMonsterPoint.areaIdx]++; } public void SetCurMonsterPathIdx(int idx) { if (_dicMonsterPathPointSize.ContainsKey(_curMonsterPoint.areaIdx)) return; _dicMonsterPathPointSize.Add(_curMonsterPoint.areaIdx, idx); } public int GetCurMonsterPathIdx() { if (!_dicMonsterPathPointSize.ContainsKey(_curMonsterPoint.areaIdx)) return 0; return _dicMonsterPathPointSize[_curMonsterPoint.areaIdx]; } //副本刷怪区 public void SetCurFuBenCenterPoint(int idx, int radius, int id, int num) { _curFuBenPoint.areaIdx = idx; _curFuBenPoint.radius = radius; _curFuBenPoint.id = id; _curFuBenPoint.num = num; } public void RemoveFuBenCenterPoint(int idx) { _curFuBenPoint.areaIdx = idx; RemoveSpecialPoint(EditCellType.FuBenArea); } //聚宝区 //public void SetCurJuBaoCenterPoint(int idx, int radius, int id, int num) public void SetCurJuBaoCenterPoint(int idx, int radius, int id) { _curJuBaoPoint.areaIdx = idx; _curJuBaoPoint.radius = radius; _curJuBaoPoint.id = id; } public void RemoveJuBaoCenterPoint(int idx) { _curJuBaoPoint.areaIdx = idx; RemoveSpecialPoint(EditCellType.JuBaoArea); } private string GetSpecialName(EditCellType cellType, out int size) { size = 0; string cellName = string.Empty; switch (cellType) { case EditCellType.TeleportCell: cellName = "传送点"; size = _teleportPointSize; break; case EditCellType.NpcCell: cellName = "Npc"; size = _npcPointSize; break; case EditCellType.PathNodeCell: cellName = "PathNode"; size = _pathNodePointSize; break; case EditCellType.ReliveCell: cellName = "复活点"; size = UIWindow.Instance.uiRelivesPanel.itemParent.childCount; break; case EditCellType.AudioTrigger: cellName = "音效触发"; size = UIWindow.Instance.uiAudioTriggerPanel.itemParent.childCount; break; case EditCellType.TriggerCell: cellName = "触发区"; size = UIWindow.Instance.uiTriggersPanel.itemParent.childCount; break; case EditCellType.SellArea: cellName = "摆摊区"; size = UIWindow.Instance.uiSellAreasPanel.itemParent.childCount; break; case EditCellType.MonsterArea: cellName = "怪物区"; //size = UIWindow.Instance.uiMonstersPanel_old.itemParent.childCount; break; case EditCellType.FuBenArea: cellName = "副本刷怪"; size = UIWindow.Instance.uiFuBensPanel.itemParent.childCount; break; case EditCellType.JuBaoArea: cellName = "聚宝区"; size = UIWindow.Instance.uiFuBensPanel.itemParent.childCount; break; default: return null; } return cellName; } public void ShowSpecialPoint(EditCellType cellType) { int size = 0; string cellName = GetSpecialName(cellType, out size); //TODO tb 格子类型放在这里 SetEditCellType(cellType); if (cellType == EditCellType.MonsterArea) { } } public void HideSpecialPoint(EditCellType cellType) { int size = 0; string cellName = GetSpecialName(cellType, out size); } public void RemoveSpecialPoint(EditCellType cellType, int idx = 0) { Transform parentArea = mapAreaParent; string cellName = string.Empty; switch (cellType) { case EditCellType.ReturnCell: cellName = "回城点"; break; case EditCellType.TeleportCell: cellName = $"传送点{_curTeleportPointIdx}"; break; case EditCellType.NpcCell: cellName = $"Npc{_curNpcPointIdx}"; break; case EditCellType.PathNodeCell: cellName = $"PathNode{_curPathNodePointIdx}"; break; case EditCellType.ReliveCell: cellName = $"复活点{_curReliveCenterPoint.areaIdx}"; parentArea = mapReliveArea; break; case EditCellType.AudioTrigger: cellName = $"音效触发{_curAudioTriggerCenterPoint.areaIdx}"; break; case EditCellType.TriggerCell: cellName = $"Trigger{_curTriggerPointIdx}"; break; case EditCellType.SellArea: cellName = $"摆摊区{_curSellAreaCenterPoint.areaIdx}"; break; case EditCellType.MonsterArea: cellName = $"怪物区{_curMonsterPoint.areaIdx}"; parentArea = mapMonsterArea; break; case EditCellType.FuBenArea: cellName = $"副本刷怪{_curFuBenPoint.areaIdx}"; break; case EditCellType.JuBaoArea: cellName = $"聚宝区{_curJuBaoPoint.areaIdx}"; break; case EditCellType.NpcPath: cellName = $"NpcPath{_curNpcPointIdx}{idx}"; break; case EditCellType.MonsterPath: cellName = $"MonsterPath{_curMonsterPoint .areaIdx}{idx}"; break; default: return; } if (parentArea.Find(cellName)) { DestroyImmediate(parentArea.Find(cellName).gameObject); } } public void CreateSpecialPoint(int x, int y, EditCellType cellType) { if (_curOpenMapId <= 0) return; UnityEngine.Object obj = null; Transform parentArea = mapAreaParent; if (cellType < EditCellType.AudioTrigger) obj = null; else if (cellType == EditCellType.AudioTrigger) obj = Resources.Load("Prefabs/audioTriggerCenterPoint"); else if (cellType == EditCellType.TriggerCell) obj = Resources.Load("Prefabs/triggerCenterPoint"); else if (cellType == EditCellType.ReliveCell) { obj = Resources.Load("Prefabs/reliveCenterPoint"); parentArea = mapReliveArea; } else if (cellType == EditCellType.MonsterArea) { obj = Resources.Load("Prefabs/monsterPoint"); parentArea = mapMonsterArea; } else if (cellType == EditCellType.FuBenArea) obj = Resources.Load("Prefabs/fubenPoint"); else if (cellType == EditCellType.JuBaoArea) obj = Resources.Load("Prefabs/jubaoPoint"); if (obj == null) { UIWindow.Instance.ShowMessage("加载cell.prefab失败"); return; } string cellName = string.Empty; Vector3 localScale = Vector3.zero; int Idx = 0; switch (cellType) { case EditCellType.ReturnCell: cellName = "回城点"; break; case EditCellType.TeleportCell: cellName = $"传送点{_curTeleportPointIdx}"; Idx = _curTeleportPointIdx; break; case EditCellType.NpcCell: cellName = $"Npc{_curNpcPointIdx}"; Idx = _curNpcPointIdx; break; case EditCellType.PathNodeCell: cellName = $"PathNode{_curPathNodePointIdx}"; Idx = _curPathNodePointIdx; break; case EditCellType.AudioTrigger: cellName = $"音效触发{_curAudioTriggerCenterPoint.areaIdx}"; Idx = _curAudioTriggerCenterPoint.areaIdx; break; case EditCellType.TriggerCell: cellName = $"触发区{_curTriggerCenterPoint.areaIdx}"; Idx = _curTriggerCenterPoint.areaIdx; break; case EditCellType.ReliveCell: cellName = $"复活点{_curReliveCenterPoint.areaIdx}"; Idx = _curReliveCenterPoint.areaIdx; break; case EditCellType.MonsterArea: cellName = $"怪物区{_curMonsterPoint.areaIdx}"; Idx = _curMonsterPoint.areaIdx; if (Idx < 0) return; break; case EditCellType.FuBenArea: cellName = $"副本刷怪{_curFuBenPoint.areaIdx}"; Idx = _curMonsterPoint.areaIdx; break; case EditCellType.JuBaoArea: cellName = $"聚宝区{_curJuBaoPoint.areaIdx}"; Idx = _curJuBaoPoint.areaIdx; break; case EditCellType.NpcPath: cellName = $"NpcPath{_curNpcPointIdx}{GetCurNpcPathIdx()}"; Idx = _curNpcPointIdx; break; case EditCellType.MonsterPath: cellName = $"MonsterPath{_curMonsterPoint.areaIdx}{GetCurMonsterPathIdx()}"; Idx = _curMonsterPoint.areaIdx; break; } GameObject go = null; if (parentArea.Find(cellName)) { go = parentArea.Find(cellName).gameObject; } else { go = Instantiate(obj) as GameObject; go.transform.SetParent(parentArea, false); } var sceneArea = go.GetComponent(); sceneArea.SetSceneAreaData(cellType, Idx); sceneArea.SetAreaPos(new Vector2Int(x, y)); go.name = cellName; if(cellType == EditCellType.MonsterArea) { go.transform.Find("Name").GetComponent().text = $"怪物区{_curMonsterPoint.areaIdx}"; go.transform.Find("ID").GetComponent().text = "ID:" + _curMonsterPoint.id.ToString(); go.transform.Find("Num").GetComponent().text = "Num:" + _curMonsterPoint.num.ToString(); float scaleX = MapManager.Instance.map.sideWidth * _curMonsterPoint.radius * 2; float scaleY = MapManager.Instance.map.sideHeight * _curMonsterPoint.radius * 2; go.transform.localScale = new Vector3(scaleX,scaleY,1); } else if (cellType == EditCellType.FuBenArea) { go.transform.Find("Order").GetComponent().text = _curFuBenPoint.areaIdx.ToString(); go.transform.Find("ID").GetComponent().text = "ID:" + _curFuBenPoint.id.ToString(); go.transform.Find("Num").GetComponent().text = "Num:" + _curFuBenPoint.num.ToString(); } else if (cellType == EditCellType.JuBaoArea) { go.transform.Find("ID").GetComponent().text = "ID:" + _curJuBaoPoint.id.ToString(); } else if(cellType == EditCellType.TriggerCell) { go.transform.GetChild(0).GetComponent().text = _curTriggerCenterPoint.text; } } public int GetLayCellCount(CellType lay) { if(!_layCellsMap.ContainsKey(lay)) return 0; return _layCellsMap[lay].Count; } public void CreateCells() { foreach (var key in _layCellsMap.Keys) _layCellsMap[key].Clear(); Transform cellsTrans = UIWindow.Instance.mapTrans.Find("CellsNode"); if(cellsTrans == null) { UIWindow.Instance.ShowMessage("没有找到CellsNode节点"); return; } //有可能创建了回城点等 if (cellsTrans.childCount > IGNORECELLSIZE) { SetGameObjectActiveWithAllChild(cellsTrans, true); return; } } public void HideCells() { Transform cellsTrans = UIWindow.Instance.mapTrans.Find("CellsNode"); if (cellsTrans == null) { UIWindow.Instance.ShowMessage("没有找到CellsNode节点"); return; } SetGameObjectActiveWithAllChild(cellsTrans, false); } public void ShowCells() { Transform cellsTrans = UIWindow.Instance.mapTrans.Find("CellsNode"); if (cellsTrans == null) { UIWindow.Instance.ShowMessage("没有找到CellsNode节点"); return; } SetGameObjectActiveWithAllChild(cellsTrans, true); } void SetGameObjectActiveWithAllChild(Transform parentTrans, bool bActive) { for (int i = 0; i < parentTrans.childCount; i++) { Transform trans = parentTrans.GetChild(i); if (trans == null) continue; trans.gameObject.SetActive(bActive); } } public void RemoveAllCells() { Transform trans = UIWindow.Instance.mapTrans.Find("CellsNode"); if (trans == null) return; int count = trans.childCount; for (int i = 0; i < count; i++) { DestroyImmediate(trans.GetChild(0).gameObject); } Cleanup(); } public CellNode GetCell(int x, int y) { if (x < 0 || y < 0) return null; if (y >= _cellRows || x >= _cellCols) return null; int index = y * _cellCols + x; return cellsNode[index]; } public CellNode GetCell(int index) { if (index < 0) return null; if (index >= cellsNode.Length) return null; return cellsNode[index]; } public CellNode GetCell(Vector3 pos) { int x = (int)pos.x / _cellWidth; int y = (int)pos.z / _cellHeight; return GetCell(x, y); } private CellType GetCellType(string cellName) { string[] tmp = cellName.Split('_'); if (tmp.Length != 2) return CellType.None; int x, y; x = Convert.ToInt32(tmp[0]); y = Convert.ToInt32(tmp[1]); int index = y * _cellCols + x; return cellsNode[index].cellType; } private CellType SetCellType(string cellName, CellType type) { string[] tmp = cellName.Split('_'); if (tmp.Length != 2) return CellType.None; int indexX, indexY; indexX = Convert.ToInt32(tmp[0]); indexY = Convert.ToInt32(tmp[1]); return SetCellType(indexX, indexY, type); } private CellType SetCellType(int indexX, int indexY, CellType type) { CellNode cell = GetCell(indexX, indexY); if (cell == null) return CellType.None; if (type == CellType.Safe) cell.cellType |= CellType.Safe; else cell.cellType = type; return cell.cellType; } public bool isDragging = false; public Vector3 downPos; public SceneArea currentComponent; private void UpdateCellPos() { if (Input.GetMouseButtonDown(0)) { if (EventSystem.current.IsPointerOverGameObject()) return; int hitLayer = (1 << LayerMask.NameToLayer("MapCell")); Ray ray = Camera.main.ScreenPointToRay(Input.mousePosition); Vector2 rayOrigin = ray.origin; Vector2 rayDirection = ray.direction; RaycastHit2D hit = Physics2D.Raycast(rayOrigin, rayDirection, Mathf.Infinity, hitLayer); if (hit.collider != null) { var mouseComponent = hit.collider.transform.GetComponent(); if (mouseComponent != null) { if (mouseComponent.editCellType != _curEditCellType) return; mouseComponent.OnPointerClick(); currentComponent = mouseComponent; } downPos = Input.mousePosition; } } // 检测鼠标左键拖拽 if (Input.GetMouseButton(0)) { if (Input.mousePosition != downPos || isDragging) { isDragging = true; // 调用 AreaComponent 的拖拽方法 currentComponent?.OnPointerDrag(Input.mousePosition); } } // 检测鼠标左键释放 if (Input.GetMouseButtonUp(0)) { currentComponent?.OnPointerUp(); isDragging = false; currentComponent = null; } } public void ResetCell() { if (MapManager.Instance.map == null) return; int cellTotal = MapManager.Instance.map.selector.horizontalNumber * MapManager.Instance.map.selector.verticalNumber; cellsNode = new CellNode[cellTotal]; for (int row = 0; row < MapManager.Instance.map.selector.horizontalNumber; row++) for (int col = 0; col < MapManager.Instance.map.selector.verticalNumber; col++) { int index = row * MapManager.Instance.map.selector.verticalNumber + col; cellsNode[index] = new CellNode(row,col,index, MapManager.Instance.map.selector.getCellType(index)); } } }