Search code examples
iosobjective-csprite-kitsklabelnode

Optimizing SKLabelNode to reduce performance issues


Creating an RPG with SpriteKit has me creating SKLabelNode's for displaying all game text. I'm suffering performance issues (FPS dropping & the game lagging) every time my multi-line text box begins auto typing inputted text which uses SKLabelNode's. I also see performance hits when "summoning" UI elements, such as character stat panels (with lots of SKLabelNode's for skill levels, skills names, etc.).

Veteran developers say pre-loading data always helps, thus I did the following (which has reduced the performance hit but hasn't eliminated it & the text box still lags):

// Preloaded model label (private property that is initialized in the class init method).
_modelLabel = [[SKLabelNode alloc] initWithFontNamed:_fontName];
_modelLabel.fontColor = _fontColor;
_modelLabel.fontSize = _fontSize;
_modelLabel.text = @"T";

// Constantly created label.
SKLabelNode *rowText = [[SKLabelNode alloc] initWithFontNamed:self.modelLabel.fontName];
rowText.fontColor = self.modelLabel.fontColor;
rowText.fontSize = self.modelLabel.fontSize;
rowText.text = row;
...
[self addChild:rowText];

I would be grateful for getting some more optimizations tricks when using SKLabelNode's. Here are the tips I have collected thus far:

  • Preloading is only needed when using a font that is not available via iOS.

  • To get the font to actually load you need to also set the text for the preload to work.


Solution

  • Try to preload SKLabelNode with all chars you need. Maybe, SpriteKit renders only required glyphs into texture.

    // Preloaded model label (private property that is initialized in the class init method).
    _modelLabel = [[SKLabelNode alloc] initWithFontNamed:_fontName];
    _modelLabel.fontColor = _fontColor;
    _modelLabel.fontSize = _fontSize;
    _modelLabel.text = @"ABCDEFGHIJKLMNOPQRSTUVWXZabcdefghijklmnopqrstuvwxyz0123456789-+=_()";
    

    And then add your model into scene with minimal alpha (but no zero, because if node has 0 alpha, it will not drawn); Try to keep that node in scene

    _modelLabel.alpha = CGFLOAT_MIN;
    [self addChild:_modelLabel];
    

    If not helps:

    • Organize nodes by aligning their zPosition (aka z-index). You should disable ignoresSiblingOrder for having control over zPosition. Make your all SKLabelNode be drawn at one z level.
    • Switch to bitmap fonts. Writing custom bitmap font renderer is super easy. The only thing you should remember - Make all glyphs be in only texture atlas, so you can draw your text in one draw call
    • Use native labels. I'm not sure, how much does it help. If you're having heavy FPS drops (~5..10FPS) This may help you