cocos 碰撞系统
前面的话
本文将简要介绍 Cocos Creator 中的碰撞系统,Cocos Creator 内置了一个简单易用的碰撞检测系统,支持圆形、矩形以及多边形相互间的碰撞检测
编辑碰撞组件
当添加了一个碰撞组件后,可以通过点击 inspector 中的 editing 来开启碰撞组件的编辑
【多边形】
如果编辑的是多边形碰撞组件,会出现如下图所示的多边形编辑区域,区域中的这些点是可以拖动的,拖动的结果会反映到多边形碰撞组件的 points 属性中
当鼠标移动到两点连成的线段上时,鼠标指针会变成添加样式,这时点击鼠标左键会在这个地方添加一个点到多边形碰撞组件中
按住 ctrl 或 command 按键时,移动鼠标到多边形顶点上,会发现顶点以及连接的两条线条变成红色,这时点击鼠标左键将会删除多边形碰撞组件中的这个点
多边形碰撞组件中有一个 Regenerate Points 功能,这个功能可以根据组件依附的节点上的 Sprite 组件的贴图的像素点来自动生成相应轮廓的顶点
Threshold 指明生成贴图轮廓顶点间的最小距离,值越大则生成的点越小,可根据需求进行调节
【圆形】
如果编辑的是圆形碰撞组件,则会出现下图所示的圆形编辑区域
当鼠标悬浮在圆形编辑区域的边缘线上时,边缘线会变亮,这时点击鼠标左键拖动将可以修改圆形碰撞组件的半径大小
【矩形】
如果编辑的是矩形碰撞组件,则会出现如下图所示的矩形编辑区域
当鼠标悬浮在矩形碰撞区域的顶点上时,点击鼠标左键拖拽可以同时修改矩形碰撞组件的长宽;当鼠标悬浮在矩形碰撞区域的边缘线上时,点击鼠标左键拖拽将修改矩形碰撞组件的长或宽中的一个方向
按住 shift 键拖拽时,在拖拽过程中将会保持按下鼠标那一刻的长宽比例,按住 alt 键拖拽时,在拖拽过程中将会保持矩形中心点位置不变
【偏移】
以上所有的碰撞组件编辑中,都可以在各自的碰撞中心区域点击鼠标左键拖拽来改变偏移量
碰撞分组
分组管理,需要打开项目设置面板进行设置,位置为 菜单栏 -> 项目 -> 项目设置
打开项目设置面板后,在分组管理一栏可以看到分组列表的配置项,如下图所示
点击添加分组按钮后即可添加一个新的分组,默认会有一个 Default 分组
要注意的是,分组添加后不可以删除,但可以任意修改分组的名字
【碰撞分组配对】
在分组列表下面可以进行碰撞分组配对表的管理,如下图所示
这张表里的行与列分别列出了分组列表里面的项,分组列表里的修改将会实时映射到这张表里。可以在这张表里配置哪一个分组可以对其他的分组进行碰撞检测,假设 a 行 b 列被勾选上,那么表示 a 行上的分组将会与 b 列上的分组进行碰撞检测
运行时修改节点的 group 之后,需要调用 Collider 的 apply,修改才会生效
根据上面的规则,在这张表里产生的碰撞对有:
Platform-Bullet、Collider-Collider、Actor-Wall、Actor-Platform
脚本控制
cocos creator 内置了一个简单易用的碰撞检测系统,根据添加的碰撞组件进行碰撞检测
当一个碰撞组件被启用时,这个碰撞组件会被自动添加到碰撞检测系统中,并搜索能够与之进行碰撞的其他已添加的碰撞组件来生成一个碰撞对
需要注意的是,一个节点上的碰撞组件,无论如何都是不会进行相互碰撞检测的
【接口】
获取碰撞检测系统
const manager = cc.director.getCollisionManager();
默认碰撞检测系统是禁用的,如果需要使用则需要使用以下方法来开启碰撞检测系统
manager.enabled = true;
默认碰撞检测系统的 debug 绘制是禁用的,如果需要使用则使用以下方法开启 debug 绘制
manager.enableDebugDraw = true;
开启后在运行时可显示碰撞组件的碰撞检测范围,如下所示
如果需要显示碰撞组件的包围盒,可以通过以下接口来进行设置
manager.enabledDrawBoundingBox = true;
结果如下所示
【回调】
当碰撞系统检测到有碰撞产生时,将会以回调的方式通知使用者,如果产生碰撞的碰撞组件依附的节点下挂的脚本中有实现以下函数,则会自动调用以下函数,并传入相关参数
/** * 当碰撞产生的时候调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionEnter: function (other, self) { console.log('on collision enter'); // 碰撞系统会计算出碰撞组件在世界坐标系下的相关的值,并放到 world 这个属性里面 var world = self.world; // 碰撞组件的 aabb 碰撞框 var aabb = world.aabb; // 节点碰撞前上一帧 aabb 碰撞框的位置 var preAabb = world.preAabb; // 碰撞框的世界矩阵 var t = world.transform; // 以下属性为圆形碰撞组件特有属性 var r = world.radius; var p = world.position; // 以下属性为 矩形 和 多边形 碰撞组件特有属性 var ps = world.points; },
/** * 当碰撞产生后,碰撞结束前的情况下,每次计算碰撞结果后调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionStay: function (other, self) { console.log('on collision stay'); },
/** * 当碰撞结束后调用 * @param {Collider} other 产生碰撞的另一个碰撞组件 * @param {Collider} self 产生碰撞的自身的碰撞组件 */ onCollisionExit: function (other, self) { console.log('on collision exit'); }
【触发】
properties: { collider: cc.BoxCollider }, start () { // 开启碰撞检测系统,未开启时无法检测 cc.director.getCollisionManager().enabled = true; // cc.director.getCollisionManager().enabledDebugDraw = true; this.collider.node.on(cc.Node.EventType.TOUCH_START, function (touch, event) { // 返回世界坐标 let touchLoc = touch.getLocation(); // https://docs.cocos.com/creator/api/zh/classes/Intersection.html 检测辅助类 if (cc.Intersection.pointInPolygon(touchLoc, this.collider.world.points)) { console.log("Hit!"); } else { console.log("No hit"); } }, this); }
collider 组件
点击属性检查器下面的添加组件按钮,然后从添加碰撞组件中选择需要的 Collider 组件,即可添加 collider 组件到节点上
【属性】
tag: 标签。当一个节点上有多个碰撞组件时,在发生碰撞后,可以使用此标签来判断是节点上的哪个碰撞组件被碰撞了
editing: 是否编辑此碰撞组件,只在编辑器中有效
一个节点上可以挂多个碰撞组件,这些碰撞组件之间可以是不同类型的碰撞组件
碰撞组件目前包括了 Polygon(多边形)、Circle(圆形)、Box(矩形)这几种碰撞组件,这些组件都继承自 Collider 组件
【多边形 Polygon】
offset 组件相对于节点的偏移量
points 组件的顶点数组
【圆形 circle】
offset 组件相对于节点的偏移量
radius 组件的半径
【矩形 box】
offset 组件相对于节点的偏移量
size 组件的长宽
好的代码像粥一样,都是用时间熬出来的