
引言
哈喽大家好,我是亿元程序员,一位有着8年游戏行业经验的主程。
不知道 大家还记不记得,笔者之前写过一篇3D箭头游戏实战,当时我们已经把基础版本跑通了:
- MagicaVoxel 编辑3D像素模型关卡
- 导出文本数据,解析每个方块的x/y/z/r/g/b
- 用一个白色基础模型配合Shader动态上色
- 通过"剥洋葱"思路给每个方块找可移出方向
- 点击屏幕后发射射线,选中最近方块
- 方块无阻挡就飞出,有阻挡就回弹
- 最后还补了拖尾效果和性能优化
当时做出来之后,还挺满意:能编辑关卡,能生成模型,能点击消除,能拖尾,性能也不算差。

结果有小伙伴拿去做箭头游戏的试玩素材后,私信我:
亿哥 ,老板说你的3D箭头游戏用来做试玩太普通了,没人想玩,让我变点花样...
能不能做一个合并方块的版本?
**合并方块?**仔细了解了一下,就是把原来多个方块合并成一个大的。
与此同时,刚好专属群里也有水友讨论到:

既然如此 ,笔者只好再水一期(传道授业的事怎能叫水呢?叫分享!),把这个3D箭头游戏再升级一版。
本期 带大家看看:如何把普通的3D箭头方块,升级成支持合并块的版本。
本文实战完整源码可在文末获取,已经拥有合集的小伙伴可以直接更新。
上期回顾:3D箭头基础版做了什么?
简单回顾 一下,上期3D箭头游戏主要分成几块。
1. 关卡编辑器
通过
MagicaVoxel编辑 3D 像素模型,导出文本数据,用每个方块的坐标和颜色生成关卡。
2. 数形结合
解析 导出的
PLY文本,拿到每个体素方块的x/y/z/r/g/b,再在Cocos里实例化出对应的3D方块。
3. 颜色 Shader
只保留 一个白色基础模型,通过
Shader把贴图当成mask,再动态混合baseColor和arrowColor,不用为每种颜色单独做模型。
4. 游戏逻辑
点击屏幕发射射线,选中最近方块;方块根据箭头方向判断是否被挡住,没挡住就飞出去。
5. 更进一步
补上 动态
Mesh拖尾,以及按颜色缓存材质、开启GPU Instancing,减少绘制压力。
这一版 作为3D箭头基础玩法已经够用了。
但是,如果要做试玩素材,还缺一个东西:第一眼的变化感。
这次怎么变花样?
小伙伴的思路是:把相邻的小方块合并成不同形态的大块。
以前是:
txt
[1][1][1]
[1][1][1]
现在可以变成:
txt
[ 2 ][1]
[1][ 2 ]
也就是说,以前每个体素点都是一个独立小方块;现在会根据颜色、方向、空间关系,把部分小方块合并成大块。
这样关卡里就会同时出现:
- 普通单格方块
- 单轴长条块
- 小矩形块
- 少量大体块
看起来 就不再是一堆完全一样的小cube,而是更像一个更有难度的3D关卡。
但是问题来了。
合并方块 不是把 scale 放大一下就完事。只要方块尺寸变了,生成、贴图、碰撞、拖尾全都要跟着改。
核心实战:方块合并
1. 新增MergedBlock
旧版一个顶点就是一个方块。
新版一个方块可能由多个体素点合并而来,所以需要一个新的结构记录合并后的信息:

简单解释一下:
-
min/max:记录这个合并块覆盖的体素范围 -
sx/sy/sz:记录合并后的尺寸 -
cx/cy/cz:记录中心点,用于摆放节点 -
dir:记录箭头方向 -
r/g/b:记录颜色
生成流程也从原来的:
PLY顶点 -> 生成方块
变成了:
PLY顶点 -> 计算方向 -> 合并成MergedBlock -> 生成方块
这一层抽象很重要,因为后面的缩放、旋转、碰撞、拖尾,都要按合并后的真实尺寸来处理。
2. 方向分配:先制造同向区域
想要合并,有个前提:相邻格子的方向要一致。
如果每个方块方向完全随机,旁边的格子不是向左就是向右,根本合不起来。

所以新版先对方向分配做了一轮优化。
旧版大概是:
txt
这个方向能走?随机挑一个。
新版变成:
txt
这个方向能走?看看周围能不能一起走。
核心思路:
- 检查每个体素点在
6个方向上是否有阻挡 - 找到当前可以移出的点
- 选择一个使用次数较少的方向,避免方向过度集中
- 从该点开始向周围
BFS蔓延 - 能沿同方向移出的邻居,也尽量分配同方向
这样会自然形成一些同方向区域。
同方向区域越多,合并出来的块就越自然。
3. 合并规则:同色、同向、相邻
合并不是乱合。
当前规则很保守,必须同时满足:
- 颜色相同
- 箭头方向相同
- 空间连续相邻
- 还没有被合并过
**为什么?**三观不合的人还是比较难在一起的,何况方块有上面4个条件。
踩坑实录:箭头贴图又扁了
第一版合并跑起来后,确实有变化了。
但是马上发现一个问题:长条块上的箭头和圆点被拉扁了。

原因也很简单。
旧版 Shader里是直接按UV采样:

标准正方体没问题。
但 长条块的世界空间比例变了,UV还按原来那样铺,图案自然会被拉伸。
解决思路是:方块可以变长,但图案尽量保持原比例。

新版 Shader做了几件事:
-
把贴图当成
2x2图集 -
找到当前
UV所在象限 -
用
dFdx/dFdy估算UV在世界空间的真实比例 -
根据比例压缩采样区域
-
重映射
texUV后再采样
关键就是:方块可以拉长,箭头不要跟着一起拉扁。
更进一步
拖尾也要适配合并块
上期 已经做过拖尾效果,当时是通过动态Mesh生成一条逐渐透明的3D色带。
但是 旧版方块都是小cube,拖尾截面固定也还行。
合并之后,方块可能变成长条,拖尾也要跟着变化。

新版里做了这些调整:
-
根据方块的世界旋转计算局部截面方向
-
使用
worldScale.y和worldScale.z得到真实宽高 -
拖尾网格按矩形截面生成四个角
这样长条块飞出去时,拖尾也会跟着变宽或变高,看起来更贴合。
最终效果
改造之后 ,方块不再全是同尺寸小cube。
局部会出现长条、矩形、大块,视觉层次更明显:
旧版效果:

新版效果:

结语
老板一句"变点花样",听起来像是简单的美术需求,改起来却是需要点技术的。
小伙伴们有没有哪些被老板一句话打动的瞬间?
本文实战完整源码 已集成到亿元Cocos小游戏实战合集2.0,已经拥有的小伙伴可以直接更新。
我是"亿元程序员",一位有着8年游戏行业经验的主程。在游戏开发中,希望能给到您帮助,也希望通过您能帮助到大家。
实不相瞒,想要个赞 和爱心 !请把该文章分享给你觉得有需要的其他小伙伴。谢谢!
推荐文章: