Is there a way to create an SKTexture from an SKShapeNode? Shape nodes are known to cause memory issues and I am looking for a way to create a static graphic from them (.png preferably).
You can use the SKView
method called textureFromNode:
Here's from the reference :
textureFromNode:
Renders and returns a Sprite Kit texture that contains the node’s contents.
- (SKTexture *)textureFromNode:(SKNode *)node
Parameters
node
A node object representing the content you want to render to the texture.
Return Value
A Sprite Kit texture that holds the rendered image.
Discussion The node being rendered does not need to appear in the view’s presented scene. The new texture is created with a size equal to the rectangle returned by the node’s calculateAccumulatedFrame method. If the node is not a scene node, it is rendered with a clear background color ([SKColor clearColor]).
UPDATE-- After exploring SKShapeNode a bit and verifying there indeed was a memory leak issue revolving around assigning a path and then removing the node, I had an idea...
Not really a new idea, more of a repurposed one. This wonderful idea actually allowed me to use SKShapeNodes to my hearts content :)
POOLING
Yep... I just created a pool of SKShapeNodes that I reused as needed. What a difference that makes :) So simply redefine the path whenever needed, when done using return to your pool, and it'll be waiting there for you to play with again at a later time.
You simply redefine the path whenever needed, when done using return to your pool, and it'll be waiting there for you to play with again at a later time.
Create a ivar or property NSMutableArray
in your SKScene
called pool and create it when you init the SKScene
. You can either populate the array with your shape nodes during init, or you can create them as needed.
This is something quick method I created for grabbing a new node from the pool :
-(SKShapeNode *)getShapeNode
{
if (pool.count > 0)
{
SKShapeNode *shape = pool[0];
[pool removeObjectAtIndex:0];
return shape;
}
// if there is not any nodes left in the pool, create a new one to return
SKShapeNode *shape = [SKShapeNode node];
return shape;
}
So wherever in the scene you need a SKShapeNode you'd do this :
SKShapeNode *shape = [self getShapeNode];
// do whatever you need to do with the instance
When you are done using the shape node, just return it to the pool and set the path to . For example :
[pool addObject:shape];
[shape removeFromParent];
shape.path = NULL;
I know it's a workaround and not an ideal solution, but certainly this is a very viable workaround for anyone wanting to use a large number of SKShapeNodes and not bleed memory.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With