>我有一个非常简单的场景:一个带有动态物理体的立方体和一个带有静态物理体的平面。当立方体掉落并撞击地面时,两个物体之间有一个可见的间隙,你可以在这里看到这个视频:
我已经尝试了所有不同的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 文件(附在这里(并根据此问题应用了所有缩放/转换,但结果相同。
我想我在这里错过了一些明显的东西,有什么想法吗?
>@Toyos关于提交错误的评论是个好主意。但是,在这种情况下,最好不要依赖默认的凸包生成。
TLDR:尽可能使用原始参数实体(或其化合物(作为物理形状。
从自定义几何体(即从 DAE 加载(生成物理形状时,SceneKit 必须构建一个描述该几何体的凸包的复杂数据结构,并且必须通过该数据结构对每个渲染帧执行冲突检测(即每秒最多 60 次(。
当您改用其中一个内置参数化形状(SCNBox
、SCNSphere
等(时,您会向 SceneKit 发出信号,表明它可以使用该形状的理想化表示形式,而不是基于其多边形网格的复杂数据结构。
举一个极端的例子,考虑一个球体:渲染一个看起来不错的球体需要大量的多边形。如果将这样的网格馈送到碰撞检测算法中,它要么陷入顶点数据的复杂性,要么必须生成不太复杂但不太准确的形状近似值(例如十二面体(。另一方面,球体是最简单的碰撞检测形状——要确定给定点是否在球体内,您需要做的就是获取从该点到球体中心的距离,并查看它是否小于半径。(做对了,你甚至不用担心sqrt
成本。
您应该为 SCNPhysicsShape.Option.collisionMargin
设置0.0
。
result.node!.physicsBody = SCNPhysicsBody(
type: .dynamic,
shape: SCNPhysicsShape(
node: result.node!,
options: [
.collisionMargin: 0.0,
.type: SCNPhysicsShape.ShapeType.convexHull
]
)
)