using UnityEngine; using System.Collections.Generic; using UnityEngine.AI; public class HeroRoundGird : Singleton { public class GirdNode { public int index; public int column; public int row; public float dis; public uint ownerSID; } private List m_1 = new List(); private List m_2 = new List(); private List m_3 = new List(); private List m_4 = new List(); private Dictionary m_NodeDict = new Dictionary(); private Dictionary m_NodeEmpty = new Dictionary(); private float m_Width = 0.5f; private float m_Height = 0.5f; private int m_Row; private int m_Column; private float m_OffsetX; private float m_OffsetY; private float m_Sin45 = .7071f; private int m_Half; public Vector3 GetRealPos(GirdNode node) { var _hero = PlayerDatas.Instance.hero; if (_hero != null) { return new Vector3(node.column * m_Width, 0, node.row * m_Height) + _hero.Pos - new Vector3(m_Half * m_Width, 0, m_Half * m_Height); } return Vector3.zero; } public GirdNode Get(int row, int column) { var _index = row * m_Column + column; if (m_NodeDict.ContainsKey(_index)) { return m_NodeDict[_index]; } return null; } public void UnInit() { m_1.Clear(); m_2.Clear(); m_3.Clear(); m_4.Clear(); m_NodeDict.Clear(); m_NodeEmpty.Clear(); } private bool m_Inited = false; public void Init(int row, int column) { if (m_Inited) { return; } m_Inited = true; m_1.Clear(); m_2.Clear(); m_3.Clear(); m_4.Clear(); m_Row = row; m_Column = column; m_Half = m_Row / 2; int _count = m_Half * m_Half; m_OffsetX = column * m_Width * .5f; m_OffsetY = row * m_Height * .5f; for (int i = m_Half; i < m_Row; ++i) { for (int j = m_Half; j < m_Column; ++j) { var _node = new GirdNode { index = i * m_Column + j, column = j, row = i, }; _node.dis = GetDistance(_node); m_1.Add(_node); m_NodeDict[_node.index] = _node; m_NodeEmpty[_node.index] = true; }; } m_1.Sort(_Sort); for (int i = m_Half; i < m_Row; ++i) { for (int j = 0; j < m_Half; ++j) { var _node = new GirdNode { index = i * m_Column + j, column = j, row = i }; _node.dis = GetDistance(_node); m_2.Add(_node); m_NodeDict[_node.index] = _node; m_NodeEmpty[_node.index] = true; } } m_2.Sort(_Sort); for (int i = 0; i < m_Half; ++i) { for (int j = 0; j < m_Half; ++j) { var _node = new GirdNode { index = i * m_Column + j, column = j, row = i }; _node.dis = GetDistance(_node); m_3.Add(_node); m_NodeDict[_node.index] = _node; m_NodeEmpty[_node.index] = true; } } m_3.Sort(_Sort); for (int i = 0; i < m_Half; ++i) { for (int j = m_Half; j < m_Column; ++j) { var _node = new GirdNode { index = i * m_Column + j, column = j, row = i }; _node.dis = GetDistance(_node); m_4.Add(_node); m_NodeDict[_node.index] = _node; m_NodeEmpty[_node.index] = true; } } m_4.Sort(_Sort); } private float GetDistance(GirdNode n) { var _r = (n.row - m_Half) * m_Height; var _c = (n.column - m_Half) * m_Width; return Mathf.Sqrt(_c * _c + _r * _r); } private int _Sort(GirdNode a, GirdNode b) { if (a.dis > b.dis) { return -1; } else if (a.dis < b.dis) { return 1; } return 0; } public GirdNode Request(uint sid, Vector3 pos, float limitDis) { var _hero = PlayerDatas.Instance.hero; if (_hero == null) { return null; } Vector3 _chkCenter = _hero.Pos; // 获取行列 float _x = pos.x - _chkCenter.x + m_OffsetX; float _y = pos.z - _chkCenter.z + m_OffsetY; int _column = (int)(_x / m_Width); int _row = (int)(_y / m_Height); // Debug.LogFormat("计算得出: row: {1}, column: {0}", _row, _column); int _index = _row * m_Column + _column; // Debug.LogFormat("监测点: {0}, 所处行: {1}, 列: {2}, 当前对应索引 {3}", pos, _row, _column, _index); // 距离满足的情况下, 则计算索引 float _currentDistance = MathUtility.DistanceSqrtXZ(pos, _chkCenter); if (_currentDistance < limitDis * limitDis) { if (_index >= 0 && _index < m_NodeDict.Count) { if (m_NodeEmpty[_index]) { m_NodeEmpty[_index] = false; m_NodeDict[_index].ownerSID = sid; return m_NodeDict[_index]; } else { if (m_NodeDict[_index].ownerSID == sid) { return m_NodeDict[_index]; } // Debug.LogFormat("监测点: {0}, 索引 {1} 已经被占用...", pos, _index); } } else { // Debug.LogFormat("监测点: {0}, 索引 {1} 非法...", pos, _index); } } else { // Debug.LogFormat("监测点: {0}, 距离超出限定距离...", pos, _index); } byte _quadrant = 0; if (pos.x >= _chkCenter.x && pos.z >= _chkCenter.z) { _quadrant = 0; } else if (pos.x <= _chkCenter.x && pos.z >= _chkCenter.z) { _quadrant = 1; } else if (pos.x <= _chkCenter.x && pos.z <= _chkCenter.z) { _quadrant = 2; } else { _quadrant = 3; } // Debug.LogFormat("监测点: {0}, 相对于玩家处于第 {1} 象限.", pos, (_quadrant + 1)); GirdNode _node; switch (_quadrant) { case 0: // □ │ ■ // ───┼─── // □ │ □ for (int i = 0; i < m_1.Count; ++i) { _node = m_1[i]; if (_node.dis >= limitDis) { continue; } if (m_NodeEmpty[_node.index]) { m_NodeEmpty[_node.index] = false; var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { _node.ownerSID = sid; return _node; } } else { if (!m_NodeEmpty[_node.index]) { if (_node.ownerSID == 0) { var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { m_NodeEmpty[_node.index] = true; } } } if (m_NodeDict[_node.index].ownerSID == sid) { return m_NodeDict[_node.index]; } } } break; case 1: // ■ │ □ // ───┼─── // □ │ □ for (int i = 0; i < m_2.Count; ++i) { _node = m_2[i]; if (_node.dis >= limitDis) { continue; } if (m_NodeEmpty[_node.index]) { m_NodeEmpty[_node.index] = false; var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { _node.ownerSID = sid; return _node; } } else { if (!m_NodeEmpty[_node.index]) { if (_node.ownerSID == 0) { var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { m_NodeEmpty[_node.index] = true; } } } if (m_NodeDict[_node.index].ownerSID == sid) { return m_NodeDict[_node.index]; } } } break; case 2: // □ │ □ // ───┼─── // ■ │ □ for (int i = 0; i < m_3.Count; ++i) { _node = m_3[i]; if (_node.dis >= limitDis) { continue; } if (m_NodeEmpty[_node.index]) { m_NodeEmpty[_node.index] = false; var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { _node.ownerSID = sid; return _node; } } else { if (!m_NodeEmpty[_node.index]) { if (_node.ownerSID == 0) { var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { m_NodeEmpty[_node.index] = true; } } } if (m_NodeDict[_node.index].ownerSID == sid) { return m_NodeDict[_node.index]; } } } break; case 3: // □ │ □ // ───┼─── // □ │ ■ for (int i = 0; i < m_4.Count; ++i) { _node = m_4[i]; if (_node.dis >= limitDis) { continue; } if (m_NodeEmpty[_node.index]) { m_NodeEmpty[_node.index] = false; var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { _node.ownerSID = sid; return _node; } } else { if (!m_NodeEmpty[_node.index]) { if (_node.ownerSID == 0) { var _real = GetRealPos(_node); _real.y = 0; NavMeshHit _hit; if (NavMesh.SamplePosition(_real, out _hit, 0.02f, NavMesh.AllAreas)) { m_NodeEmpty[_node.index] = true; } } } if (m_NodeDict[_node.index].ownerSID == sid) { return m_NodeDict[_node.index]; } } } break; } return null; } public void Release(int id) { if (!m_NodeEmpty.ContainsKey(id)) { return; } m_NodeEmpty[id] = true; m_NodeDict[id].ownerSID = 0; } }