SCNParticleSystem:在代码中为 "particleColor" 属性 设置动画

SCNParticleSystem: animating "particleColor" property in code

我想仅在代码中为 SceneKit 粒子系统中的特定颜色序列设置动画。 (就像在 XCode 中的粒子系统编辑器中可以做的那样。)

我正在尝试以下操作,每次将动画附加到粒子系统时应用程序都会崩溃。编译器不会抱怨,Xcode 不会指示语法中的任何错误。 (没有动画部分,粒子系统工作正常)

func particleSystemTesting(shape: SCNGeometry) -> SCNParticleSystem {
    
    let explosion = SCNParticleSystem(named: "explosion.scnp", inDirectory: nil)!
    explosion.emitterShape = shape
    explosion.birthLocation = .surface
    explosion.birthDirection = .surfaceNormal
    explosion.isAffectedByGravity = true
    explosion.isLightingEnabled = false
    explosion.loops = true
    explosion.sortingMode = .none
    explosion.isBlackPassEnabled = true
    explosion.blendMode = .additive

    explosion.particleColor = UIColor.white // using as default, should even not be required

    // Animation Part        
    let animation = CABasicAnimation(keyPath: "particleColor")
    animation.fromValue = UIColor.blue
    animation.toValue = UIColor.red
    animation.duration = 2.0
    animation.isRemovedOnCompletion = true
    
    explosion.addAnimation(animation, forKey: nil) // causing the crash
    
    return explosion
    
}

这是控制台打印出的错误:

2020-08-23 18:25:53.281120+0200 MyTestApp[1684:892874] Metal GPU Frame Capture Enabled
2020-08-23 18:25:53.281349+0200 MyTestApp[1684:892874] Metal API Validation Enabled
2020-08-23 18:25:56.563208+0200 MyTestApp[1684:892874] -[SCNParticleSystem copyAnimationChannelForKeyPath:animation:]: unrecognized selector sent to instance 0x101041500
2020-08-23 18:25:56.564524+0200 MyTestApp[1684:892874] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[SCNParticleSystem copyAnimationChannelForKeyPath:animation:]: unrecognized selector sent to instance 0x101041500'
*** First throw call stack:
(0x1998d5654 0x1995f7bcc 0x1997d9dd8 0x1998d97f8 0x1998db71c 0x1ade571f8 0x1ade55f24 0x1ade59268 0x1ade5af2c 0x1ade23d84 0x1adf18cf0 0x199852f2c 0x19984de20 0x19984e29c 0x19984dba8 0x1a39bd344 0x19d9893e4 0x100566384 0x1996d58f0)
libc++abi.dylib: terminating with uncaught exception of type NSException

经过更多研究和咨询 apples 文档 reference 看来我的第一种方法是错误的,因为那会同时影响所有生成的粒子。

但它仍然没有按预期工作 - 所有粒子都 gone/invisible 在场景中 - 否则没有错误。随着时间的推移,这应该会改变每个粒子的颜色。怎么了?

func particleSystemTesting(shape: SCNGeometry) -> SCNParticleSystem {

    let explosion = SCNParticleSystem(named: "explosion_testing.scnp", inDirectory: nil)!
    // let explosion = SCNParticleSystem() // makes no difference
    explosion.emitterShape = shape
    explosion.birthLocation = .surface
    explosion.birthDirection = .surfaceNormal
    explosion.isAffectedByGravity = true
    explosion.isLightingEnabled = false
    explosion.loops = true
    explosion.sortingMode = .none
    explosion.isBlackPassEnabled = true
    explosion.blendMode = .additive
    
    // explosion.particleColor = UIColor.black

    let red = UIColor.red
    let green = UIColor.green
    let blue = UIColor.blue
    let yellow = UIColor.yellow
    
    let color1 = SCNVector4(red.redValue, red.greenValue, red.blueValue, 1.0)
    let color2 = SCNVector4(green.redValue, green.greenValue, green.blueValue, 1.0)
    let color3 = SCNVector4(blue.redValue, blue.greenValue, blue.blueValue, 1.0)
    let color4 = SCNVector4(yellow.redValue, yellow.greenValue, yellow.blueValue, 1.0)
    
    let animation = CAKeyframeAnimation()
    // animation.keyPath = "color" // has like no effect (?...)
    animation.values = [color1,color2,color3,color4]
    animation.keyTimes = [0, 0.333, 0.666, 1]
    animation.duration = 2.0
    animation.isAdditive = false // should overwrite default colours
    animation.isRemovedOnCompletion = true

     let colorController = SCNParticlePropertyController(animation: animation)
    explosion.propertyControllers = [SCNParticleSystem.ParticleProperty.color: colorController]

    return explosion
    
}

Apple 文档是这样说的:

Apple Discussion

这个属性的值是一个四分量向量(一个包含粒子属性控制器的SCNVector4值的NSValue对象,或者一个包含四个浮点值的数组粒子事件或修改器块)。 粒子系统的 particleColor 和 particleColorVariation 属性决定了每个粒子的初始颜色。

有趣的问题 This: https://developer.apple.com/documentation/scenekit/animation/animating_scenekit_content 显示了与 SCNTransaction 的类似调用,因此看起来您正在做的事情“应该”起作用。但是,它不是 SCNParticle 系统组件。使用粒子可能有点棘手。我对选择器的东西不是很好,所以我不能只看代码就知道。

particleColorVaration - 向量随机化指定的颜色。这听起来并不完全像您想做的,但它可能会让您接近 - 矢量按顺序指定范围(色调、饱和度、亮度、alpha)。

我认为文档有误。您的动画值数组应包含 UIColor 个对象。

animation.values = [UIColor.red, UIColor.green, UIColor.blue, UIColor.yellow]