从 ViewController 访问 SceneKit-Node
Accessing SceneKit-Node from ViewController
我正在尝试在 Swift 中构建一个 SceneKit-App。这个应用程序应该有一个 SpriteKit-Overlay。我的问题是,我可以从 ViewController 中的 SpriteKit 访问 LabelNode,但不能更改 SceneKit 中 Cube-Node 的位置值,尽管我可以访问该节点。因为我是新手,所以如果有人能指出正确的方向,那就太好了。
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)
}
}
当您调用 SceneKitScene().cubeNode.position = SCNVector3(0,10,0)
时,您正试图在新创建的 SceneKitScene
上更改 cubeNode.position
。
尝试将您的 GameViewController
更改为:
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)
}
}
这会创建一个新的实例变量来保存您当前的 SceneKitScene
(与您对当前 SpriteKitOverlay
所做的相同)。然后你可以使用这个变量来访问和更新当前 cubeNode
在屏幕上的位置。
我正在尝试在 Swift 中构建一个 SceneKit-App。这个应用程序应该有一个 SpriteKit-Overlay。我的问题是,我可以从 ViewController 中的 SpriteKit 访问 LabelNode,但不能更改 SceneKit 中 Cube-Node 的位置值,尽管我可以访问该节点。因为我是新手,所以如果有人能指出正确的方向,那就太好了。
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)
}
}
当您调用 SceneKitScene().cubeNode.position = SCNVector3(0,10,0)
时,您正试图在新创建的 SceneKitScene
上更改 cubeNode.position
。
尝试将您的 GameViewController
更改为:
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)
}
}
这会创建一个新的实例变量来保存您当前的 SceneKitScene
(与您对当前 SpriteKitOverlay
所做的相同)。然后你可以使用这个变量来访问和更新当前 cubeNode
在屏幕上的位置。