前篇:Unity实战案例全解析:RTS游戏的框选和阵型功能(3)生成范围检测框 +重置框选操作-CSDN博客
本案例来源于unity唐老狮,有兴趣的小伙伴可以去泰克在线观看该课程
我只是对重要功能进行分析和做出笔记分享,并未无师自通,吃水不忘打井人
本案例的实现流程图
本节实现效果
分析
选中士兵数量和布阵方式
如何实现呢?如果没有分析出算法就用switch语句一个一个去规定,如果分析出了算法直接根据框选中的士兵数量实现即可
容易忽略的关键变量
士兵前进的方向该如何确定?
可以根据当前的位置frontPos指向target
如果是第一移动,那frontPos就设置为当前士兵的位置
当下次一达到目的地以后,就将上一个位置 =当前的目标位置即可
最后每一次重置框选后,可以重置一下frontPo
cs
nowRigth = Quaternion.Euler(0, 90, 0) * nowForward;
s
计算布局函数
这里面定义了一个偏移量用来设置士兵之间的间隔
cs
//士兵之间的间隔距离
private float soldierOffset = 3;
还定义了一个当前朝向的右向量用来计算位置
cs
/// <summary>
/// 根据鼠标点击的目标点 计算出 阵型的其它点位
/// </summary>
/// <param name="targetPos"></param>
/// <returns></returns>
private List<Vector3> GetTargetPos(Vector3 targetPos)
{
//需要计算目标点 的 面朝向和 右朝向
Vector3 nowForward = Vector3.zero;
Vector3 nowRigth = Vector3.zero;
//是一批士兵 上一次已经移动过一次了 有上一次的位置
if(frontPos != Vector3.zero)
nowForward = (targetPos - frontPos).normalized;//有上一次的点 就直接计算
else//没有上一次的点 就用第一个士兵的位置 作为上一次的点来计算
nowForward = (targetPos - soldierObjs[0].transform.position).normalized;
//根据面朝向 得到右朝向 旋转y轴 90度
nowRigth = Quaternion.Euler(0, 90, 0) * nowForward;
List<Vector3> targetsPos = new List<Vector3>();
switch (soldierObjs.Count)
{
case 1:
targetsPos.Add(targetPos);
break;
case 2:
targetsPos.Add(targetPos + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos - nowRigth * soldierOffset / 2);
break;
case 3:
targetsPos.Add(targetPos);
targetsPos.Add(targetPos + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowRigth * soldierOffset);
break;
case 4:
targetsPos.Add(targetPos + nowForward * soldierOffset / 2 - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset / 2 + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos - nowForward * soldierOffset / 2 - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos - nowForward * soldierOffset / 2 + nowRigth * soldierOffset / 2);
break;
case 5:
targetsPos.Add(targetPos + nowForward * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset / 2 - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset / 2 + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset / 2 - nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset / 2 + nowRigth * soldierOffset);
break;
case 6:
targetsPos.Add(targetPos + nowForward * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset / 2 - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset / 2 + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset / 2 - nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset / 2 + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset / 2);
break;
case 7:
targetsPos.Add(targetPos + nowForward * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowRigth * soldierOffset);
targetsPos.Add(targetPos);
targetsPos.Add(targetPos - nowForward * soldierOffset);
break;
case 8:
targetsPos.Add(targetPos + nowForward * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowRigth * soldierOffset);
targetsPos.Add(targetPos);
targetsPos.Add(targetPos - nowForward * soldierOffset - nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset + nowRigth * soldierOffset);
break;
case 9:
targetsPos.Add(targetPos + nowForward * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowRigth * soldierOffset);
targetsPos.Add(targetPos + nowRigth * soldierOffset);
targetsPos.Add(targetPos);
targetsPos.Add(targetPos - nowForward * soldierOffset - nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset + nowRigth * soldierOffset);
targetsPos.Add(targetPos - nowForward * soldierOffset);
break;
case 10:
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos - nowForward * soldierOffset - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowForward * soldierOffset + nowRigth * soldierOffset * 1.5f);
break;
case 11:
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos - nowForward * soldierOffset - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowForward * soldierOffset + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowForward * soldierOffset);
break;
case 12:
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowForward * soldierOffset - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos + nowForward * soldierOffset + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos + nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos - nowForward * soldierOffset - nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowForward * soldierOffset + nowRigth * soldierOffset * 1.5f);
targetsPos.Add(targetPos - nowForward * soldierOffset - nowRigth * soldierOffset / 2);
targetsPos.Add(targetPos - nowForward * soldierOffset + nowRigth * soldierOffset / 2);
break;
}
//计算完毕后 记录当前次的位置
frontPos = targetPos;
return targetsPos;
}
}
实际移动函数
使用射线检测得到目标点target
cs
if( Physics.Raycast(Camera.main.ScreenPointToRay(Input.mousePosition), out hitInfo, 1000, 1 << LayerMask.NameToLayer("Ground")) )
{
//通过目标点 计算出 真正的 阵型目标点
//计算目标点
List<Vector3> targetsPos = GetTargetPos(hitInfo.point);
//命令士兵朝向各自的目标点 移动
for (int i = 0; i < soldierObjs.Count; i++)
soldierObjs[i].Move(targetsPos[i]);
}