碰撞回调
我们需要一个方式来获取到这些碰撞信息,物理引擎提供的方式是在碰撞发生时产生回调,在回调里我们可以根据产生碰撞的两个碰撞体的类型信息来判断需要作出什么样的动作。
注意:
需要先在 rigidbody 中 开启碰撞监听,才会有相应的回调产生。
回调中的信息在物理引擎都是以缓存的形式存在的,所以信息只有在这个回调中才是有用的,不要在你的脚本里直接缓存这些信息,但可以缓存这些信息的副本。
定义一个碰撞回调函数很简单,只需要在刚体所在的节点上挂一个脚本,脚本中添加上你需要的回调函数即可。
在上面的代码示例中,我们添加了所有的碰撞回调函数到这个脚本中,一共有四个类型的回调函数,每个回调函数都有三个参数。每种回调函数的作用如注释所示,你可以根据自己的需求来实现相应的回调函数。
我们可以通过拆分一个简单的示例的碰撞过程来描述碰撞回调函数的回调顺序和回调的时机,假设有两个刚体正相互移动,三角形往右运动,方块往左运动,即将碰撞到了一起。
回调的参数包含了所有的碰撞接触信息,每个回调函数都提供了三个参数: contact, selfCollider, otherCollider。
selfCollider 和 otherCollider 很容易理解,如名字所示,selfCollider 指的是回调脚本的节点上的碰撞体,ohterCollider 指的是发生碰撞的另一个碰撞体。
最主要的信息都包含在 contact 中,这是一个 cc.PhysicsContact 类型的实例,可以在 api 文档中找到相关的 api 。contact 中比较常用的信息就是碰撞的位置和法向量,contact 内部是按照刚体的本地坐标来存储信息的,而我们一般需要的是世界坐标系下的信息,我们可以通过 来获取这些信息。
worldManifold
具有以下成员:
points
碰撞点数组,他们不一定会精确的在碰撞体碰撞的地方上,如下图所示(除非你将刚体设置为子弹类型,但是会比较耗性能),但实际上这些点在使用上一般都是够用的。
注意:不是每一个碰撞都会有两个碰撞点,在模拟的更多的情况下只会产生一个碰撞点,下面列举一些其他的碰撞示例。
- normal
在图中所示的线条即碰撞点上的法向量,在这个碰撞中,解决碰撞最快的途径是添加冲量将三角形往左上推,将方块往右下推。需要注意的是这里的法向量只是一个方向,并不带有位置属性,也不会连接到这些碰撞点中的任何一个。
你还需要明白的是碰撞法向量并不是碰撞体碰撞的角度,他只会指明可以解决两个碰撞体相互覆盖这一问题最短的方向。比如上面的例子中如果三角形移动得更快一点,覆盖的情形像下图所示的话:
那么最短的方式将会是把三角形往右上推,所以使用法向量来作为碰撞角度不是一个好主意。如果你希望知道碰撞的真正的方向,可以使用下面的方式:
var vel2 = squareBody.getLinearVelocityFromWorldPoint( worldManifold.points[0] );
这个代码可以获取到两个碰撞体相互碰撞时在碰撞点上的相对速度。
禁用掉 contact 会使物理引擎在计算碰撞时会忽略掉这次碰撞,禁用将会持续到碰撞完成,除非在其他回调中再将这个 contact 启用。
或者如果你只想在本次物理处理步骤中禁用 contact ,可以使用 disabledOnce
。
注意这些修改只会在本次物理处理步骤中生效。