title: SceneKit – Particle transform animation along a path
body: <p>I am trying to achieve an airflow like animation along a custom node (loaded from <code>.usdz</code> file) but all I can achieve is that the particles flow all around or just stick to the node. How can I achieve that there is some kind of flow along the object?</p>
  <p>The Object looks something like this:
  <a href="https://i.stack.imgur.com/J2LSv.jpg" rel="nofollow noreferrer">usdz node object</a></p>
  <pre><code>let particleSystem = SCNParticleSystem()
  particleSystem.isLocal = true
  particleSystem.birthRate = 100
  particleSystem.emitterShape = child.geometry
  particleSystem.particleSize = 0.002
  particleSystem.particleLifeSpan = 20 //0.14
  particleSystem.particleColor = UIColor(red: 118.0/255.0, 
                                       green: 146.0/255.0, 
                                        blue: 190.0/255.0, 
                                       alpha: 1.0)
  particleSystem.isAffectedByGravity = false
  particleSystem.isAffectedByPhysicsFields = true
  particleSystem.birthLocation = .surface
  particleSystem.birthDirection = .surfaceNormal
  particleSystem.acceleration = SCNVector3(2, 1.8, 0)
  particleSystem.particleVelocity = 20
  
  let spring = SCNPhysicsField.drag()
  spring.isActive = true
  spring.strength = 100
  child.physicsField = spring
  particleSystem.particleColorVariation = SCNVector4(0, 0, 0.1, 1)
  particleSystem.blendMode = .alpha
  child.addParticleSystem(particleSystem)
  </code></pre>
  <hr />
  <p>Somehow I can't post the answer so here it is:</p>
  <p>I think I found the solution I was looking for.</p>
  <p>I found this code on stack overflow (I can not find the link anymore)</p>
  <pre><code>extension  SCNGeometry {
  
  
      /**
       Get the vertices (3d points coordinates) of the geometry.
  
       - returns: An array of SCNVector3 containing the vertices of the geometry.
       */
      func vertices() -&gt; [SCNVector3]? {
  
          let sources = self.sources(for: .vertex)
  
          guard let source  = sources.first else{return nil}
  
          let stride = source.dataStride / source.bytesPerComponent
          let offset = source.dataOffset / source.bytesPerComponent
          let vectorCount = source.vectorCount
  
          return source.data.withUnsafeBytes { (buffer : UnsafePointer&lt;Float&gt;) -&gt; [SCNVector3] in
  
              var result = Array&lt;SCNVector3&gt;()
              for i in 0...vectorCount - 1 {
                  let start = i * stride + offset
                  let x = buffer[start]
                  let y = buffer[start + 1]
                  let z = buffer[start + 2]
                  result.append(SCNVector3(x, y, z))
              }
              return result
          }
      }
  }
  </code></pre>
  <p>And here the animation itself.</p>
  <pre><code>        let moveAround = SCNNode(geometry: SCNSphere(radius: 0.01))
          moveAround.geometry?.materials.first?.diffuse.contents = UIColor(red: 30, green: 150, blue: 30, alpha: 1.0)
          
          let particleSystem = SCNParticleSystem()
          particleSystem.isLocal = true
          particleSystem.birthRate = 20
          particleSystem.particleSize = 0.006
          particleSystem.particleLifeSpan = 0.14
          particleSystem.particleColor = UIColor(red: 118.0/255.0, green: 146.0/255.0, blue: 190.0/255.0, alpha: 1.0)
          particleSystem.birthLocation = .surface
          particleSystem.birthDirection = .surfaceNormal
          particleSystem.acceleration = SCNVector3(1, 0, 0)
          moveAround.addParticleSystem(particleSystem)
          child.addChildNode(moveAround)
          
          let points = child.geometry?.vertices() ?? []
          var actionArray: [SCNAction] = []
          
          for i in points {
              
              let action = SCNAction.move(to: i, duration: 0.01)
              actionArray.append(action)
          }
          
          let moveSequence = SCNAction.sequence(actionArray)
          let moveLoop = SCNAction.repeatForever(moveSequence)
          moveAround.runAction(moveLoop)
  </code></pre>