【问题标题】:SceneKit presentScene(_withTransition:incomingPointOfView completionHandler) crash with dynamically loaded SCNSceneSceneKit presentScene(_withTransition:incomingPointOfView completionHandler) 崩溃,动态加载 SCNScene
【发布时间】:2015-12-28 08:25:35
【问题描述】:

我正在尝试从一个场景过渡到另一个场景,但是当我拨打presentScene 时发生了崩溃! 场景不存储在类中或引用,它们直接加载到presentScene 调用中。

Xcode 中的崩溃屏幕截图:

我的简单最小项目在这里:https://dl.dropboxusercontent.com/u/6979623/SceneKitTransitionTest.zip

MKScene 只是SCNScene 的一个子类,因为我想知道一个场景何时被定义以确保它是它。

self.gameView!.scene = MKScene(named:"art.scnassets/scene1.scn")

然后我再打电话

let scnView:SCNView = self.gameView! as SCNView
let skTransition:SKTransition = SKTransition.crossFadeWithDuration(1.0)
skTransition.pausesIncomingScene = false
skTransition.pausesOutgoingScene = false
self.sceneToggler = !self.sceneToggler
// transition
scnView.presentScene((self.sceneToggler ? MKScene(named:"art.scnassets/scene1.scn")! : MKScene(named:"art.scnassets/scene2.scn")!), withTransition:skTransition, incomingPointOfView:nil, completionHandler:nil)

如果我在课堂上保留对场景的引用,那么它会起作用——但这不是我想要的。我只想过渡到不同的场景,然后将当前场景置于 deinited 之后。

为什么会崩溃? 这似乎是一项简单的任务……

【问题讨论】:

    标签: crash scenekit


    【解决方案1】:

    这是 SceneKit 中的一个错误。解决方法:在调用“presentScene”之前保留对传出场景的引用,并在调用之后释放它。

    【讨论】:

    • SceneKit 中有很多需要解决的错误 - 希望你们修复它们并提高质量!
    【解决方案2】:

    我能够通过一个更简单的项目重现您的崩溃。它不使用MKScene,也不使用通知来触发转换。它在第二次尝试加载时崩溃。

    我已经在https://bugreport.apple.com 提交了此文件,名称为 rdar://24012973,我希望你能欺骗它,以及你更长的项目。

    这是我简化的 ViewController.swift。在SCNScene 属性(第 25/29 行)或动态加载(第 24/28 行)之间切换会在正确行为和崩溃行为之间切换。也就是说,

            nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
    

    失败,并且

            nextScene = scene2!
    

    有效。

    //  ViewController.swift
    import Cocoa
    import SceneKit
    import SpriteKit
    
    class ViewController: NSViewController {
    
    @IBOutlet weak var sceneView: SCNView!
    private var sceneToggler:Bool = false
    private var scene1: SCNScene? = SCNScene(named:"art.scnassets/scene1.scn")
    private var scene2: SCNScene? = SCNScene(named:"art.scnassets/scene2.scn")
    
    private func nextSceneToLoad() -> SCNScene {
        let nextScene: SCNScene
    
        if (sceneToggler) {
            //nextScene = SCNScene(named:"art.scnassets/scene1.scn")!
            nextScene = scene1!
            print ("scene1")
        }
        else {
            nextScene = SCNScene(named:"art.scnassets/scene2.scn")!
            //nextScene = scene2!
            print ("scene2")
        }
        print (nextScene)
        sceneToggler = !sceneToggler
        return nextScene
    }
    
    override func mouseUp(theEvent: NSEvent) {
    
        let skTransition:SKTransition = SKTransition.fadeWithDuration(5.0)
        skTransition.pausesIncomingScene = false
        skTransition.pausesOutgoingScene = false
        sceneView.presentScene(nextSceneToLoad(),
            withTransition:skTransition,
            incomingPointOfView:nil, completionHandler:nil)
    
    
        super.mouseUp(theEvent)
    }
    }
    

    【讨论】:

    • 是的,它有效。但它保留对两个场景的引用 = 浪费内存。
    • 根据@toyos 的注释,这就是你所坚持的,要么接受,要么离开。根据您使用 Instruments 使用几个真实场景文件进行的测量,内存使用真的是一个问题吗?复制我发布的雷达号码,以获得更好的注意力。如果这是一个真正的问题,您可以在完成处理程序中释放对传出场景的引用。但这对我来说听起来像是过早的优化。
    • 这就是我为使它工作所做的工作。 private var mTempSceneReference:AnyObject?and self.mTempSceneReference = self.gameView!.scene // catch the current scene so that we don't crashthen 在完成处理程序中 self.mTempSceneReference = nil // release the current scene
    猜你喜欢
    • 2020-10-01
    • 1970-01-01
    • 2018-03-12
    • 2019-02-19
    • 1970-01-01
    • 2020-12-27
    • 2022-12-05
    • 2015-07-26
    • 2016-02-26
    相关资源
    最近更新 更多