Unity实战案例全解析:RTS游戏的框选和阵型功能(4)阵型功能

前篇: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]);
            }
相关推荐
gopyer2 小时前
180课时吃透Go语言游戏后端开发6:Go语言的循环语句
开发语言·游戏·golang·循环语句
心疼你的一切14 小时前
使用Unity引擎开发Rokid主机应用的模型交互操作
游戏·ui·unity·c#·游戏引擎·交互
dengzhenyue19 小时前
游戏项目 多态练习 超级玛丽demo8
游戏
心疼你的一切20 小时前
使用Unity引擎开发Rokid主机应用的全面配置交互操作
学习·游戏·unity·c#·游戏引擎·交互
2501_929157682 天前
NEOGEOCD模拟器+全游戏ISO+工具+特典美术+文档
游戏
da_vinci_x2 天前
2D角色动画进阶:Spine网格变形与序列帧特效的混合工作流
游戏·设计模式·设计师·photoshop·spine·游戏策划·游戏美术
大Mod_abfun3 天前
Unity游戏基础-2(初识场景~项目构建)
游戏·unity·游戏引擎
utmhikari3 天前
【测试人生】LLM赋能游戏自动化测试的一些想法
自动化测试·游戏·ai·大模型·llm·游戏测试
gopyer4 天前
180课时吃透Go语言游戏后端开发7:Go语言中的函数
开发语言·游戏·golang·go·函数
taulee014 天前
在云服务器搭建部署私人饥荒联机版游戏服务器 [2025.10.3][ubuntu 24.04][腾讯云2核2G服务器]
服务器·ubuntu·游戏