Game

Ruin

万物皆可碎

UnityC#实时网格破碎计算几何FPS

实机截图

破碎几何体空间
01实时破碎 —— 子弹击中瞬间网格崩解为数百碎片
战斗场景
02FPS 战斗场景 —— 混合弹道与物理破碎
破碎场景
03可破坏环境 —— 万物皆可碎

演示视频

演示视频

核心亮点

💥

实时网格破碎

从「重心离散分类」到「几何布尔运算」的迭代,实现水密(Watertight)的实时网格切割与截面生成。

🧮

计算几何算法

重心坐标插值、单调链凸包重构截面、各向异性切割,把离线渲染的计算几何搬进实时管线。

🎯

FPS 系统工程

混合弹道系统、程序化后坐力、基于标签的解耦交互协议、旋转解耦动态模糊。

核心思考

DESIGN & ENGINEERING
01

实时破碎:从「空壳」到「水密」的迭代

问题

初版用「重心离散分类」做网格切割——把每个三角形按重心归到切割平面一侧。速度快,但暴露两个致命缺陷:横跨切割面的三角形被强制归边,产生锯齿;更糟的是,简单分离只剥离了表面,没生成新截面,碎片是空心的「纸片壳」,物理碰撞也异常。

思考

根本问题是把三角形当「原子」处理了。真正的切割要深入到顶点级别,做几何布尔运算——计算切割平面与每条边的精确交点,重构上层/下层壳体,并生成封口的截面。

解决

引入 SlicedHull 数据结构做精确几何布尔运算;用重心坐标插值重采样交点处的 UV/法线/切线;用单调链算法在 2D 投影上求凸包、三角剖分生成截面,实现水密网格。

反思

这次迭代让我理解了「性能」和「拓扑正确性」的权衡——朴素算法 O(N) 很快但视觉是废的,进阶算法贵但真实。真正的工程是找到那个「递归深度限制 2-3 层 + 碎片大小阈值」的平衡点,在 60FPS 下既真实又流畅。

SlicedHull重心坐标插值单调链凸包截面生成
实时破碎:从「空壳」到「水密」的迭代 架构图
02

各向异性破碎:不同材质不同碎法

问题

现实里木材沿纹理劈裂、玻璃和混凝土则各向同性碎裂。如果所有物体都用同一种切割策略,破碎效果会「假」——木材不会沿纹理裂开。

思考

破碎策略应该由材质驱动。对木材,限制切割面法线垂直于纹理方向;对玻璃/混凝土,用球形随机分布生成各向同性切割面。递归破碎时,碎片继承父物体速度并施加爆炸力。

解决

实现 ShatterableObject 递归破碎逻辑 + 各向异性切割策略,按材质区分切割方式,碎片赋予独立刚体与凸包碰撞体。

递归破碎各向异性切割材质驱动
各向异性破碎:不同材质不同碎法 架构图
03

动态模糊:旋转解耦避免晕动症

问题

FPS 里传统全屏动态模糊会「隧道效应」——高速奔跑时整个视野边缘模糊,诱发晕动症、干扰索敌。但完全没有模糊,又无法传达速度感、掩盖帧率抖动。

思考

人眼的生理习惯是:自身移动时眼球锁定目标(视野清晰),快速转头时视觉才模糊。可以把「位移」和「旋转」解耦——人为构造一个「伪造的上一帧矩阵」,用当前帧位置 + 上一帧旋转,让位移不产生模糊、只让旋转产生模糊。

解决

基于深度纹理做屏幕空间速度场重建,用「旋转解耦矩阵」消除位移分量,仅在甩鼠标转视角时触发径向模糊。

屏幕空间速度场旋转解耦矩阵深度逆推
动态模糊:旋转解耦避免晕动症 架构图
04

混合弹道与标签解耦

问题

纯射线(Hitscan)零延迟但没有弹道、重力和动能传递,无法驱动破碎;纯物理弹丸真实但 UI 交互反馈慢。且子弹可能击中几十种物体,硬编码 `if (obj is Wall)` 会导致高耦合。

思考

把武器功能解耦成两层:射线做「意图查询」(准星变色、拾取),物理弹丸做「弹道模拟」(动能驱动破碎)。交互则用标签做「握手协议」——子弹只认 `Sliceable` 标签,调用通用 `ShatterableObject.OnHit()`,不关心目标具体是什么。

解决

构建混合弹道系统(射线 + 实体弹丸)+ 基于标签的解耦交互协议,遵循单一职责原则,新增交互类型无需改武器代码。

混合弹道系统标签握手协议事件驱动解耦
混合弹道与标签解耦 架构图

技术细节

引擎Unity
语言C#
平台PC
EzySliceSlicedHullCompute Shader(展望)Shader 后处理

核心:实时网格破碎(SlicedHull 几何布尔运算 + 截面生成)+ 混合弹道 + 程序化后坐力 + 旋转解耦动态模糊。基于标签的解耦交互协议连接射击系统与破碎系统。