1、SCNPhysicsBody
要讲解碰撞检测和接触检测之前,首先先了解一个概念:SCNPhysicsBody
每一个物体都属于一种类型:staticBody、dynamicBody、kinematicBody
(1)staticBody
是一个不受外力或碰撞影响的物体,不能移动。比如地板、墙壁等。
必须把它附加到SCNNode
的physicsBody
属性上。附加到节点上后,会自动为节点创建物理形状。
(2)dynamicBody
是一个可以受力和碰撞影响的物体,其余同staticBody
(3)kinematicBody
是一个不受外力或碰撞影响的物理实体,但它会在移动时造成碰撞影响其他物体。
其余同staticBody
SCNPhysicsBody就是这个物体的受力类型,也可以说是物理属性
2、物体之间的碰撞检测
(1)每一个物体(SCNNode)在SCNPhysicsBody这个属性对象里面都会设置有三个码:
contactTestBitMask:允许可以跟哪些物体进行接触检测
collisionBitMask :碰撞掩码,设置允许可以跟那些物力进行碰撞
categoryBitMask:类别掩码,也就是自己的唯一标志
(2)物体之间发生碰撞的唯一条件
用SCNNode各自双方的碰撞掩码(collisionBitMask)和类别掩码(categoryBitMask)分别做与运算,若都为非0,则发生碰撞
例如:
其中一个物体:
boyNode.physicsBody = [SCNPhysicsBody dynamicBody];
boyNode.physicsBody.contactTestBitMask = 0b110;
boyNode.physicsBody.collisionBitMask = 0b01;
boyNode.physicsBody.categoryBitMask = 0x101;
另外一个物体:
bNode.physicsBody = [SCNPhysicsBody staticBody];
bNode.physicsBody.contactTestBitMask = 0b111;
bNode.physicsBody.collisionBitMask = 0x11;
bNode.physicsBody.categoryBitMask = 0b11;
碰撞掩码(collisionBitMask)和类别掩码(categoryBitMas)做与运算:
(boyNode的categoryBitMas)& (bNode的collisionBitMask) != 0
0x101 & 0x11 != 0
并且:
(bNodee的categoryBitMas)& (boyNode的collisionBitMask) != 0
0b11 & 0b01 != 0
两个同时不等于0,所以他们会发生碰撞
(3)物体之间触发接触的消息回调的唯一条件
用SCNNode各自双方的接触掩码(contactTestBitMask)和类别掩码(categoryBitMask)分别做与运算,若都为非0,则发生接触回调
例如:
其中一个物体:
boyNode.physicsBody = [SCNPhysicsBody dynamicBody];
boyNode.physicsBody.contactTestBitMask = 0b110;
boyNode.physicsBody.collisionBitMask = 0b01;
boyNode.physicsBody.categoryBitMask = 0x101;
另外一个物体:
bNode.physicsBody = [SCNPhysicsBody staticBody];
bNode.physicsBody.contactTestBitMask = 0b111;
bNode.physicsBody.collisionBitMask = 0x11;
bNode.physicsBody.categoryBitMask = 0b11;
接触掩码(contactTestBitMask)和类别掩码(categoryBitMas)做与运算:
(boyNode的contactTestBitMask)& (bNode的collisionBitMask) != 0
0b110 & 0x11 != 0
并且:
(bNodee的contactTestBitMask)& (boyNode的collisionBitMask) != 0
0b111 & 0b01 != 0
两个同时不等于0,所以他们会发生接触消息回调,也就是会执行下面三个代理方法:
- (void)physicsWorld:(SCNPhysicsWorld *)world didBeginContact:(SCNPhysicsContact *)contact;
- (void)physicsWorld:(SCNPhysicsWorld *)world didUpdateContact:(SCNPhysicsContact *)contact;
- (void)physicsWorld:(SCNPhysicsWorld *)world didEndContact:(SCNPhysicsContact *)contact;
不过要执行代理方法,记得要设置代理: