【问题标题】:Halt when presenting ViewController with SKScene使用 SKScene 呈现 ViewController 时停止
【发布时间】:2016-01-20 21:43:40
【问题描述】:

编辑:好的,即使是空的 SpriteKit 场景也会发生这种情况! 这里有什么问题? 为什么 iOS 需要 2 秒才能显示 SpriteKit 场景??

编辑 2:我第一次单击选项卡栏以显示带有 SKScene 的视图控制器时,它会立即显示,但每次我尝试导航回此视图控制器时,它都需要 2 秒才能显示!

我的应用中有一个标签栏控制器,其中包含多个不同的视图控制器。

其中一个包含一个 SpriteKit 场景,有几个节点,其中 5 个,没有太重。

在模拟器中一切都很好,但是在设备上进行测试时,我注意到有时在使用 SpriteKit 场景更改为 ViewController 时会出现很大的停顿(大约 2 秒!)。

其他时候没有暂停,立即显示视图。

现在,我知道我在这里做错了什么,因为 iOS 肯定能够处理这个问题。

这是我在带有 spriteKit 场景的 viewController 中的 viewDidLoad 函数:

override func viewDidLoad() {
    super.viewDidLoad()

    if let scene = MyScene(fileNamed:"MyScene") {
        // Configure the view.
        scene.switchView = switchView

        let parentNode = scene.childNodeWithName("WholeObject") as! SKSpriteNode
        let contentNode = scene.childNodeWithName("CenterNode") as! SKSpriteNode
        addPhotoToFrame(contentNode, photoName: "woman", maskName: "circleMask")

        let node1 = parentNode.childNodeWithName("node1")  as! SKSpriteNode
        addPhotoToFrame(zealNode1, photoName: "motherCircleImage", maskName: "circleMaskSmall")

        let node2 = parentNode.childNodeWithName("node2")  as! SKSpriteNode
        addPhotoToFrame(zealNode2, photoName: "hairstylistCircleImage", maskName: "circleMaskSmall")

        let node3 = parentNode.childNodeWithName("node3")  as! SKSpriteNode
        addPhotoToFrame(zealNode3, photoName: "dietCircleImage", maskName: "circleMaskSmall")


        let skView = self.view as! SKView
        skView.showsFPS = true
        skView.showsNodeCount = true


        /* Sprite Kit applies additional optimizations to improve rendering performance */
        skView.ignoresSiblingOrder = true

        /* Set the scale mode to scale to fit the window */
        scene.scaleMode = .AspectFill


        skView.presentScene(scene)
    }

}

【问题讨论】:

  • 您是否在预加载图形尝试首先使用纹理图集预加载图形或尝试在单独的线程中绘制所有绘图 OpenGL 绘图取决于图形的大小(宽度和高度)而不是图形的数量其次,为什么你最后向根容器添加视图只是尝试先添加视图,然后再添加场景,最后再进一步绘制
  • 问题是即使在完全空旷的场景中也会发生这种情况!所以我不认为问题出在图形上。它也很不一致...我觉得我应该设置一些缓存标志或其他东西来解决这个问题...
  • 你有没有尝试先添加视图,然后是场景,然后是 gfx
  • view 是由其UIViewController 管理的SKView,由标签栏控制器管理。所以我想它首先添加对吗?我尝试用一​​个丰富的场景替换上面的代码,结果完全一样。您是否建议我在 viewDidLoad 函数添加场景后等待一段时间?

标签: ios swift sprite-kit


【解决方案1】:

嗨 deloki,我在 swift 中创建了一个新项目,并提供了一个解决方案,它在设备上运行良好.....查看我的代码

这是我调用 GameScene 的 GameViewController

import UIKit
import SpriteKit

extension SKNode {
    class func unarchiveFromFile1(file : String) -> SKNode? {
        if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
            var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
            var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)

            archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
            let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
            archiver.finishDecoding()
            return scene
        } else {
            return nil
        }
    }
}

