【问题标题】:SCNParticleSystem load from document DirectorySCNParticleSystem 从文档目录加载
【发布时间】:2021-01-27 09:01:50
【问题描述】:

我正在尝试从我无法加载的下载包中加载 SCNParticleSystem。

资源的路径。

file:///var/mobile/Containers/Data/Application/A91E9970-CDE1-43D8-B822-4B61EFC6149B/Documents/so/solarsystem.bundle/Contents/Resources/

                let objScene = SCNParticleSystem(named: "stars", inDirectory: directory)

此对象为零。

【问题讨论】:

  • 你的包中的stars.scnp文件在哪里?
  • 它在提到的路径中可用 file:///var/mobile/Containers/Data/Application/A91E9970-CDE1-43D8-B822-4B61EFC6149B/Documents/so/solarsystem.bundle/Contents/Resources / 即使我尝试了捆绑文件:///var/mobile/Containers/Data/Application/A91E9970-CDE1-43D8-B822-4B61EFC6149B/Documents/solarsystem/stars.sncp

标签: ios swift scenekit arkit


【解决方案1】:

这是一个合法的问题,因为SceneKit 没有提供从主包之外的文件初始化粒子系统的开箱即用解决方案(唯一的 init 方法 SCNParticleSystem.init(named:inDirectory:) 意味着 SCNParticleSystem.scnp文件在主包中)。

幸运的是我们.scnp 文件只是编码/存档SCNParticleSystem 实例,我们可以使用NSKeyedUnarchiver 轻松解码/取消存档:

extension SCNParticleSystem {
    static func make(fromFileAt url: URL) -> SCNParticleSystem? {
        guard let data = try? Data(contentsOf: url),
            let object = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data),
            let system = object as? SCNParticleSystem else { return nil }

        return system
    }
}

如果您不需要支持iOS 9iOS 10,您可以使用NSKeyedUnarchiver.unarchivedObject(ofClass: SCNParticleSystem.self, from: data) 代替NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(_:) 和类型转换,这是在iOS 11.0 中引入的。

您最有可能遇到的另一个问题是缺少粒子图像。这是因为默认情况下SceneKit 会在主包中查找它们。截至当前版本的 iOS(iOS 12)和 Xcode(Xcode 10.scnp 文件(particleImage 属性)中的粒子图像是 String 值,它们是主包中的纹理文件名(可能会改变,但可能不会,但是我们可以使用的其他东西不多)。

所以我的建议是采用该文件名并在.scnp 文件所在的同一目录中查找具有相同名称的纹理文件:

extension SCNParticleSystem {
    static func make(fromFileAt url: URL) -> SCNParticleSystem? {
        guard let data = try? Data(contentsOf: url),
            let object = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data),
            let system = object as? SCNParticleSystem else { return nil }

        if let particleImageName = system.particleImage as? String {
            let particleImageURL = url
                .deletingLastPathComponent()
                .appendingPathComponent(particleImageName)

            if FileManager.default.fileExists(atPath: particleImageURL.path) {
                system.particleImage = particleImageURL
            }
        }

        return system
    }
}

您可以只设置图像文件的URLSceneKit 将从那里处理它。


附带说明一下,可下载内容的推荐目录是Application Support 目录,而不是Documents

应用程序支持:使用此目录存储所有应用程序数据文件,但与用户文档关联的文件除外。例如,您可以使用此目录来存储应用程序创建的数据文件、配置文件、模板或其他由应用程序管理的固定或可修改资源。应用程序可能会使用此目录来存储最初包含在应用程序包中的资源的可修改副本。游戏可能会使用此目录来存储用户购买并从服务器下载的新关卡。

(来自File System Basics

【讨论】:

    【解决方案2】:

    没有足够的代表来添加评论,所以将其添加为答案。

    Lësha Turkowski 的回答确实有效,但在仅使用 NSURL 加载粒子图像时遇到了问题。

    所有粒子都呈正方形,这意味着,

    如果值为 nil(默认值),SceneKit 会将每个粒子渲染为 白色小方块(由particleColor 属性着色)。

    SCNParticleSystem particleImage

    在文档中它说您可以使用 NSImage(在 macOS 中)或 UIImage(在 iOS 中)实例,或 NSString 或 包含图像文件的路径或 URL 的 NSURL 实例。

    最终没有使用 NSURL,而是使用 UIImage 并且加载正常。

        extension SCNParticleSystem {
        static func make(fromFileAt url: URL) -> SCNParticleSystem? {
            guard let data = try? Data(contentsOf: url),
                let object = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data),
                let system = object as? SCNParticleSystem else { return nil }
    
            if let particleImageName = system.particleImage as? String {
                let particleImageURL = url
                    .deletingLastPathComponent()
                    .appendingPathComponent(particleImageName)
    
                if FileManager.default.fileExists(atPath: particleImageURL.path) {
                    // load up the NSURL contents in UIImage
                    let particleUIImage = UIImage(contentsOfFile: particleImageURL.path)
                    system.particleImage = particleUIImage
                }
            }
    
            return system
        }
    }
    

    【讨论】:

      【解决方案3】:

      我发现,有时将 SCNParticleSystem 文件拖入您的项目(可能形成不同的项目)时,由于 Xcode 中的一些错误,可能会发生静默错误。因此,您无法获得对 SCNParticleSystem 实例的引用。

      解决方案:检查目标中的 BuildSettings。 SCNPaticleSystem 和相关的 ImageFile 应该在那里列出,然后你应该做对了。 (见下面的截图)

      【讨论】:

        猜你喜欢
        • 2012-01-27
        • 1970-01-01
        • 2015-10-20
        • 2019-01-30
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多