1
votes

I need to attach a SCNCamera to a SCNNode so that whenever the node (ball) moves, the camera follows it.

So far I managed to do it by constantly moving the camera when physics is updated, but its not very efficient and has some delay.

    func physicsWorld(world: SCNPhysicsWorld, didBeginContact contact: SCNPhysicsContact)
    {
        var cameraP = SCNVector3(x: ball.presentationNode().position.x, y: ball.presentationNode().position.y + 5, z: ball.presentationNode().position.z + 12)
        camera.constraints = nil
        camera.position = cameraP
        camera.constraints = [SCNLookAtConstraint(target: ball)]
    }

I read some information about SCNTransformationConstraint that could "attach" the camera to the node but I found no working example.

I can't just attach the camera to the node as I want to adjust the position of the camera.

Thanks.

Edit: (To Moustach)

I tried to do that using:

optional func renderer(_ renderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: NSTimeInterval)
{
    println("called")
}

but I get an error saying: Extraneous '_' in parameter: 'rendered' has no keyword argument name

Edit 2 (working):

With Moustach's advice, we were able to make this work efficiently.

The camera position is now updated on:

func renderer(aRenderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: NSTimeInterval)
{
    println("called")
}

Furthermore, a new SCNNode was created as a rootNode of the camera node to hold its position.

Setting up the camera now looks like this:

        let lookAtBallConstraint = SCNLookAtConstraint(target: ball)
        lookAtBallConstraint.gimbalLockEnabled = true

        let tempCam = SCNCamera()
        tempCam.zFar = 5000
        camera = SCNNode()
        camera.camera = tempCam
        camera.position = SCNVector3(x: 0, y: 0, z: 0)
        camera.constraints = [lookAtBallConstraint]

        cameraPosition = SCNNode()
        cameraPosition.position = SCNVector3(x: 0, y: 5, z: 12)
        cameraPosition.addChildNode(camera)

And now the camera moving function looks like this:

func renderer(aRenderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: NSTimeInterval)
{
    var cameraP = SCNVector3(x: ball.presentationNode().position.x, y: ball.presentationNode().position.y + 5, z: ball.presentationNode().position.z + 12)
    cameraPosition.position = cameraP
}
1

1 Answers

2
votes

It seems you are adding a new constraint every time the ball touches anything, which probably happens a lot every frame!

Here's what you should do:

  • Move the constraint creation to somewhere it will be only set once, such as the init
  • Move the position update code to the renderer delegate so that it only get called once a frame, just after the physics have been calculated.

You should see a huge performance update!

Edit: try this

func renderer(aRenderer: SCNSceneRenderer, didSimulatePhysicsAtTime time: NSTimeInterval){
    println("called")
}