如何在 SKScene 中引用我的 UIViewController?

How to do a reference of my UIViewController in the SKScene?

我需要将我的 UIViewController 作为我的 GameScene 的 属性。 所以在调用 presentScene 之前,我用 UIViewController 设置了 属性。

我的 UIViewController class:

class GameViewController: UIViewController {

    var scene:GameScene!

    override func viewDidLoad() {
        super.viewDidLoad()

        if let scene = GKScene(fileNamed: "GameScene") {

            // Get the SKScene from the loaded GKScene
            if let sceneNode = scene.rootNode as! GameScene? {

                self.scene=sceneNode

                // Set the scale mode to scale to fit the window
                sceneNode.scaleMode = .aspectFill

                // Present the scene
                if let view = self.view as! SKView? {

                    sceneNode.gameViewController = self //SET THE PROPERTY
                    view.presentScene(sceneNode)

                    view.ignoresSiblingOrder = true
                    view.showsPhysics = true
                    view.showsFPS = true
                   view.showsNodeCount = true    
                }
            }
        }
    }
}

我的游戏场景class:

class GameScene: SKScene, SKPhysicsContactDelegate {

    // MARK: Properties
    var gameViewController:GameViewController!

    override func sceneDidLoad() {

         print(self.gameViewController) // -> CRASH
         //DO SOME STUFF
    }
}

我遇到了这个崩溃:

fatal error: unexpectedly found nil while unwrapping an Optional value

编辑 1

所以我尝试使用:

override func didMove(to view: SKView) {
    super.didMove(to: view)

    self.physicsWorld.contactDelegate = self
    self.physicsBody!.categoryBitMask = ColliderType.DeviceBounds.rawValue

    //ALL MY INIT CODE
}


override func sceneDidLoad() {
    super.sceneDidLoad()
    //NOTHING HERE
}

但是物理世界不再起作用了。我的崩溃消失了,但是物理世界坏了。

在我的控制台中:

--->GameViewController - viewDidLoad()<---
--->GameScene - sceneDidLoad()<---
--->GameScene - sceneDidLoad()<---
--->GameScene - didMove(to:)<---
--->GameViewController - viewWillAppear<---
--->GameViewController - viewDidAppear<---

在 ViewDidLoad 上使用 GameSceneView Controller:

if let scene = SKScene(fileNamed: "GameScene") {
  currentGame = scene as! GameScene
  currentGame.gameViewController = self
 }

那么你们就可以互相参考了。

sceneDidLoad 函数在您设置对 gameViewController 的引用之前被调用。您应该改用 SKScene didMoveToView 函数。

override func didMove(to view: SKView) {
    print(self.gameViewController)
}

您可以在 Xcode 中设置断点(在您的 gameScene 和 gameViewController 中)并查看事件的时间。顺便说一句,更好的做法是使用协议来实现 delegate pattern,而不是像这样使用具体的引用。

您忘记添加到 GameViewController,在此代码之后:

// Get the SKScene from the loaded GKScene
            if let sceneNode = scene.rootNode as! GameScene? {

行:

               sceneNode.gameViewController = self

另外,在你的场景中class你应该使用:

override func didMove(to view: SKView) {

因为 sceneDidLoad() 方法(现在在 iOS10 中)等同于 UIKit 中的 viewDidLoad()但是你的视图尚未呈现场景