SCNParticleSystem:コード内の「particleColor」プロパティのアニメーション化

Aug 24 2020

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

リンゴのドキュメントをさらに調査して参照したところ、最初のアプローチは間違っていたようです。これは、スポーンされたすべてのパーティクルに同時に影響を与えるためです。

しかし、それでも期待どおりに機能しません-すべてのパーティクルがシーン上で消えたり見えなくなったりします-それ以外の場合はエラーは発生しません。これにより、時間の経過とともに各パーティクルの色が変化するはずです。なにが問題ですか?

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ドキュメントはこれを言います:

アップルディスカッション

このプロパティの値は、4つのコンポーネントのベクトル(パーティクルプロパティコントローラーのSCNVector4値を含むNSValueオブジェクト、またはパーティクルイベントまたはモディファイアブロックの4つのfloat値の配列)です。パーティクルシステムのparticleColorプロパティとparticleColorVariationプロパティは、各パーティクルの初期カラーを決定します。

回答

1 JamesP Aug 28 2020 at 20:19

ドキュメントが間違っていると思います。アニメーション値の配列にはUIColorオブジェクトが含まれている必要があります。

animation.values = [UIColor.red, UIColor.green, UIColor.blue, UIColor.yellow]
Voltan Aug 24 2020 at 22:20

興味深い問題これ: https://developer.apple.com/documentation/scenekit/animation/animating_scenekit_contentはSCNTransactionを使用した同様の呼び出しを示しているため、実行していることは「機能するはず」のように見えます。ただし、これはSCNParticleシステムコンポーネントではありませんでした。パーティクルは、操作が少し難しい場合があります。私はセレクターのことは得意ではないので、コードを見ただけでは本当にわかりません。

particleColorVaration-ベクトルは指定された色をランダム化します。それはあなたがやりたいこととまったく同じようには聞こえませんが、それはあなたを近づけるかもしれません-ベクトルは範囲(色相、彩度、明るさ、アルファ)を​​この順序で指定します。