今天想跟大家聊聊我之前捣鼓的那个“软泥模拟器”。这玩意儿一开始根本没在我计划里,完全是阴差阳错给弄出来的。
那会儿大概是去年暑假,我侄子放假来我家玩。小家伙精力旺盛,整天闹腾得不行。我看他特别喜欢玩那种史莱姆,就是那种软乎乎、黏糊糊的东西,可以随便捏随便搓。但是,玩着玩着家里地上、沙发上到处都是,清理起来可真是个大工程,我老婆都快被他折腾疯了。
有一天晚上,我看着老婆一边抱怨一边清理地上那摊史莱姆印子,我心里突然冒出了个想法:要是能搞个虚拟的史莱姆,让他在电脑上随便玩,那不就省心多了吗?这个念头一冒出来,我就觉得特有意思。平时我喜欢自己捣鼓点小玩意儿,觉得这事儿有点挑战,但我就是喜欢这种从零到一的感觉。
起初的想法和准备
第二天一早,我就开始琢磨这事儿。我当时想,要弄个模拟器,得让它“软”起来,还得能“捏”。我脑子里第一个蹦出来的就是Unity,毕竟以前也用它做过几个小游戏,对它的物理系统有点概念。我就打开电脑,翻了翻以前存的一些资料,看看有没有现成的物理引擎或者粒子系统的例子可以借鉴一下。
我先是找了一些关于软体物理模拟的论文和教程,看得我一头雾水,毕竟那些理论太高深了。我就想,别搞那么复杂,先从最简单的碰撞和形变开始。我打算用Unity的刚体(Rigidbody)和一些关节(Joints)来试试,看看能不能模拟出那种弹性和黏性。再就是材质,得让它看起来晶莹剔透,摸起来(虽然是虚拟的)感觉也得像那么回事。
动手实践的坎坷路
说干就干,我拉了个空项目,扔了一个球体进去。这第一步看起来简单,但要让球体像软泥一样可塑,可就没那么容易了。我尝试了很多种办法。
- 我尝试用很多小球用弹簧连接起来。 我觉得这样应该能模拟出那种聚合又分散的感觉。结果?一运行起来,整个球就跟散架了一样,或者直接穿透地板,根本控制不住。我调了半天弹簧的强度和阻尼,效果还是不理想,根本不像软泥,更像一堆被扯来扯去的橡皮泥。
- 后来我又转向了粒子系统。 我想,软泥不就是很多微小的颗粒聚合在一起吗?我就在Unity里拉了个粒子系统,把粒子的生命周期、速度、碰撞都设了一下。结果发现,粒子系统虽然能做出流体的效果,但它很难表现出软泥那种整体的形变和受力反馈。捏下去一团,松开又恢复,这种感觉粒子系统很难模拟出来,而且性能消耗也挺大的。
- 琢磨了几天,我突然想到了顶点着色器和网格形变。 我觉得这可能是一条路子。我找了一个基础的球体模型,然后开始研究怎么通过代码去修改它的顶点位置。我想,当鼠标点下去的时候,我就让鼠标附近的顶点往里凹,然后通过一些插值和平滑算法,让它看起来是整体在形变。松开鼠标后,再让它慢慢恢复原状。
这期间我看了不少图形学的文章,虽然很多东西半懂不懂,但我就是硬着头皮往前拱。我发现光修改顶点还不够,因为这样看起来很生硬。我还得给它加上弹性效果,让它恢复的时候有个回弹,看起来更自然。我就把一个弹性公式套了进去,让顶点形变有个阻尼恢复的过程。
材质方面,我一开始用了 Unity 自带的一些透明材质,但总觉得少了点“果冻感”。我就自己写了一个简单的着色器,给软泥加上了菲涅尔反射和高光,让它在不同的光照下有那种bling bling的透亮感。我还给它加了一层次表面散射的效果,让光线穿透进去的时候,能有一点点扩散的感觉,这样看起来就更像史莱姆了。
终于成型与后续优化
经过大概一个多星期的折腾,我终于做出一个能看、能玩的东西了。鼠标点下去,软泥会凹陷下去,拖动鼠标还能拉伸,放开后它还会弹几下恢复原状。我把这个小东西拿给我侄子玩,他眼睛都亮了,玩得不亦乐乎,真的再也不在家里撒得到处都是了!那会儿我就觉得,所有的折腾都值了。
这只是个初版,很多地方还能优化。比如,形变的时候网格可能会扭曲得很难看,我还需要找方法去平滑网格的法线;还有颜色切换,手势识别,甚至后面我还想给它加一些音效,模拟那种黏糊糊的声音。虽然只是个小玩意儿,但从想法到一步步实现,中间遇到的问题和解决问题的过程,真的挺锻炼人的。我也算是从头到尾把它给“生”出来了,心里还挺得意的。


