Ios Swift/SceneKit-为游戏创建菜单/关卡选择场景的最佳实践

Ios Swift/SceneKit-为游戏创建菜单/关卡选择场景的最佳实践,ios,swift,scenekit,Ios,Swift,Scenekit,我对iOS级别的开发非常陌生,目前正在尝试创建我的第一个SceneKit游戏-但是,我不确定应该使用什么方法来创建“非3D”页面,如菜单、级别选择页面、设置等 我目前有一个GameViewController,我使用带有Overlyskcene的空SCNScene来显示我的SpriteKit菜单。单击菜单中的播放按钮后,我将切换到另一个空SCNScene,在那里我将显示级别列表。我是否应该再次使用ovelaySKSCene,这是正确的方法吗 我还注意到,即使我在转换到levelScene之前设置

我对iOS级别的开发非常陌生,目前正在尝试创建我的第一个SceneKit游戏-但是,我不确定应该使用什么方法来创建“非3D”页面,如菜单、级别选择页面、设置等

我目前有一个GameViewController,我使用带有Overlyskcene的空SCNScene来显示我的SpriteKit菜单。单击菜单中的播放按钮后,我将切换到另一个空SCNScene,在那里我将显示级别列表。我是否应该再次使用ovelaySKSCene,这是正确的方法吗

我还注意到,即使我在转换到levelScene之前设置了scnView.OverlySkscene=nil,如果我点击pla按钮的上一个位置,OverlyScene中显示的节点仍然包含playButton节点

请原谅我的新手问题,到目前为止,我还没有找到一个很好的例子来学习这类场景

到目前为止,我的代码是:

import UIKit
import QuartzCore
import SceneKit
import SpriteKit

