1

I'm trying to build an SceneKit-App in Swift. This App should have an SpriteKit-Overlay. My problem is, that i can access the LabelNode from SpriteKit inside my ViewController, but cannot change the position-value of the Cube-Node in SceneKit, although i can access the node. Because i'm a newbie it would be very nice, if anyone could point me in the right direction.

class GameViewController: UIViewController {

    var sceneView: SCNView!
    var spriteScene: SpriteKitOverlay!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        self.sceneView.scene = SceneKitScene()
        self.sceneView.backgroundColor = UIColor.brownColor()
        self.view.addSubview(self.sceneView)

        self.spriteScene = SpriteKitOverlay(size: self.view.bounds.size)
        self.sceneView.overlaySKScene = self.spriteScene

        SceneKitScene().cubeNode.position = SCNVector3(0,10,0)
        spriteScene.labelTest.text = "Changed label"
        print(SceneKitScene().cubeNode.position)
    }
}

class SpriteKitOverlay: SKScene {

    var labelTest: SKLabelNode!

    override init(size: CGSize) {
        super.init(size: size)

        self.labelTest = SKLabelNode(text: "Label text")
        self.labelTest.fontColor = UIColor.whiteColor()
        self.labelTest.fontSize = 24
        self.labelTest.position = CGPoint(x: size.width/2, y: size.height/2)

        self.addChild(self.labelTest)

    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

}


class SceneKitScene: SCNScene {

    var cubeNode: SCNNode!
    var cameraNode: SCNNode!
    var lightNode: SCNNode!

    override init() {
        super.init()

        let cube = SCNBox(width: 3, height: 3, length: 3, chamferRadius: 0)
        let cubeMaterial = SCNMaterial()
        cubeMaterial.diffuse.contents = UIColor.blueColor()
        cube.materials = [cubeMaterial]
        self.cubeNode = SCNNode(geometry: cube)
        self.cubeNode.position = SCNVector3(0,0,0)
        self.cubeNode.runAction(SCNAction.repeatActionForever(SCNAction.rotateByX(0, y: 0.01, z: 0, duration: 1.0/60.0)))

        let camera = SCNCamera()
        camera.xFov = 60
        camera.yFov = 60

        let ambientLight = SCNLight()
        ambientLight.type = SCNLightTypeAmbient
        ambientLight.color = UIColor(red: 0.2, green: 0.2, blue: 0.2, alpha: 1.0)

        let cameraConstraint = SCNLookAtConstraint(target: self.cubeNode)
        cameraConstraint.gimbalLockEnabled = true

        self.cameraNode = SCNNode()
        self.cameraNode.camera = camera
        self.cameraNode.constraints = [cameraConstraint]
        self.cameraNode.light = ambientLight
        self.cameraNode.position = SCNVector3(x: 5, y: 5, z: 5)

        let omniLight = SCNLight()
        omniLight.type = SCNLightTypeOmni

        self.lightNode = SCNNode()
        self.lightNode.light = omniLight
        self.lightNode.position = SCNVector3(x: -3, y: 5, z: 3)

        self.rootNode.addChildNode(self.cubeNode)
        self.rootNode.addChildNode(self.cameraNode)
        self.rootNode.addChildNode(self.lightNode)
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }


}
Ebrahim Ghasemi
  • 5,850
  • 10
  • 52
  • 113
panjabi
  • 13
  • 3
  • on a related note see rickster's answer on whether or not you should subclass `SCNScene`: http://stackoverflow.com/a/34536248/2997825 – mnuages Mar 14 '16 at 10:10

1 Answers1

1

When you call SceneKitScene().cubeNode.position = SCNVector3(0,10,0), you are trying to change cubeNode.position on a newly created SceneKitScene.

Try changing your GameViewController to:

class GameViewController: UIViewController {

    var sceneView: SCNView!
    // create new instance variable to hold current sceneKitScene
    var sceneKitScene: SceneKitScene!
    var spriteScene: SpriteKitOverlay!

    override func viewDidLoad() {
        super.viewDidLoad()

        self.sceneView = SCNView(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: self.view.frame.height))
        // save SceneKitScene to instance variable
        self.sceneKitScene = SceneKitScene()
        self.sceneView.scene = self.sceneKitScene
        self.sceneView.backgroundColor = UIColor.brownColor()
        self.view.addSubview(self.sceneView)

        self.spriteScene = SpriteKitOverlay(size: self.view.bounds.size)
        self.sceneView.overlaySKScene = self.spriteScene

        // update cubeNode position in active sceneKitScene
        sceneKitScene.cubeNode.position = SCNVector3(0,10,0)
        spriteScene.labelTest.text = "Changed label"
        print(SceneKitScene().cubeNode.position)
    }
}

This creates a new instance variable to hold your current SceneKitScene (same as you did with your current SpriteKitOverlay). Then you can use this variable to access and update the position of the current cubeNode on screen.

Dion Larson
  • 868
  • 8
  • 14