How do I repeat an animation multiple times simultaneously with respect to performance?

172 Views Asked by At

I am aiming to have all these waves animate identically, for performance reasons. This will help by reducing the cost of calculating wave paths, and to reduce the draw count.

I have a scene in SpriteKit setup like so:

Scene → There is a link to an animating version here.

The scene is mainly composed of 2 things:

  • Stones (the light and dark grey hexagons)
  • Waves (there are 2 per stone - a lighter and a darker blue animating path)

The waves are create like so:

// Wave outline shape node
shapeNode               = SKShapeNode(path: self.oldPath)
shapeNode.strokeColor   = wave.color
shapeNode.lineWidth     = 5
shapeNode.zPosition     = waveIndex == 0 ? Layer.farWave : Layer.nearWave
shapeNode.lineJoin      = .round
shapeNode.position      = stoneCell.node.position.offset(by: stoneCell.offsetVector)
view.scene?.addChild(shapeNode)

// Layer which creates the animation
shapeLayer = CAShapeLayer()
shapeLayer.isHidden = true
view.layer.addSublayer(shapeLayer)

animate()

And the animate() function:

/// Animates the wave's path. This method calls itself forever.
private func animate() {
    let newPath = WavePath(wave: wave, direction: currentDirection).createPath()

    let anim = CABasicAnimation(keyPath: "path")
    anim.duration   = 2  // Duration of the wave movements in a direction (in or out)
    anim.fromValue  = oldPath
    anim.toValue    = newPath
    anim.timingFunction = CAMediaTimingFunction(name: .easeInEaseOut)

    shapeLayer.path = newPath
    shapeLayer.add(anim, forKey: nil)

    shapeNode.run(SKAction.customAction(withDuration: anim.duration, actionBlock: { (node, timeDuration) in
        (node as? SKShapeNode)?.path = self.shapeLayer.presentation()?.path
    }), completion: {
        self.oldPath = newPath
        self.currentDirection.toggle()
        self.animate()
    })
}

The problems arise because there are 10 stones on the scene, which increases the performance cost. Is there a way to make this wave animation duplicated under all these stones?

Possible options I can think of:

  • Convert the paths into a texture, which could be shared between multiple stones? However I think this would be slow to convert to a texture twice (for each wave) per frame, and then copy it over...

  • Rendering a full animation pass of the wave going in and then out, and then putting that on a loop for every node. But how?

What other solutions may be better?

I do not want to create an atlas and animate it. I cannot do this because these stones and waves change in size, depending on the screen size and level and I want them pixel-perfect. I do not mind however (as mentioned in bullet point two) of storing textures of an animation loop and then repeating that.

0

There are 0 best solutions below