1功能描述
敌方出现在我方视野中,小地图显示敌方icon。丢失敌方时,icon消失。类似moba游戏,要满足以下要点:
1.所有己方单位自身都要在小地图上显示。
2.所有己方单位共享视野,当有敌方出现在某个己方单位的视野中时,小地图上显示这个敌方icon。
3.敌方一旦丢失在所有己方单位视野中,小地图上icon消失。
2 详细设计
总体思路是对地形分成二维数组int[N][[N],作为己方的视野权值打分。每个单位所在的世界坐标转化为在地形数组中坐标x,y,每个己方单位的视野以自身为中心探测到格子。每帧检测,上一帧的该单位探测到所有小方块权值-1,当前帧该单位探测到小方块权值+1。当敌人的x,y落在在权值>0的小方块中,说明被探测到了(被谁探测到了不管,己方单位共性视野)。
某一帧,我的视野包括的小方块(绿色框内包含N个小方块)权值为1,队友视野包块的小方块权值为1,两人重叠的部分为2.只要敌人的x,y在权值>0的小方块,说明要出现在视野中了。
2.1 数据初始化
void viewDataInit()
{
m_gridLen = (int)(m_mapSize / m_gridSize);
m_gridCampUnitCnt = new int[m_gridLen, m_gridLen];
m_gridUnitInView = new List<UnitCtrl>();
for (int i = 0; i < m_gridLen; i++)
{
for (int j = 0; j < m_gridLen; j++)
{
m_gridCampUnitCnt[i, j] = 0;
}
}
}
m_mapSize:地形尺寸。m_gridSize:每个格子的世界坐标大小。m_gridCampUnitCnt:权值二维数组。m_gridUnitInView:所有需要显示在小地图上的单位(包含敌方和我方)。
2.2单位出生时
public void Respawn(UnitCtrl unitCtrl)
{
m_unitCtrl = unitCtrl;
m_gridSize = MainMgr.self.m_gridSize;//每一格所占的尺寸(世界坐标)
m_gridViewXLen = (int) (m_unitCtrl.m_viewXLen/m_gridSize);//我x方向上能看到的格子数量
m_gridViewYLen = (int) (m_unitCtrl.m_viewYLen/m_gridSize);
m_gridX = (int)(m_unitCtrl.transform.position.x/m_gridSize);
m_gridY = (int) (m_unitCtrl.transform.position.z/m_gridSize);
if (MainMgr.self.isInRange(m_gridX) && MainMgr.self.isInRange(m_gridY))
{(MainMgr.self.m_gridAllUnit[m_gridX,m_gridY]).Add(m_unitCtrl);}
m_maxLen = MainMgr.self.m_gridLen - 1;
if (m_unitCtrl.m_camp == MainMgr.self.m_camp)//如果是同一阵营的,unit视野下的方块权值+1
{
for (int x = m_gridX - m_gridViewXLen; x <= m_gridX + m_gridViewXLen; x++)
{
if (x >= 0 && x <= m_maxLen)
{
for (int y = m_gridY - m_gridViewYLen; y <= m_gridY + m_gridViewYLen; y++)
{
if (y >= 0 && y <= m_maxLen)
{
MainMgr.self.m_gridCampUnitCnt[x, y]++;//权值加1
}
}
}
}
unitShowInMiniMap();
}
StartCoroutine("yieldUpdataGrid");
}
单位出生时,如果是我方阵营时,他包含的所有小格子权值+1,并且自身要显示在小地图上。出生后开启yieldUpdataGrid的协同函数.
2.3单位移动时
所有处理在yieldUpdataGrid中。
当单位为我方阵营时,每个小格子权值的要做改变。
//当前所在格子
int gridX = (int)(m_unitCtrl.transform.position.x / m_gridSize);
int gridY = (int)(m_unitCtrl.transform.position.z / m_gridSize);
//与上一帧所在格子做比较
int offsetX = gridX - m_gridX;
int offsetY = gridY - m_gridY;
if (m_unitCtrl.m_camp == MainMgr.self.m_camp) //跟我是同一阵营的,更新地图小格子的权值
{
if (offsetX > 0) //向右走
{
int left = m_gridX - m_gridViewXLen;
int right = m_gridX + m_gridViewXLen + 1;
for (int x = 0; x < offsetX; x++)
{
for (int y = m_gridY - m_gridViewYLen; y <= m_gridY + m_gridViewYLen; y++)
{
if (MainMgr.self.isInRange(y))
{
if (MainMgr.self.isInRange(left + x))
MainMgr.self.m_gridCampUnitCnt[left + x, y]--;
if (MainMgr.self.isInRange(right + x))
MainMgr.self.m_gridCampUnitCnt[right + x, y]++;
}
}
}
}
else if (offsetX < 0) //向左走
{
int left = m_gridX - m_gridViewXLen - 1;
int right = m_gridX + m_gridViewXLen;
for (int x = 0; x > offsetX; x--)
{
for (int y = m_gridY - m_gridViewYLen; y <= m_gridY + m_gridViewYLen; y++)
{
if (MainMgr.self.isInRange(y))
{
if (MainMgr.self.isInRange(right + x))
MainMgr.self.m_gridCampUnitCnt[right + x, y]--;
if (MainMgr.self.isInRange(left + x))
MainMgr.self.m_gridCampUnitCnt[left + x, y]++;
}
}
}
}
if (offsetY > 0) //向上走
{
int top = m_gridY + m_gridViewYLen + 1;
int bottom = m_gridY - m_gridViewYLen;
for (int y = 0; y < offsetY; y++)
{
for (int x = gridX - m_gridViewXLen; x <= gridX + m_gridViewXLen; x++)
{
if (MainMgr.self.isInRange(x))
{
if (MainMgr.self.isInRange(bottom + y))
MainMgr.self.m_gridCampUnitCnt[x, bottom + y]--;
if (MainMgr.self.isInRange(top + y))
MainMgr.self.m_gridCampUnitCnt[x, top + y]++;
}
}
}
}
else if (offsetY < 0) //向下走
{
int top = m_gridY + m_gridViewYLen;
int bottom = m_gridY - m_gridViewYLen - 1;
for (int y = 0; y > offsetY; y--)
{
for (int x = gridX - m_gridViewXLen; x <= gridX + m_gridViewXLen; x++)
{
if (MainMgr.self.isInRange(x))
{
if (MainMgr.self.isInRange(top + y))
MainMgr.self.m_gridCampUnitCnt[x, top + y]--;
if (MainMgr.self.isInRange(bottom + y))
MainMgr.self.m_gridCampUnitCnt[x, bottom + y]++;
}
}
}
}
}
主要处理为上一帧的包含的所有小格子权值-1,当前帧包含的所有小格子权值-1.MainMgr.self.isInRange是判断游标有没越界。
当单位为敌方单位时:
if (m_unitCtrl.m_camp != MainMgr.self.m_camp)//如果单位和我是不同阵营的
{
if (MainMgr.self.isInRange(gridX) && MainMgr.self.isInRange(gridY))
{
if (MainMgr.self.m_gridCampUnitCnt[gridX, gridY] > 0)
{
unitShowInMiniMap();
}
else
{
unitHideInMinimap();
}
}
}
3 运行情况
我没探测到敌方A,敌方B,但队友探测到敌方A了,所以小地图上显示3个点(我,队友,敌方B)。
我移动了探测到了敌方B,所以小地图上显示4个点(我,队友,敌方A,B)。