SceneKit - SCNPhysicsBody不匹配SCNPhysicsShape

5
我有一个非常简单的场景:一个具有动态物理体的立方体和一个具有静态物理体的平面。 当立方体下落并撞击地面时,两个物体之间会出现可见的间隙,您可以在此处观看视频:
我尝试了所有不同的SCNPhysicsShapeTypeKey组合,并尝试将SCNPhysicsBody的形状设置为nil(文档说:“将其保留为nil将让系统决定并使用最有效的边框表示”),但是没有能够消除这个间隙。
    // ...
    // plane physics
    var body = SCNPhysicsBody(type: SCNPhysicsBodyType.Static, shape: SCNPhysicsShape(geometry: result.node!.geometry!, options: [SCNPhysicsShapeTypeKey:SCNPhysicsShapeTypeConvexHull]));
    result.node!.physicsBody = body;
} else {
    // cube physics
    var body = SCNPhysicsBody(type: SCNPhysicsBodyType.Dynamic, shape: SCNPhysicsShape(node: result.node!, options: [SCNPhysicsShapeTypeKey:SCNPhysicsShapeTypeConvexHull]));
     result.node!.physicsBody = body;
}

我已经检查了我的dae文件(附在这里),并按照此问题的要求应用了所有比例/变换,但结果仍然相同。
我认为我在这里遗漏了一些明显的东西,有什么想法吗?

你能打开统计信息并添加一个截图,让我们可以看到物理形状吗? - David Rönnqvist
1
我使用您的DAE文件重现了您的问题。使用显式形状时,它可以正常工作(立方体:physicsShape = [SCNPhysicsShape shapeWithGeometry:[SCNBox boxWithWidth:0.5 height:0.5 length:0.5 chamferRadius:0] options:nil] - 平面:planeNode = [SCNNode nodeWithGeometry:[SCNPlane planeWithWidth:10 height:10]]; planeNode.eulerAngles = SCNVector3Make(-M_PI_2, 0, 0); SCNNode *parentNode = [SCNNode node]; [parentNode addChildNode:planeNode]; plane.physicsBody.physicsShape = [SCNPhysicsShape shapeWithNode:parentNode options:nil])。 - Toyos
我不知道默认的凸包在这个特定场景中出了什么问题,但值得向苹果提交一个错误报告。 - Toyos
@DavidRönnqvist 在iOS上的showStatistics不会像OS X那样绘制物理体,或者还有其他标志吗? - N S
你修好了吗?我无法正确地表示圆柱体的物理实体。这真让人沮丧 :( - Mihai Fratu
2个回答

5

@Toyos提到提交错误报告的建议很好。然而,在这种情况下最好不要依赖于默认的凸包生成。

简而言之:尽可能使用基本参数化实体(或其复合形状)作为物理形状。

当你从自定义几何图形生成物理形状时(即从DAE加载),SceneKit必须建立一个复杂的数据结构来描述该几何图形的凸包,每渲染一帧都需要通过该数据结构进行碰撞检测(即高达60次/秒)。

相比之下,如果你使用内置的参数化形状(如SCNBoxSCNSphere等),则向SceneKit发出信号,它可以使用该形状的理想化表示,而不是基于其多边形网格的复杂数据结构。

以极端的例子来说,考虑一个球体:渲染一个看起来不错的球体需要大量的多边形。如果你将这样的网格输入到碰撞检测算法中,要么它会陷入顶点数据的复杂性中,要么就必须生成一个形状的近似值,该近似值比较简单但不够准确(例如,一个十二面体)。另一方面,球体是碰撞检测中最简单的形状——找出给定点是否在球体内只需要获取该点到球体中心的距离,并查看它是否小于半径即可。(如果做得正确,甚至不需要担心sqrt的代价。)


没想到要这么做,但我理解其中的原因。关于将其打包成游戏,我应该拥有一个包含dae对象标识符和有关我想要添加的物理体的属性的plist,然后只需迭代即可吗?还是有更优雅的实现您的解决方案的方法... - N S
你已经必须遍历你的DAE结构来有条件地添加物理体了,对吧?记住哪些节点需要哪些基本形状只是这个过程的延伸。此外,请注意,当你使用NSCoding序列化场景时,所有的物理相关内容都会被保存下来——如果你不想在运行时进行设置,你可以在OS X上编写一个小应用程序,在开发时完成它。 - rickster

0

你应该将 SCNPhysicsShape.Option.collisionMargin 设置为 0.0

result.node!.physicsBody = SCNPhysicsBody(
    type: .dynamic, 
    shape: SCNPhysicsShape(
        node: result.node!, 
        options: [
            .collisionMargin: 0.0,
            .type: SCNPhysicsShape.ShapeType.convexHull
        ]
    )
)

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