Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Copying SCNParticleSystem doesn't seem to work well

I'm trying to use an SCNParticleSystem as a "template" for others. I basically want the exact same properties except for the color animation for the particles. Here's what I've got so far:

if let node = self.findNodeWithName(nodeName),
    let copiedParticleSystem: SCNParticleSystem = particleSystemToCopy.copy() as? SCNParticleSystem,
    let colorController = copiedParticleSystem.propertyControllers?[SCNParticleSystem.ParticleProperty.color],
    let animation: CAKeyframeAnimation = colorController.animation as? CAKeyframeAnimation {

    guard animation.values?.count == animationColors.count else {

        return nil
    }

    // Need to copy both the animations and the controllers
    let copiedAnimation: CAKeyframeAnimation = animation.copy() as! CAKeyframeAnimation
    copiedAnimation.values = animationColors

    let copiedController: SCNParticlePropertyController = colorController.copy() as! SCNParticlePropertyController
    copiedController.animation = copiedAnimation

    // Finally set the new copied controller
    copiedParticleSystem.propertyControllers?[SCNParticleSystem.ParticleProperty.color] = copiedController

    // Add the particle system to the desired node
    node.addParticleSystem(copiedParticleSystem)

    // Some other work ...
}

I copy not only the SCNParticleSystem, but also SCNParticlePropertyController and CAKeyframeAnimation just to be safe. I've found that I've had to manually do these "deep" copies "manually" since a .copy() on SCNParticleSystem doesn't copy the animation, etc.

When I turn on the copied particle system on the node it was added to (by setting the birthRate to a positive number), nothing happens.

I don't think the problem is with the node that I've added it to, since I've tried adding the particleSystemToCopy to that node and turning that on, and the original particle system becomes visible in that case. This seems to indicate to me that the the node I've added the copied particle system to is OK in terms of its geometry, rendering order, etc.

Something else perhaps worth mentioning: the scene is loaded from a .scn file and not created programmatically in code. In theory that shouldn't affect anything, but who knows ...

Any ideas on why this copied particle system doesn't do anything when I turn it on?

like image 685
kevlar Avatar asked Apr 25 '17 06:04

kevlar


1 Answers

Do not use copy() method for particle systems !

copy() method does not allow copy particles' color (copied particles will be default white).

You can test it with the following code:

let particleSystem01 = SCNParticleSystem()
particleSystem01.birthRate = 2
particleSystem01.particleSize = 0.5
particleSystem01.particleColor = .systemIndigo                 // INDIGO
particleSystem01.emitterShape = .some(SCNSphere(radius: 2.0))

let particlesNode01 = SCNNode()
particlesNode01.addParticleSystem(particleSystem01)
particlesNode01.position.y = -3
sceneView.scene.rootNode.addChildNode(particlesNode01)

let particleSystem02 = particleSystem01.copy()                 // WHITE

let particlesNode02 = SCNNode()
particlesNode02.addParticleSystem(particleSystem02 as! SCNParticleSystem)
particlesNode02.position.y = 3
sceneView.scene.rootNode.addChildNode(particlesNode02)


Use clone() method for nodes instead !

clone() method works more consistently for 3d objects and particle systems and it can help you save particles' color but, of course, doesn't allow save a position for each individual particle.

let particlesNode02 = particlesNode01.clone()                  // INDIGO

particlesNode02.position.y = 3
sceneView.scene.rootNode.addChildNode(particlesNode02)
like image 156
Andy Jazz Avatar answered Nov 12 '22 06:11

Andy Jazz