I have a sphere that is a dynamic body. I would like to animate the scale of this sphere so that it grows in size:
let sphere = SCNNode(geometry: SCNSphere(radius: 1))
scene.rootNode.addChildNode(sphere)
sphere.physicsBody = SCNPhysicsBody.dynamicBody()
sphere.runAction(SCNAction.scaleTo(10, duration: 1))
However, this does not seem to work. The sphere falls down due to gravity, but stays the same size. If I comment out the line that gives the sphere its physics body, then the scaling animation plays out like it should.
This strange phenomenon is even observed without an animation. Simply changing the scale of the sphere directly doesn't work:
let sphere = SCNNode(geometry: SCNSphere(radius: 1))
scene.rootNode.addChildNode(sphere)
sphere.physicsBody = SCNPhysicsBody.dynamicBody()
sphere.scale = SCNVector3(x: 10, y: 10, z: 10)
The sphere drops down but remains with a radius of 1. Unless the sphere is scaled before its physics body is added. In which case, the sphere starts out scaled to 10 and drops down, keeping its radius of 10.
Interestingly, upon further inspection by printing out the sphere's scale after the animation has supposedly run, it is observed that the scale has indeed changed, it's just not visible unless the physics body is removed:
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
})
Why is it not possible to change the scale of dynamic body? (Note that static and kinematic bodies will scale just fine.) Is it possible to achieve this in some way?
You wouldn't just need a "scaling velocity" to interact with other objects as one changes size, you'd need a "scaling force". How strongly should it push on things that it collides with while growing? And what happens if it's in a situation that depends on its mass, like balancing on a seesaw?
Game engines are already loose approximations of real-world physics, so asking them to figure out Ant-Man physics on their own is a bit of a stretch. If they could do that, they could probably also start building killer robots, and that'd kinda ruin your day. :)
Anyway, depending on how you want your expanding sphere to affect things, you have a few options. One is to delete and re-create the physics body at intervals:
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()
}))
This does it every frame, which could be costly — you might want to throw some gating on progress
in there so it happens less often. (And depending on what other effects need to happen as a result of the sphere changing size, you could set things like mass when you re-create the physics body.)
Another option might be to look at SCNPhysicsField
. Use a radial gravity field to make a region that shoves everything out of its area of influence, then animate its parameters to change size and strength over time.
I ran into this when trying to scale a model I was importing from a .scn file. Just like rickster did, I ended up removing the physics body, scaled the shape & then re-attached the physics body. This was only done during startup, so not a big performance impact.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With