TLTR:

问题:SKScene子类的init(fileNamed:)返回nil
原因:在第二次初始化调用时.sks文件不存在。这个问题与ODR实现和/或行为有关。

说明:

使用SpriteKit构建的游戏。我的SKScene子类的init(fileNamed:)返回nil。我试图理解“为什么?”如何?”调试此问题。

我的初始化SKScene子类的代码:

/// the hierarchy: SKScene -> TBTBaseScene -> TBTLevelScene

let sceneType: TBTBaseScene.Type = TBTLevelScene.self
let fileName = "Level1"

let scene = sceneType.init(fileNamed: fileName)

几件事要注意:
  • 此代码在运行时的某个时候起作用,但在另一时间不起作用。
  • 通过Xcode构建目标时,转到产品-> AppName.app,右键单击“在Finder中显示”,没有Level1.sks。也许可以,因为该应用程序使用ODR并且Level1.sks带有“Level1”标记,即使它位于“初始安装”标记中
  • 将断点设置为let sceneType:...行时,我可以通过各自的子类和fileName轻松创建其他游戏场景,但是expression TBTLevelScene(fileName:"Level1")返回nil
  • 我尝试检查的
  • 在主捆绑包中是否存在Level1.sks,但是对于所有场景,下面的代码始终表示“FILE NOT AVAILABLE”,因此该方法似乎是错误的。
  • 游戏的场景加载架构由DemoBots Sample Code驱动。您可以在LoadSceneOperation.swift中看到类似的方法。不过,在任何情况下,此处的初始化都可以正常工作。

  • 基于this answer,我用来检查“Level1”或“Level1.sks”是否存在的代码:
    let path = NSBundle.mainBundle().bundlePath
    let url = NSURL(fileURLWithPath: path)
    let filePath = url.URLByAppendingPathComponent(fileName).absoluteString
    let fileManager = NSFileManager.defaultManager()
    if fileManager.fileExistsAtPath(filePath) {
        print("FILE AVAILABLE")
    } else {
        print("FILE NOT AVAILABLE")
    }
    

    更新:

    检查Michael Dautermann提供的文件的方法确实有效,并证明了原因:在第二次尝试加载Level1.sks时,不存在而不是

    项目中的Level1.sks文件已添加到“复制包资源”区域,并具有“Level1” ODR标记。该标签在“初始安装标签”预取组中。

    ORD实施中肯定存在一些错误,该错误会在不需要资源时处理资源(Level1.sks),并且在需要时不会再次加载资源。我将继续努力以解决问题。 (似乎到目前为止,SO社区与之无关)

    最佳答案

    这里发生了一些事情,但是最终发生的事情是,听起来您的“Level1”文件没有最终出现在构建的应用程序中。

    1)

    您的文件存在检查代码在那里混合了文件URL和文件路径太多。更改您的代码,如下所示:

    // if nodePath is nil, then it's not found in the bundle
    if let nodePath = NSBundle.mainBundle().pathForResource("Level1", ofType: "sks")
    {
        print("FILE AVAILABLE")
    } else {
        print("FILE NOT AVAILABLE")
    }
    

    2)

    确保将您的.sks文件复制到内置应用中。

    打开目标的“构建阶段”部分和click on the "Copy Bundle Resources" area。确保您的.sks文件包含在其中。

    10-08 12:13