Загрузка SCNParticleSystem из каталога документов - PullRequest
0 голосов
/ 24 декабря 2018

Я пытаюсь загрузить 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)

Этот объект равен nil.

Ответы [ 2 ]

0 голосов
/ 30 июля 2019

Недостаточно повторений, чтобы добавить комментарий, поэтому добавьте его в качестве ответа.

Ответ Леша Турковски работает наверняка, но у него были проблемы с загрузкой изображений частиц с использованием только NSURL.

Все частицы выглядели квадратными, что означало,

Если значение равно nil (по умолчанию), SceneKit отображает каждую частицу в виде небольшого белого квадрата (раскрашивается свойствомичка colorColor).

SCNParticleSystemicleImage

В документации сказано, что вы можете указать изображение, используя экземпляр NSImage (в macOS) или UIImage (в iOS), илиЭкземпляр NSString или NSURL, содержащий путь или URL-адрес файла изображения.

Вместо использования 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
    }
}
0 голосов
/ 25 декабря 2018

Это законная проблема, поскольку SceneKit не предоставляет готового решения для инициализации систем частиц из файлов, которые находятся за пределами основного пакета (единственный метод инициализации 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 9 и iOS 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
    }
}

Вы можете просто установить URL файла изображения, и SceneKit будет обрабатывать его оттуда.


КакНебольшое примечание: рекомендуемый каталог для загружаемого контента - каталог Application Support, а не Documents.

Поддержка приложений : Используйте этот каталог для хранения всех файлов данных приложения, кроме тех, которые связаны с документами пользователя.Например, вы можете использовать этот каталог для хранения созданных приложением файлов данных, файлов конфигурации, шаблонов или других фиксированных или изменяемых ресурсов, которыми управляет приложение.Приложение может использовать этот каталог для хранения изменяемой копии ресурсов, изначально содержащихся в комплекте приложения.Игра может использовать этот каталог для хранения новых уровней, приобретенных пользователем и загруженных с сервера.

(из Основы файловой системы )

...