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
的信息来确认你的动画为什么糟糕。
我有一个球体,它是一个动态物体。我想为这个球体的比例设置动画,使其变大:
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
的信息来确认你的动画为什么糟糕。