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]
我想仅在代码中为 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]