先看效果
附上灵感来源,分别是cannon的布娃娃示例和大佬的动态骨骼
https://github.com/schteppe/cannon.js/blob/master/demos/ragdoll.html
https://forum.cocos.org/t/topic/135672
不知道大家有没有试过,尝试实现布娃娃效果,直接把关节添加到模型的骨骼上,
然后运行,结果模型扭成一团,大失所望。这是骨骼之间的父子关系导致的
于是本人就想,那创建一副所有节点在同一层级的模拟骨骼
在模拟骨骼上添加刚体,关节
然后把每个节点的坐标和转角赋给真实骨骼(模型的骨骼),不就解决了
咱来试试,首先,想要让骨骼实时受到物理影响,就不能是预渲染的动画
把Use Baked Animation上的钩去掉
接下来创建模拟骨骼,我对模拟骨骼的构想:
- 并非是一比一复刻真实骨骼,只需要有在布娃娃系统中起作用的骨骼就可以
- 为了受到力的作用,还有让布娃娃瘫倒在场景中,每个模拟骨骼都具备刚体和碰撞体
- 用关节将这些骨骼联系起来
选择使用cannon,主要是因为cannon有一个非常简单直观的示例(文章开头给出)
要在代码中引入cannon,我们把CANNON.d.ts复制到项目中(引擎目录下)
建议放在项目的根目录,这样项目里的所有代码都可以用
我们最想要的就是cannon的ConeTwistConstraint(锥形扭曲关节)
要把关节添加到我们的骨骼上呢,首先获取cannon的物理世界(当你的项目物理引擎为cannon时,cannon的物理世界就是通用接口获取的世界)
this.world = PhysicsSystem.instance.physicsWorld.impl;
然后创建一个新的关节,参数填入两根模拟骨骼(比如对应上臂和小臂骨骼的虚拟骨骼)
cocos 把所有的关节参数都统一了,但是我们想要angle和twistAngle起作用(很重要)
所以我们修改CANNON.d.ts 粗暴点,在coneTwistConstraint的参数中直接加入
但这并非胡乱添加,看cannon的源码,原本就是会判断是否存在这2个参数的
剩下的参数之后再详细说,我们把关节添加到物理世界,就生效了
那么要怎么同步模拟骨骼和真实,其实非常简单,只需要以下2行代码
nodeA.setWorldPosition(nodeB.worldPosition)
nodeA.setWorldRotation(nodeB.worldRotation)
这并不是说,从世界坐标系转换到本地之类的操作就不存在了,而是让引擎代劳了
感谢引擎组的努力,还有模型网格会随骨骼动态变化也是,没有这些基础功能·,本文也就不会存在
话又说回来,这样做等于是覆盖了骨骼的动作,原本的动画就没作用了
所以强烈建议启用布娃娃之前,停止动画
this.skeletalAnimation.stop()
至于如何在动画的基础上加入布娃娃…未来会做吧…大概
最后一步就是调参数了
现在再解释一下,把bodyA理解为球关节,bodyB就是球窝关节,
pivotA和pivotB分别是bodyA和bodyB指向连接点的向量
向量的方向由axisA和axisB确定
angle确定球关节的活动范围(移动轨迹可画出一个圆锥)
twistAngle确定bodyA绕axisA的最大旋转角
两个旋转角都用弧度表示,取0到π之间
(以上是本人根据资料和源码做出的理解,如有不对,还请各位大佬指正)
一些有待改进的地方:
- 添加ik,让动作更真实
- 移植ConeTwistConstraint,解除cannon的限制
最后附上商店的示例代码,技术含量不高,如果喜欢就当是鼓励本人的创意了
https://store.cocos.com/app/detail/6247