SceneKit:如何检测没有碰撞的接触

时间:2014-07-31 18:03:51

标签: ios objective-c macos swift scenekit

我正在寻找最好的方法(性能方面)来检测两个不会在SceneKit物理世界中发生碰撞(不互相反弹)的物体之间的接触。

我看到SpriteKit对物理实体有contactTestBitMaskcollisionBitMask,而SceneKit只有后者。因此,当对象在SceneKit中有联系时,必须有另一种首选方式来获得通知。我想在每个帧中为每个对象调用contactTestBetweenBody:andBody:options:不是最好的方法吗?

更新 在iOS 9.0中,Apple已将contactTestBitMask添加到SCNPhysicsBody。所以这个问题很快就会过时。

3 个答案:

答案 0 :(得分:11)

这个问题值得一个完整的教程。简而言之,每个物理主体都有一个categoryBitMask和collisionBitMask。

<强> categoryBitMask 这是代表身体的一点。

<强> collisionBitMask 这是表示哪些实体与之碰撞的位。

默认情况下(当指定了physicsBody时),所有实体都会与kinematicBody异常发生碰撞,后者表现特殊。物体不会与它发生碰撞。但不要混淆,手动移动时可能会与其他物体发生碰撞(例如用手指拖动)。

如何处理!!!

指定您的身体是静态还是动态。分配类别和碰撞掩码。如果面具匹配则会发生碰撞。一个例子怎么样!

这些身体相互碰撞

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(幽灵)。

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中删除物理体(这将从节点中删除所有物理模拟)。只要正确分配了类别和碰撞位掩码,我认为这不会是一个问题。

这是我能找到的最佳方法。在Apple文档的支持下,所有编码都来自我的脑海,所以可能不完全正确,但我希望这会有所帮助!

答案 1 :(得分:2)

我发现最好的方法是将质量设置在运动体上,使另一个物体穿过它。

sensorBox.physicsBody.mass = 0.00000000001; //超微质量使它成为“传感器”

答案 2 :(得分:0)

不要忘记你的场景的物理世界可以调用“contactTestBetweenBody:andBody:withOptions ...这很有用。

用法

[myScene.physicsWorld contactTestBetweenBody:(SCNPhysicsBody *) andBody:(SCNPhysicsBody *) options:(NSDictionary *)];