3

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.

Krekin
  • 1,516
  • 1
  • 13
  • 24
  • No such an optimisation in SpriteKit. What you can try is to use bitmap fonts but that will require complete rewrite. SKLabelNode is unperformant. It requires one draw call for rendering, so it should be used sparingly. Same as SKShapeNode for SKShapeNode, so it cant be drawn in batches like SKSpriteNode. – Whirlwind Dec 07 '16 at 09:11
  • One hint related to SKLabelNode - always double check if you are trying to use correct font name. If suplied name is wrong, some lag will occur because iOS will try to find that font anyway... – Whirlwind Dec 07 '16 at 09:15

2 Answers2

2

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
GRiMe2D
  • 654
  • 1
  • 10
  • 22
1

It seems to me you are creating new labels every time you need text. If I were you only create the label once, and just alter the text when needed as well as just hide the lines you are not using.

Another thing you can do is fill the text in on your label one time, then assign it to an SKCropNode. Then you can use the SKCropNode to bring the font characters back in, which in turn should give you a nicer scrolling effect since you are not doing it at one character at a time.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44