解散SKScene返回到UIKit菜单

一旦我的SpriteKit游戏结束,我想回到我的UIKit MenuViewController 。 从我迄今为止学到的,使用协议/委托是最好的(?)选项,但是我一直没有能够得到这个工作。 我知道该协议可能会超过GameViewController的类声明,看起来像这样:

 protocol GameViewControllerDelegate { var gameOver: Bool? } 

但是我需要帮助从GameScene访问它,并得到它来消除GameViewController 。 下面是应用程序的骨骼,以防万一。

故事板图像

MenuViewController

 class MenuViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() } @IBAction func goToGame(_ sender: UIButton) { performSegue(withIdentifier: "toGameSegue", sender: sender.currentTitle) } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let destinationVC = segue.destination as? GameViewController { if let item = sender as? String { destinationVC.numberOfPlayers = item } } } } 

GameViewController

 class GameViewController: UIViewController { var numberOfPlayers: String? override func viewDidLoad() { super.viewDidLoad() if let view = self.view as! SKView? { if let scene = SKScene(fileNamed: "GameScene") { scene.scaleMode = .aspectFill scene.userData = NSMutableDictionary() scene.userData?.setObject(numberOfPlayers!, forKey: "numberOfPlayers" as NSCopying) view.presentScene(scene) } } } ... 

GameScene

 class GameScene: SKScene { var howManyPlayers: String? override func didMove(to view: SKView) { if let numPlayers = self.userData?.value(forKey: "numberOfPlayers") { howManyPlayers = numPlayers as? String } print(howManyPlayers!) } ... 

这个SpriteKit游戏有一个MenuViewController,一个GameViewController和一个GameScene。 当你从MenuViewController按下一个button,数据通过segue发送到GameViewController。 在GameViewController呈现GameScene之前,它将数据存储在场景的userDatavariables中,以便GameScene可以访问它。 在这个例子中,这是玩家的数量。

我同意Whirwind的评论:为什么混合两个不同的框架和复杂的生活,当你可以使用一个viewController只做你所有的游戏?

无论如何,根据你的故事板截图,有2个viewControllers,你可以去第二个viewController(和GameScene只有当你按下button

有两件事要做:取消分配当前SKScene(在你的情况GameScene ),并呈现“初始视图控制器”或你的MenuViewController

为此,我使用协议/委托方法的“Hello world”雪碧套件模板来扩展SKSceneDelegate 类 。 正如你所看到的,我们可以消除场景(呈现零),并调用GameViewController上的外部方法来呈现MainViewController

为了确保这两个操作都能成功,我还使用了两个print用于debugging:

GameViewController

 import UIKit import SpriteKit class GameViewController: UIViewController,TransitionDelegate { override func viewDidLoad() { super.viewDidLoad() if let view = self.view as! SKView? { if let scene = SKScene(fileNamed: "GameScene") { scene.scaleMode = .aspectFill scene.delegate = self as TransitionDelegate view.presentScene(scene) } view.ignoresSiblingOrder = true view.showsFPS = true view.showsNodeCount = true } } func returnToMainMenu(){ let appDelegate = UIApplication.shared.delegate as! AppDelegate guard let storyboard = appDelegate.window?.rootViewController?.storyboard else { return } if let vc = storyboard.instantiateInitialViewController() { print("go to main menu") self.present(vc, animated: true, completion: nil) } } } 

GameScene

 import SpriteKit protocol TransitionDelegate: SKSceneDelegate { func returnToMainMenu() } class GameScene: SKScene { override func didMove(to view: SKView) { self.run(SKAction.wait(forDuration: 2),completion:{[unowned self] in guard let delegate = self.delegate else { return } self.view?.presentScene(nil) (delegate as! TransitionDelegate).returnToMainMenu() }) } deinit { print("\n THE SCENE \((type(of: self))) WAS REMOVED FROM MEMORY (DEINIT) \n") } } 

输出

在这里输入图像说明