效果预览
模型来自Sketchfab的keiichiisozaki,自带一个idle动画,最左边没有做处理,中间是用了AnimationRigging的DampTransform脚本,最右边是修改过的DampTransform,我把这脚本叫CustomDampTransform。
方案可选
- 软体模拟在AssetStore有Obi、DynamicBone等工具,都是基于韦尔莱积分(Verlet integration),有篇专家的博文介绍得深入浅出形象生动非常漂亮《Verlet Simulations》,十分推荐阅读。
- Obi基于一个叫Oni的原生库(看了下官网文档最近也支持了Burst),运算效率问题不大。
- DynamicBone似乎是简单地在Mono Behavior Update里面计算,可能有效率问题,但是人家设计本来就是用来给几根骨头做计算,不是用来做复杂的织物刚体等计算的。
- unity官方推出的Animation Rigging插件,里面有个Damp Transform,可以用来模拟阻尼,但它有个缺点,就是会拉长(因为其设计,必然拉长),而且有蒙皮变形 ,以前运用过一次,当时没能克服这个问题,上面视频中间的角色用的就是原版的DampTransform,可以看出有位移的时候头发被拉长了。
- 另外一提推出Animation Rigging的时候官方还给了个JiggleChain,之前用过来模拟树木晃动,但我认为它比较贴近刚性弹簧,不适合用来模拟柔软的东西。
- 这里的方法是在官方Animation Rigging插件的DampTransform脚本上做修改,好处是蹭到了JobSystem和Burst(burst编译器使用LLVM将IL / .NET字节码转换为高度优化的Native代码、JobSystem在另外的线程里面做运算,已实现好线程之间的数据传递) 。
做法
脚本上传到了GitHub,点击转跳。
主要是积分的思想,一直维持住约束和被约束的两点之间的距离,有点verlet simulation的味道(?)。
原版DampTransform在source点移动之后,d点有一个阻尼,然后这个阻尼慢慢减少,最终到达d’,在这个过程中,d点与s’的距离有瞬时增大再慢慢恢复,这就导致了拉伸。于是做出修改:一直维持d到s的距离,瞬时把d往s’的方向靠拢,再慢慢绕s’旋转,最终使d到达d’。
其中一个点是,要不断计算被约束点的位置,才能使其不断“回弹”。回弹结束后骨骼的控制权最终完全回到animation clip,结果是:物理干预和原动画较好地融合在了一起。