0

I want to detect when an SCNNode stops moving in my Scenekit game written in swift.

I have a floor with a node falling towards it by gravity. the node hits the floor, bounces and then lands and settles in a stationary position.

I need to add a function that watches the SCNNode and does something when it comes to rest.

In the final game i will have different SCNNodes falling at different speeds and so need a function that relies solely on looking at the motion of the node rather than waiting for a set time.

Is there anything built in to scenekit that would be of use? If not is there anyway to use some form of timer to call a function every half second? how would i set up a timer and how would i check the SCNNode to see if it has stopped moving?

EDIT:

As was pointed out, my question is the same as SceneKit SCNPhysicsBody get notified of resting. that questioner was using obj-c though and im using swift. i found that the answer in a comment here seems much better and worked for me.

  • Possible duplicate of [SceneKit SCNPhysicsBody get notified of resting](https://stackoverflow.com/questions/41309204/scenekit-scnphysicsbody-get-notified-of-resting) – James P Mar 19 '19 at 10:21
  • An alternative to that linked answer would be to implement one of the `SCNSceneRendererDelegate` methods and check if the velocity of the node is close to zero. – James P Mar 19 '19 at 10:23

2 Answers2

1

The comment from James P solved this for me.

Using SCNSceneRendererDelegate means i can run code repeatedly every render cycle to check if the node has stopped moving.

I then ran into this problem SceneKit: isResting never returns true. isResting was always false. the only way to get what i needed was to use Int(SCNNode.physicsBody?.velocity.z) and when that is zero my node is fully resting on the floor

0

The had a simulation where many objects jiggle, looking for a stable position. In my case, I simply looked for a condition where all 3 velocities were less than some threshold.

Set up a SCNSceneRedererDelegate, and in there, do something like this:

sceneView.scene?.rootNode.childNodes(passingTest: {
  (node, stop) -> Bool in
  if abs(node.physicsBody!.velocity.x)<0.001 &&
     abs(node.physicsBody!.velocity.y)<0.001 &&
     abs(node.physicsBody!.velocity.z)<0.001 {
     //In here, you know it has stopped
     ...
     return true
  }
  return false
  })
cdeerinck
  • 688
  • 6
  • 17