cocos creator 不用物理系统,自己检测碰撞遇到的坑
这是官方给的碰撞出发回调 ,other和self分别代表碰撞的对方node,和我的node
node中包含了world.aabb,是碰撞框,方便计算用的,里边有一些属性
onCollisionStay(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;
// console.log("------世界碰撞区域-----", t, aabb.x, aabb.y, aabb.width, aabb.height);
// 以下属性为圆形碰撞组件特有属性
var r = world.radius;
var p = world.position;
}
作为以前写unity的我来说,一直认为 aabb中的x,y是碰撞框的中心点,导致计算碰撞错误
至于x,y具体表示碰撞框什么情况下的位置,我也不得而知了
下面这个如图是aabb中的数据,-112,870是aabb.center中的坐标,也就是碰撞框的中心点,
下面的x:-161,y:829是aabb.x aabb.y的位置
这两个位置是差别还是有不少呢
这个导致我计算是否碰撞一直出错
一开始是用中心点加宽的一半,计算出最大x,其实这里aabb.xMax就是最大x
还有xMinx,xMiny等等都是提供好的
写这篇的目的主要是要记住这次教训
至于为什么aabb中的x,y和center不一样,希望有知道的朋友可以在下方解释一下,谢谢啦
最后贴上我自己计算角色碰撞后回弹的代码
let otherR = other.world.aabb.xMax;// 碰撞物的右边x
let otherL = other.world.aabb.xMin;// 碰撞物的左边x
let otherU = other.world.aabb.yMax;// 碰撞物的上边x
let otherD = other.world.aabb.yMin;// 碰撞物的下边x
let myR = self.world.aabb.xMax;// 我的右边x
let myL = self.world.aabb.xMin// 我的左边x
let myU = self.world.aabb.yMax;// 我上边x
let myD = self.world.aabb.yMin;// 我的下边x
if(this.lookAt===GameConfig.RoleDirection.left|| this.lookAt === GameConfig.RoleDirection.right)
{// 角色当前朝向是左或者右
if((myR-otherL>=0&&myR-otherL<60)||(otherR-myL>=0&&otherR-myL<60))
{// 我的最大x大于他的最小x,右侧撞到// 他的最大x大于我的最小x,左侧撞到
dir = this.lookAt; // 记录撞到的方向
}
// 没有找到方向
if(dir===GameConfig.RoleDirection.none)
{
// 还要看看上下方向有没有撞到
if(myU-otherD>=0&&myU-otherD<60)
{// 我的最大y大于他的最小y,上侧撞到
dir = GameConfig.RoleDirection.up;
}
if(otherU-myD>=0&&otherU-myD<60)
{// 他的最大y大于我的最小y,下侧撞到
dir = GameConfig.RoleDirection.down;
}
}
}
if(this.lookAt===GameConfig.RoleDirection.up|| this.lookAt === GameConfig.RoleDirection.down)
{// 角色当前朝向是上或者下
if((myU-otherD>=0&&myU-otherD<60)||(otherU-myD>=0&&otherU-myD<60))
{// 我的最大y大于他的最小y,上侧撞到//他的最大y大于我的最小y,下侧撞到
dir = this.lookAt;
}
if(dir===GameConfig.RoleDirection.none)
{// 左右方向没有撞到
// 还要看看左右方向有没有撞到
if(myR-otherL>=0&&myR-otherL<60)
{// 我的最大x大于他的最小x,右侧撞到
dir = GameConfig.RoleDirection.right;
}
if(otherR-myL>=0&&otherR-myL<60)
{// 他的最大x大于我的最小x,左侧撞到
dir = GameConfig.RoleDirection.left;
}
}
}
先根据角色当前朝向,确定是不是当前方向撞了,如果不是当前方向,再判断另外两个方向是不是撞到了,这样记录dir是撞到的方向
然后得到与dir相反的方向,让角色往dir反方向回弹一下,这里的代码是碰撞的回调,只要有接触碰撞,就回弹一下,直到没有接触
这里是因为帧同步不能用物理系统自己检测碰撞,不同机型会产生误差,所以需要自己根据碰撞器计算是否撞到了,但是这个回弹效果也没有办法,因为是撞到后
才能判断,不能让角色擦其他障碍物走,所以肯定要回弹一下,回弹后再让角色继续走,撞到的时候记录这个方向是不能走的,可能另外两个方向也擦着边,可能只有反方向可以走
回弹期间不可以走