场景Kit动态物理体穿过地板

5
我有一个带动态物理体的立方体和一个带运动学物理体的平面。当我把立方体放在平面上时,它会掉落并弹跳。
问题是:当立方体很小或很轻时,它会穿过平面。例如,0.1*0.1*0.1 的立方体可以正常工作,但 0.05*0.05*0.05 的就不行了。在这种情况下,我仍然会收到物理体接触通知。
以下是我创建几何图形的代码:
//cube
//when dimension is 0.1 everything is fine
float dimension = 0.05;
SCNBox *cube = [SCNBox boxWithWidth:dimension height:dimension length:dimension chamferRadius:0];
cube.materials = @[material];
SCNNode *node = [SCNNode nodeWithGeometry:cube];
node.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeDynamic shape:nil];
node.physicsBody.mass = 1;
node.physicsBody.categoryBitMask = phsicBodyCategoryCube;
node.physicsBody.collisionBitMask = phsicBodyCategoryPlane;
node.physicsBody.contactTestBitMask = phsicBodyCategoryPlane;

//plane
self.planeGeometry = [SCNBox boxWithWidth:100 height:0.01 length:100 chamferRadius:0
plane.physicsBody = [SCNPhysicsBody bodyWithType:SCNPhysicsBodyTypeKinematic
                    shape: [SCNPhysicsShape shapeWithGeometry:self.planeGeometry options:nil]];
plane.physicsBody.categoryBitMask = phsicBodyCategoryPlane;
plane.physicsBody.collisionBitMask = phsicBodyCategoryCube;
plane.physicsBody.contactTestBitMask = phsicBodyCategoryCube;

你尝试过更改 physicsWorld.timeStep 的值吗? - James P
没有,我没有改过它。 - ooOlly
3个回答

1
我很惊讶你会遇到碰撞。请参考SCNPhysicsBodyType文档 - 运动类型适用于您移动的物体(通过设置它们的位置等)以引起碰撞,但它们本身不受其他物体的碰撞影响。
如果将地板类型设置为静态, 您可能会看到更好的结果。静态物体不会移动(无论是由于物理相互作用还是您设置其位置),因此物理引擎可以更准确地检测其他物体与其碰撞。

编辑:需要注意的其他事项:

  • 使用 SCNPlane 而不是 SCNBox 作为地面。(请注意,如果有帮助,您可以创建形状与其可见几何图形不同的物理体)。对于许多物理引擎来说,检查“自上一帧以来是否有某个对象通过了这个无限边界?”比“在这一帧中某个对象是否在这个有限区域内?”更容易。
  • 为移动对象启用精确碰撞检测。

2
非常感谢!我误解了SCNPhysicsBodyTypeKinematic。但是当我尝试使用SCNPhysicsBodyTypeStatic时,立方体仍然穿过地板。 - ooOlly

1
最后我发现这一切都与SceneKit的物理模拟有关。如果方块下落得太快,在物理模拟步骤中它会与平面产生大量穿透。在这种情况下,SceneKit只是让它穿过平面而不是碰撞。当我将方块的速度改为一个小值时,它就会与平面碰撞。
我的解决方法是在发生大量过渡穿透时给方块一个向上的速度,这个速度是下落速度的30%。关键是调整方块的速度,直到发生碰撞。

你好,能否请您提供更多关于您如何解决问题的信息。 - Sergey Didanov

1

仅适用于球形物理形状

针对此问题,SCNPhysicsBody 具有特殊属性:continuousCollisionDetectionThreshold

例如,在涉及抛射物和目标的游戏中,如果小的抛射物在一个时间步内移动的距离超过目标的厚度,则可能穿过目标。通过将抛射物的 continuousCollisionDetectionThreshold 设置为其直径,可以确保 SceneKit 始终检测到抛射物与其他对象之间的碰撞。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接