class GameViewController: UIViewController {
       var skView:SKView!
    override func viewDidLoad() {

        super.viewDidLoad()

        if let scene = GameScene.unarchiveFromFile1("GameScene") as? GameScene {
            // Configure the view.
            let graphRect:CGRect = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
             skView = SKView();
             skView.frame=graphRect
            skView.showsFPS = true
            skView.showsNodeCount = true
            self.view.addSubview(skView)
            /* Sprite Kit applies additional optimizations to improve rendering performance */
            skView.ignoresSiblingOrder = true

            /* Set the scale mode to scale to fit the window */
            scene.scaleMode = .AspectFill

            skView.presentScene(scene)
            let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC)))
            dispatch_after(delayTime, dispatch_get_main_queue()) {
                let s2=GameViewController1();
                self.presentViewController(s2, animated: true, completion: { () -> Void in
                    //
                })
            }

        }
    }
    override func viewDidDisappear(animated: Bool) {
        if((skView) != nil)
        {
            skView .removeFromSuperview();
            skView=nil;
        }

    }
    override func shouldAutorotate() -> Bool {
        return true
    }

    override func supportedInterfaceOrientations() -> Int {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
        } else {
            return Int(UIInterfaceOrientationMask.All.rawValue)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Release any cached data, images, etc that aren't in use.
    }

    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}

这是我的 GameViewController1,它调用 MyScene1

import UIKit
import SpriteKit

extension SKNode {
    class func unarchiveFromFile(file : String) -> SKNode? {
        if let path = NSBundle.mainBundle().pathForResource(file, ofType: "sks") {
            var sceneData = NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe, error: nil)!
            var archiver = NSKeyedUnarchiver(forReadingWithData: sceneData)

            archiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKScene")
            let scene = archiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as! GameScene
            archiver.finishDecoding()
            return scene
        } else {
            return nil
        }
    }
}

class GameViewController1: UIViewController {
      var skView:SKView!
    override func viewDidLoad() {

        super.viewDidLoad()

        if let scene = GameScene.unarchiveFromFile("MyScene1") as? GameScene {
            // Configure the view.
            let graphRect:CGRect = CGRectMake(0, 0, self.view.frame.width, self.view.frame.height)
            skView=SKView()
            skView.frame=graphRect
            skView.showsFPS = true
            skView.showsNodeCount = true

            /* Sprite Kit applies additional optimizations to improve rendering performance */
            skView.ignoresSiblingOrder = true

            /* Set the scale mode to scale to fit the window */
           // scene.scaleMode = .AspectFill
            self.view.addSubview(skView)
            skView.presentScene(scene)
            let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(3 * Double(NSEC_PER_SEC)))
            dispatch_after(delayTime, dispatch_get_main_queue()) {
                let s2=GameViewController();
                self.presentViewController(s2, animated: true, completion: { () -> Void in
                    //
                })
            }
        }
    }

    override func viewDidDisappear(animated: Bool) {
        if((skView) != nil)
        {
            skView .removeFromSuperview();
            skView=nil;
        }

    }
    override func shouldAutorotate() -> Bool {
        return true
    }

    override func supportedInterfaceOrientations() -> Int {
        if UIDevice.currentDevice().userInterfaceIdiom == .Phone {
            return Int(UIInterfaceOrientationMask.AllButUpsideDown.rawValue)
        } else {
            return Int(UIInterfaceOrientationMask.All.rawValue)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Release any cached data, images, etc that aren't in use.
    }

    override func prefersStatusBarHidden() -> Bool {
        return true
    }
}

从情节提要创建 SKview 我只是以编程方式创建它,每 2 秒我从一个视图切换到另一个视图,它在所有设备上都可以正常工作,但我使用 Xcode 6.4 和 ios9 您可以从http://www.filedropper.com/tryit下载链接

【讨论】:

    【解决方案2】:

    我不知道是什么触发了这个问题,但在视图消失之前暂停为我解决了这个问题。

    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        self.contentView.paused = false
    }
    
    override func viewWillDisappear(animated: Bool) {
        super.viewWillDisappear(animated)
        self.contentView.paused = true
    }
    

    【讨论】:

    • iOS14 问题依然存在,你的修复依然有效。
    猜你喜欢
    • 2015-04-11
    • 2018-03-07
    • 2014-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-04-05
    • 1970-01-01
    相关资源
    最近更新 更多