Quite an old question, but I came across this issue from time to time. The colorBlendFactor
is not what one might expect, that it recolours sprites. In fact, the new colour, blended over the old one, heavily depends on the color that was at that position before.
To overcome this, I use overlying sprites (as mentioned before) and the alpha values of the underlying and the overlaying sprite to create the expected colours.
For example to blend the following sprite slowly from blue to gray, I use two sprites:


(The blue sprite is the original one and the grey one is just a version of the blue one, manipulated with the ColorSync Utility
on the Mac.)
and this code (Swift):
// Load the two Textures
let TEXTURE_CLOUD_BLUE = SKTexture(imageNamed: "cloud blue")
let TEXTURE_CLOUD_GRAY = SKTexture(imageNamed: "cloud gray")
// Create an Action. Note that the second Action takes longer to finish. This makes the blend to grey slower and easier to watch
let fadeToGray = SKAction.group([
SKAction.runAction(SKAction.fadeOutWithDuration(1.0), onChildWithName: "cloudBlue"),
SKAction.runAction(SKAction.fadeInWithDuration(2.0), onChildWithName: "cloudGray"), // Slower fade in
SKAction.waitForDuration(2.0) // Actions on children return immediately
])
// Init super sprite node
super.init(texture: nil, color: UIColor.clearColor(), size: size)
// Add blue cloud
let cloudBlue = SKSpriteNode(texture: TEXTURE_CLOUD_BLUE, size: size)
cloudBlue.alpha = 1.0 // Show immediately
cloudBlue.name = "cloudBlue"
addChild(cloudBlue)
// Add grey cloud
let cloudGray = SKSpriteNode(texture: TEXTURE_CLOUD_GRAY, size: size)
cloudGray.alpha = 0.0 // Don't show at start
cloudGray.name = "cloudGray"
addChild(cloudGray)
// Run Action to fade away
self.runAction(fadeToGray)
Quite some code. I hope the idea comes across. You can play around with the times in the action or use fadeAlphaTo/By
instead of fadeIn/OutWithDuration
to produce the desired effects.