class GameViewController: UIViewController {

var scnView: SCNView {
    let scnView = view as! SCNView
    scnView.backgroundColor = UIColor.init(displayP3Red: 0.98, green: 0.64, blue: 0.04, alpha: 1)

    return scnView
}

var menuScene: SCNScene!
var levelsScene: SCNScene!

var ground: SCNNode!
var light: SCNNode!
var scnScene: SCNScene!
var cameraNode: SCNNode!
var brickNode: SCNNode!
var selectedBrickNode: SCNNode!
var bricksArray : [SCNNode] = []

var controls: SKScene!
var levels: SKScene!

override func viewDidLoad() {
    super.viewDidLoad()
    setupView()
    showMenu()
    setupCamera()
}


override var shouldAutorotate: Bool {
    return true
}

override var prefersStatusBarHidden: Bool {
    return true
}



func setupView() {

    scnView.showsStatistics = true
    scnView.allowsCameraControl = false
    scnView.autoenablesDefaultLighting = true
}

func showMenu() {
    menuScene = SCNScene( )
    scnView.scene = menuScene
    self.controls = Controls(size: self.view.bounds.size)
    self.controls.isUserInteractionEnabled = false
    scnView.overlaySKScene = self.controls

}

func showLevels(){
    levelsScene = SCNScene()

    self.levels = Levels(size: self.view.bounds.size)
    self.levels.isUserInteractionEnabled = false
    scnView.overlaySKScene = self.levels

    let transition = SKTransition.push(with: .left, duration: 1.0)
    self.scnView.present(levelsScene
        , with: transition, incomingPointOfView: nil, completionHandler:nil)
}

func setupCamera(){
    cameraNode = SCNNode()
    let camera = SCNCamera()
    camera.zFar = 10000
    cameraNode.camera = camera
    cameraNode.position = SCNVector3(x: 0, y: 10, z: 20)

    let constraint = SCNLookAtConstraint(target: ground)
    constraint.isGimbalLockEnabled = true
    cameraNode.constraints = [constraint]


    let ambientLight = SCNLight()
    ambientLight.color = UIColor.darkGray
    ambientLight.type = SCNLight.LightType.ambient
    cameraNode.light = ambientLight


    menuScene.rootNode.addChildNode(cameraNode)

}

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {

    print("touch began  ")

    for touch: UITouch in touches {
        let location = touch.location(in: scnView.overlaySKScene!)
        let nodePressed = self.controls.atPoint(location)
        print(nodePressed.name)
        if (nodePressed.name == "playButton") {
            scnView.overlaySKScene = nil
            showLevels()
        }

    }

}

}
导入UIKit
进口石英砂
导入SceneKit
进口SpriteKit
类GameViewController:UIViewController{
变量scnView:scnView{
让scnView=查看为!scnView
scnView.backgroundColor=UIColor.init(displayP3Red:0.98,green:0.64,blue:0.04,alpha:1)
返回scnView
}
var menuScene:SCNScene!
var levelsScene:SCNScene!
变量地面:SCNNode!
变量灯:SCNNode!
变量scnScene:scnScene!
var cameraNode:SCNNode!
var brickNode:SCNNode!
变量selectedBrickNode:SCNNode!
var bricksArray:[SCNNode]=[]
var控件:SKScene!
变量级别:SKScene!
重写func viewDidLoad(){
super.viewDidLoad()
setupView()
showMenu()
设置摄影机()
}
覆盖变量应自动旋转:布尔{
返回真值
}
覆盖变量prefersStatusBarHidden:Bool{
返回真值
}
func setupView(){
scnView.showsStatistics=true
scnView.allowsCameraControl=false
scnView.autoenablesDefaultLighting=true
}
func showMenu(){
menuScene=SCNScene()
scnView.scene=menuScene
self.controls=控件(大小:self.view.bounds.size)
self.controls.isUserInteractionEnabled=false
scnView.overlyskscene=自我控制
}
func showLevels(){
levelsCENE=SCNScene()
self.levels=级别(大小:self.view.bounds.size)
self.levels.isUserInteractionEnabled=false
scnView.Overlyskscene=自我级别
let transition=SKTransition.push(带:。左,持续时间:1.0)
自我检查当前(水平)
,with:transition,incomingPointOfView:nil,completionHandler:nil)
}
func setupCamera(){
cameraNode=SCNNode()
让摄影机=SCNCamera()
camera.zFar=10000
cameraNode.camera=camera
cameraNode.position=SCInvector3(x:0,y:10,z:20)
let约束=SCNLookAtConstraint(目标:地面)
constraint.IsGimBallocked=true
cameraNode.constraints=[约束]
让环境光=SCNLight()
ambientLight.color=UIColor.darkGray
ambientLight.type=SCNLight.LightType.ambient
cameraNode.light=环境光
menuScene.rootNode.addChildNode(cameraNode)
}
覆盖func TouchesBegind(Touchs:Set,带有事件:UIEvent?){
打印(“触摸开始”)
对于触摸:UITouch in Touchs{
let location=touch.location(在:scnView.overlyskscene!)
让nodePressed=self.controls.atPoint(位置)
打印(nodePressed.name)
if(nodePressed.name==“播放按钮”){
scnView.overlaySKScene=零
showLevels()
}
}
}
}

“OverlyScene中显示的节点仍包含playButton节点…”

您正在将指向覆盖场景的指针设置为nil,在ToucheSStart中,您可以从覆盖场景中获取位置,但随后使用存储在“控件”属性中的skscene上的atPoint,因此它仍然可以找到播放按钮。因此,将touchesBeging中的self.controls替换为scnView.overlyskscene


也就是说,我不知道其他人通常认为什么是最佳实践,但就我个人而言,一旦我需要的不仅仅是几个按钮,我就不再使用spritekit叠加场景,而是使用常规UIKit元素在SCNView上构建菜单。

感谢您的反馈Xartec,非常感谢。您能否澄清“SCNView顶部的UIKit元素”是什么意思?最后,我决定使用storyboard创建其他ViewController,使用UIKit元素设计菜单/级别选择页面,并使用segues导航进出游戏控制器-这与您的方法类似吗?我要做的是在XIb文件中创建一个包含所需元素的UIView,然后将其添加为SCNView本身的常规子视图。所以我可以用一个3D场景作为背景,并在上面使用常规的UIKit元素。如果菜单场景完全是二维的,那么您仍然应该避免重叠场景。