This question raised my curiosity. I have a solution, but, for lack of my knowledge of Swift, have written it in Objective-C. It is very simple, however, and porting should be of no problem to you.
The trick is to flatten the entire node into a single texture and fade that instead.
I have implemented this using a Category. The code below replaces the texture
property of an SKSpriteNode with a flattened texture. The key method is -textureFromNode: inside the SKView
class.
@interface SKSpriteNode (Fading)
- (void)flattenForFading;
@end
...
#import "SKSpriteNode+Fading.h"
@implementation SKSpriteNode (Fading)
- (void)flattenForFading {
SKTexture *flattenedContents = [self.scene.view textureFromNode:self];
/// Copy the children array, so when we are iterating the removing doesn't cause any problems
NSArray *children = [self.children copy];
for (SKNode *child in children) {
[child removeFromParent];
}
self.texture = flattenedContents;
self.size = self.texture.size;
}
@end
In the case of a non-SKSpriteNode case you can just add a new SKSpriteNode as a child of the node being flattened. Animation inside the node is not supported since you're baking a single texture. Instead of removing all children, you could just hide them as well of course. If you would add an extra property for the removed texture, you could even save the internal state and revert this method's effect with a -unflatten
method. But that goes beyond the scope of your question.
I took this screenshot in the Simulator. Note that the node counter corresponds with the 3 faded SKSpriteNodes, 1 SKLabelNode and 1 flattened sprite (SKSpriteNode).