如何从 UIViewController 移动到 SKView,反之亦然?
How to move from UIViewController to SKView and vice versa?
我的想法是在移动到游戏场景之前显示地图几秒钟,游戏屏幕层次结构是这样的:
GameViewController(UIViewController ) -> EntryToGameScene (SKView) -> MapController (UIViewController) -> GamePlayGround (SKView)
我在从 MapController 移动到 GamePlayGround 时遇到问题,为了能够从控制器移动到场景,我首先将控制器视图 class 从 Storyboard 更改为 SKView,然后我添加了以下代码 ⬇️。在 handleDelay()
方法是 运行 之后,游戏场景 didMove()
方法有效但屏幕卡在旧视图(MapController)上!?我确定游戏场景 didMove()
方法有效,因为背景音乐开始 play.But 为什么屏幕没有变化?
我的代码是这样的:
override func viewDidLoad() {
super.viewDidLoad()
// Wait for three sec. then move to game scene
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
view.layoutIfNeeded()
if let view = self.view as! SKView? {
// Load the SKScene
let scene = GameScene(size: sceneSize)
// Set the scale mode
scene.scaleMode = .aspectFill
scene.delegate = self
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
}
}
所有答案都可接受。
轻松修复。我将代码复制并粘贴到一个测试项目中,我弄清楚了你做错了什么。您不是在引用要呈现的场景。您没有传递要呈现的特定 SKView。您正在展示一个通用的 SKView class.
此代码:
override func viewDidLoad() {
super.viewDidLoad()
// Wait for three sec. then move to game scene
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
view.layoutIfNeeded()
if let view = self.view as! SKView? {
// Load the SKScene
let scene = GameScene(size: sceneSize)
// Set the scale mode
scene.scaleMode = .aspectFill
scene.delegate = self
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
}
}
应该是这样的:
override func viewDidLoad() {
super.viewDidLoad()
// Wait for three sec. then move to game scene
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
view.layoutIfNeeded()
// Load the view as an SKView to prepare for an SKScene
if let view = self.view as! SKView? {
// Load the SKScene from the GameScene file
let scene = GameScene()
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
已测试并正常工作。
从视图中删除所有子视图然后呈现 SKScene 的解决方案。
注意:我知道这不是最好的解决方案,但目前没有其他选择,所以我这样更改了我的代码:
override func viewDidLoad() {
super.viewDidLoad()
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
self.view.subviews.forEach {[=10=].removeFromSuperview()}
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.swift' and should set it's size
let scene = SecondGameScene(size: self.view.frame.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
}
}
更新:
最后我找到了从 SKScene 和 UIView Controller 移动的正确方法,反之亦然。
例如(从SKScene移动到UIViewController):
fileprivate func moveToUIViewController(storyBoardId: String) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: storyBoardId)
vc.view.frame = self.frame
vc.view.layoutIfNeeded()
self.view?.window?.rootViewController?.present(vc, animated: true, completion: nil)
}
(从UIViewController移动到SKScene):
fileprivate func returnToSKScene() {
for element in self.view.subviews {
element.removeFromSuperview()
}
self.dismiss(animated: true) {
if let view = self.view as! SKView? {
// Load the SKScene
var scene: SKScene
scene = AboutScene(size: sceneSize)
// Set the scale mode
scene.scaleMode = .aspectFill
let transition = SKTransition.moveIn(with: .up, duration: 0.2)
// Present the scene
view.presentScene(scene, transition: transition)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
}
}
}
不要忘记将 UIViewController view class 更改为 "SKView":
Select 从 Storyboard -> Identity inspector -> Custom 查看 class。
2.Select SKView 来自 Class 下拉列表。
我的想法是在移动到游戏场景之前显示地图几秒钟,游戏屏幕层次结构是这样的:
GameViewController(UIViewController ) -> EntryToGameScene (SKView) -> MapController (UIViewController) -> GamePlayGround (SKView)
我在从 MapController 移动到 GamePlayGround 时遇到问题,为了能够从控制器移动到场景,我首先将控制器视图 class 从 Storyboard 更改为 SKView,然后我添加了以下代码 ⬇️。在 handleDelay()
方法是 运行 之后,游戏场景 didMove()
方法有效但屏幕卡在旧视图(MapController)上!?我确定游戏场景 didMove()
方法有效,因为背景音乐开始 play.But 为什么屏幕没有变化?
我的代码是这样的:
override func viewDidLoad() {
super.viewDidLoad()
// Wait for three sec. then move to game scene
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
view.layoutIfNeeded()
if let view = self.view as! SKView? {
// Load the SKScene
let scene = GameScene(size: sceneSize)
// Set the scale mode
scene.scaleMode = .aspectFill
scene.delegate = self
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
}
}
所有答案都可接受。
轻松修复。我将代码复制并粘贴到一个测试项目中,我弄清楚了你做错了什么。您不是在引用要呈现的场景。您没有传递要呈现的特定 SKView。您正在展示一个通用的 SKView class.
此代码:
override func viewDidLoad() {
super.viewDidLoad()
// Wait for three sec. then move to game scene
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
view.layoutIfNeeded()
if let view = self.view as! SKView? {
// Load the SKScene
let scene = GameScene(size: sceneSize)
// Set the scale mode
scene.scaleMode = .aspectFill
scene.delegate = self
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
}
}
应该是这样的:
override func viewDidLoad() {
super.viewDidLoad()
// Wait for three sec. then move to game scene
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
view.layoutIfNeeded()
// Load the view as an SKView to prepare for an SKScene
if let view = self.view as! SKView? {
// Load the SKScene from the GameScene file
let scene = GameScene()
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = true
view.showsNodeCount = true
}
}
已测试并正常工作。
从视图中删除所有子视图然后呈现 SKScene 的解决方案。
注意:我知道这不是最好的解决方案,但目前没有其他选择,所以我这样更改了我的代码:
override func viewDidLoad() {
super.viewDidLoad()
self.perform(#selector(handleDelay), with: nil, afterDelay: 3.0)
}
@objc fileprivate func handleDelay() {
self.view.subviews.forEach {[=10=].removeFromSuperview()}
if let view = self.view as! SKView? {
// Load the SKScene from 'GameScene.swift' and should set it's size
let scene = SecondGameScene(size: self.view.frame.size)
// Set the scale mode to scale to fit the window
scene.scaleMode = .aspectFill
// Present the scene
view.presentScene(scene)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
}
}
更新: 最后我找到了从 SKScene 和 UIView Controller 移动的正确方法,反之亦然。
例如(从SKScene移动到UIViewController):
fileprivate func moveToUIViewController(storyBoardId: String) {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: storyBoardId)
vc.view.frame = self.frame
vc.view.layoutIfNeeded()
self.view?.window?.rootViewController?.present(vc, animated: true, completion: nil)
}
(从UIViewController移动到SKScene):
fileprivate func returnToSKScene() {
for element in self.view.subviews {
element.removeFromSuperview()
}
self.dismiss(animated: true) {
if let view = self.view as! SKView? {
// Load the SKScene
var scene: SKScene
scene = AboutScene(size: sceneSize)
// Set the scale mode
scene.scaleMode = .aspectFill
let transition = SKTransition.moveIn(with: .up, duration: 0.2)
// Present the scene
view.presentScene(scene, transition: transition)
view.ignoresSiblingOrder = true
view.showsFPS = false
view.showsNodeCount = false
view.showsPhysics = false
}
}
}
不要忘记将 UIViewController view class 更改为 "SKView":
Select 从 Storyboard -> Identity inspector -> Custom 查看 class。
2.Select SKView 来自 Class 下拉列表。