我有以下代码:
final class PassthroughEmitterNode: SKEmitterNode {
static func load(fnWithoutExtension: String, in bundle: Bundle) -> SKEmitterNode? {
guard
let sksPath = bundle.path(forResource: fnWithoutExtension, ofType: "sks"),
let sksData = try? Data(contentsOf: URL(fileURLWithPath: sksPath)),
let unarchiver = try? NSKeyedUnarchiver(forReadingFrom: sksData),
let texturePath = bundle.path(forResource: fnWithoutExtension, ofType: "png"),
let textureImage = UIImage(contentsOfFile: texturePath)
else { return nil }
// Required to decode into subclass
unarchiver.setClass(self.classForKeyedUnarchiver(), forClassName: "SKEmitterNode")
let emitter = unarchiver.decodeObject(forKey: NSKeyedArchiveRootObjectKey) as? PassthroughEmitterNode
unarchiver.finishDecoding()
guard let emitter else { return nil }
// We still need to set texture, because the texture file is not in main bundle
emitter.particleTexture = SKTexture(image: textureImage)
// Have to enable user interaction to receive touch
emitter.isUserInteractionEnabled = true
return emitter
}
}
这与从 SKS 文件读取 SKScene 子类实例非常相似(例如:将 sks 文件与 SKScene 子类一起使用)。
但是,这行不通。解档器的解码始终返回 nil。
但是解档到
SKEmitterNode
类本身是有效的。子类不起作用。
我想我知道为什么这不起作用。
当您从
GameScene
文件解码自定义场景(例如 SKScene
的 sks
子类)时,您可以将自定义类的名称放入 sks
文件中。
不幸的是,似乎不可能对 SKEmitterNode 做同样的事情。事实上,如果您打开代表发射器的
sks
文件并将检查器转到右侧,则 Custom class inspector
面板不存在。
因此似乎不可能将包含发射器的 sks 文件解码为
SKEmitterNode
的子类。
但是,我们可以尝试其他方法:
SKEmitterNode
PassthroughEmitterNode
创建
SKEmitterNode
为了做到这一点,让我们添加这个 init
public final class PassthroughEmitterNode: SKEmitterNode {
init(emitterNode: SKEmitterNode) {
super.init()
self.emissionAngle = emitterNode.emissionAngle
self.emissionAngleRange = emitterNode.emissionAngleRange
self.numParticlesToEmit = emitterNode.numParticlesToEmit
self.particleAlpha = emitterNode.particleAlpha
self.particleAlphaRange = emitterNode.particleAlphaRange
self.particleAlphaSpeed = emitterNode.particleAlphaSpeed
self.particleBirthRate = emitterNode.particleBirthRate
self.particleBlendMode = emitterNode.particleBlendMode
self.particleColor = emitterNode.particleColor
self.particleColorBlendFactor = emitterNode.particleColorBlendFactor
self.particleColorBlendFactorRange = emitterNode.particleColorBlendFactorRange
self.particleColorBlendFactorSpeed = emitterNode.particleColorBlendFactorSpeed
self.particleLifetime = emitterNode.particleLifetime
self.particleLifetimeRange = emitterNode.particleLifetimeRange
self.particlePositionRange = emitterNode.particlePositionRange
self.particleRotation = emitterNode.particleRotation
self.particleRotationRange = emitterNode.particleRotationRange
self.particleRotationSpeed = emitterNode.particleRotationSpeed
self.particleScale = emitterNode.particleScale
self.particleScaleRange = emitterNode.particleScaleRange
self.particleScaleSpeed = emitterNode.particleScaleSpeed
self.particleSpeed = emitterNode.particleSpeed
self.particleSpeedRange = emitterNode.particleSpeedRange
self.particleTexture = emitterNode.particleTexture
self.position = emitterNode.position
self.xAcceleration = emitterNode.xAcceleration
self.yAcceleration = emitterNode.yAcceleration
// TODO: Add additional properties I might have forgot.
}
@available(*, unavailable)
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
就是这样。
现在您可以解码标准
SKEmitterNode
并将其转换为您的 PassthroughEmitterNode
let emitterNode: SKEmitterNode = ... // Decode as usual
let passthroughEmitterNode = PassthroughEmitterNode(emitterNode: emitterNode)
PassthroughEmitterNode
与 SKEmitterNode
相比具有额外的属性怎么办?这些附加属性的值不能来自 sks 文件,因为它们没有位置。因此,您需要使用一些默认值或自定义逻辑来填充它们。