SceneKit 不会缩放动态主体

SceneKit won't scale a dynamic body

我有一个球体,它是一个动态物体。我想为这个球体的比例设置动画,使其变大:

let sphere = SCNNode(geometry: SCNSphere(radius: 1))
scene.rootNode.addChildNode(sphere)
sphere.physicsBody = SCNPhysicsBody.dynamicBody()
sphere.runAction(SCNAction.scaleTo(10, duration: 1))

然而,这似乎不起作用。球体由于重力而下落,但保持相同大小。如果我注释掉为球体提供物理体的那一行,那么缩放动画就会像它应该的那样播放。

即使没有动画也能观察到这种奇怪的现象。简单地直接改变球体的比例是行不通的:

let sphere = SCNNode(geometry: SCNSphere(radius: 1))
scene.rootNode.addChildNode(sphere)
sphere.physicsBody = SCNPhysicsBody.dynamicBody()
sphere.scale = SCNVector3(x: 10, y: 10, z: 10)

球体下降但半径仍为 1。除非在添加其物理体之前缩放球体。在这种情况下,球体开始缩放到 10 并下降,保持其半径为 10。

有趣的是,据推测在动画 运行 之后,通过打印出球体的比例进一步检查,发现比例确实发生了变化,除非物理体被移除,否则它是不可见的:

let sphere = SCNNode(geometry: SCNSphere(radius: 1))
scene.rootNode.addChildNode(sphere)
sphere.physicsBody = SCNPhysicsBody.dynamicBody()
sphere.runAction(SCNAction.scaleTo(10, duration: 1), completionHandler: {() in
    println(sphere.scale.x)
    sphere.physicsBody = nil
})

为什么不能改变动态body的比例? (请注意,静态和运动物体可以很好地缩放。)是否可以通过某种方式实现这一目标?

您不仅需要一个 "scaling velocity" 来与其他对象交互,因为一个对象会改变大小,您还需要一个 "scaling force"。它应该在多大程度上推动它在生长过程中碰撞的东西?如果它处于取决于质量的情况下,比如在跷跷板上保持平衡,会发生什么?

游戏引擎已经是对现实世界物理的松散近似,所以让他们自己弄清楚蚁人物理有点牵强。如果他们能做到这一点,他们也可能会开始制造杀手机器人,而那会毁了你的一天。 :)

无论如何,根据您希望扩大的球体如何影响事物,您有几种选择。一种是每隔一段时间删除并重新创建物理体:

let duration = 5.0
node.runAction(.customActionWithDuration(duration, actionBlock: { node, progress in
    let scale = 1.0 + progress / CGFloat(duration)
    node.physicsBody = nil
    node.scale = SCNVector3(x: scale, y: scale, z: scale)
    node.physicsBody = .dynamicBody()
}))

每帧都这样做,这可能代价高昂——你可能想在 progress 上设置一些门控,这样它就不会那么频繁发生。 (并且根据球体大小变化需要发生的其他效果,您可以在重新创建物理体时设置诸如质量之类的东西。)

另一种选择可能是查看 SCNPhysicsField。使用径向重力场创建一个区域,将所有东西推出其影响区域,然后为其参数设置动画以随时间改变大小和强度。

我 运行 在尝试缩放我从 .scn 文件导入的模型时进入这个。就像 rickster 所做的那样,我最终移除了物理体,缩放了形状然后重新连接了物理体。这仅在启动期间完成,因此对性能影响不大。

物理模拟是implicit/explicit动画或动作之外的一种动画。因此,当将动画 属性 更改为受影响的节点物理时,请特别考虑节点的动画状态。

另一方面,sceneKit 将物理模拟的结果应用于 presentationNode,代表节点的当前渲染状态。你可以查看 presentationNode 的信息来确认你的动画为什么糟糕。