我正在尝试从无法加载的下载包中加载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)
该对象为空。
答案 0 :(得分:0)
这是一个合理的问题,因为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
。
应用程序支持:使用此目录存储所有应用程序数据文件,与用户文档相关的文件除外。例如,您可以使用此目录来存储由应用程序管理的应用程序创建的数据文件,配置文件,模板或其他固定或可修改的资源。应用可能会使用此目录来存储最初包含在应用捆绑中的资源的可修改副本。游戏可能会使用此目录来存储用户购买并从服务器下载的新关卡。
答案 1 :(得分:0)
没有足够的代表来添加评论,因此将其添加为答案。
LëshaTurkowski的答案可以肯定地起作用,但是在仅使用NSURL加载粒子图像时遇到了问题。
所有粒子均显示为正方形,
如果值为nil(默认值),SceneKit会将每个粒子渲染为 小的白色正方形(由particleColor属性着色)。
SCNParticleSystem particleImage
在文档中说您可以使用 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
}
}
答案 2 :(得分:0)