using UnityEngine;
|
using System.Collections.Generic;
|
using UnityEngine.AI;
|
|
|
public class HeroRoundGird : Singleton<HeroRoundGird>
|
{
|
|
public class GirdNode
|
{
|
public int index;
|
public int column;
|
public int row;
|
public float dis;
|
public uint ownerSID;
|
}
|
|
private List<GirdNode> m_1 = new List<GirdNode>();
|
private List<GirdNode> m_2 = new List<GirdNode>();
|
private List<GirdNode> m_3 = new List<GirdNode>();
|
private List<GirdNode> m_4 = new List<GirdNode>();
|
private Dictionary<int, GirdNode> m_NodeDict = new Dictionary<int, GirdNode>();
|
private Dictionary<int, bool> m_NodeEmpty = new Dictionary<int, bool>();
|
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("<color=yellow>监测点: {0}, 索引 {1} 已经被占用...</color>", pos, _index);
|
}
|
}
|
else
|
{
|
// Debug.LogFormat("<color=yellow>监测点: {0}, 索引 {1} 非法...</color>", pos, _index);
|
}
|
}
|
else
|
{
|
// Debug.LogFormat("<color=yellow>监测点: {0}, 距离超出限定距离...</color>", 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;
|
}
|
}
|