SceneKit:如何在没有碰撞的情况下检测接触
我正在寻找最佳方法(性能方面)来检测两个不会在SceneKit物理世界中发生碰撞(不互相反弹)的物体之间的接触。
我看到SpriteKit有物理实体的contactTestBitMask
和collisionBitMask
,而SceneKit只有后者。 因此,当对象在SceneKit中有联系时,必须有另一种首选方式来获得通知。 我想在每个对象的每个帧中调用contactTestBetweenBody:andBody:options:
不是最好的方法吗?
更新在iOS 9.0中,Apple已将contactTestBitMask
添加到SCNPhysicsBody
。 所以这个问题很快就会过时。
这个问题值得一个完整的教程。 简而言之,每个物理主体都有一个categoryBitMask和collisionBitMask。
categoryBitMask这是代表身体的位。
collisionBitMask这是表示哪些实体与之碰撞的位。
默认情况下(当指定了physicsBody时),所有实体都会与kinematicBodyexception碰撞,后者表现特殊。 物体不会与它发生碰撞。 但是不要混淆,它可以在手动移动时与其他物体碰撞(例如用手指拖动)。
如何处理!!!
分配您的身体,无论是静态还是动态。 分配类别和碰撞掩码。 如果面具匹配则会发生碰撞。 一个例子怎么样!
这些身体相互碰撞
bodyA.physicsBody.categoryBitMask = 4; bodyB.physicsBody.categoryBitMask = 8; bodyA.physicsBody.collisionBitMask = 8; bodyB.physicsBody.collisionBitMask = 4;
这些不会发生碰撞
bodyA.physicsBody.categoryBitMask = 4; bodyB.physicsBody.categoryBitMask = 8; bodyA.physicsBody.collisionBitMask = 0; bodyB.physicsBody.collisionBitMask = 0;
注意到我使用了两个幂的类别。 这是因为contactDelegate使用按位AND进行比较。 如果您不理解,请按位阅读。 这真的会有所帮助。
这些物体没有物理碰撞
例子:你有一个穿过鬼魂的英雄,你想要知道它发生在没有任何一个受影响的情况下。 比如互相反弹。
bodyA.physicsBody.categoryBitMask = 4; bodyB.physicsBody.categoryBitMask = 8; bodyA.physicsBody.collisionBitMask = 0; bodyB.physicsBody.collisionBitMask = 0;
因此,下面的代码被设计为bodyA(你的英雄)穿过bodyB(ghost)。
bodyB.physicsField.categoryBitMask = 4
注意到上面是physicsField.catagoryBitMask。 它被赋予一个4,以便它与bodyA匹配。
let collisionField = SCNPhysicsField.customFieldWithEvaluationBlock(){ (_, _, _, _, _) in WHAT U WANT TO DO ON CONTACT } bodyB.physicsField = collisionField
不幸的是,physicsField不是几何体的形状。 如果将physicsField属性usesEllipsoidalExtent设置为“true / yes”,则默认为其边界框或球体/椭圆的形状
可以使用physicsFields halfExtent属性更改效果区域,如此…
bodyB.physicsField.halfExtent = SCNVector3Make(.5, .5, .5)
以上将把(2,2,2)大小的盒子的范围扩展到(2.5,2.5,2.5)。
编辑 :如果他们仍然发生碰撞,请尝试从bodyB中删除物理体(这将从节点中删除所有物理模拟)。 只要正确分配了catagory和碰撞位掩码,我认为这不会是一个问题。
这是我能找到的最佳方法。 在Apple文档的支持下,所有编码都来自我的头脑,所以可能不完全正确,但我希望这有帮助!
我发现最好的方法是将质量设置在一个运动体上,使另一个物体通过它。
sensorBox.physicsBody.mass = 0.00000000001; //超微小质量使其成为“传感器”
不要忘记你的场景的物理世界可以称之为“contactTestBetweenBody:andBody:withOptions …这很有效。
用法
[myScene.physicsWorld contactTestBetweenBody:(SCNPhysicsBody *) andBody:(SCNPhysicsBody *) options:(NSDictionary *)];