How to Cache or Preload Sklabelnode Font

How to cache or preload SKLabelNode font?

We had this issue, and it turned out that we were simply not using the "correct" font name. In our case, we were using "Menlo" instead of "Menlo-Regular" when instantiating our SKLabelNode, and it was incurring the several-second penalty. Once we used the correct font name, the delay no longer happened.

(Curiously, the SKLabelNode still found Menlo and used it, so it was not immediately obvious that we had the wrong font name. Presumably, the delay is caused by the system having to figure out the appropriate substitute to use. It does a good job, finding the font we intended to use, but it takes a while to do it, hence the delay.)

How to cache or preload SKLabelNode font in spritekit

You can set the font once by initializing an UIFont:

let yourFont = UIFont(name: "yourfontName", size: 17)

var firstLabel = SKLabelNode(fontNamed: yourFont?.fontName)
var secondLabel = SKLabelNode(fontNamed: yourFont?.fontName)

That way, you only set the font once and the SKLabelNodes don't have to load it by themself.

Optimizing SKLabelNode to reduce performance issues

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

Resize a SKLabelNode font size to fit?

I was able to solve this thanks to a comment by @InvalidMemory and the answer by @mike663. Basically you scale the label in proportion to the rectangle that contains the label.

func adjustLabelFontSizeToFitRect(labelNode:SKLabelNode, rect:CGRect) {

// Determine the font scaling factor that should let the label text fit in the given rectangle.
let scalingFactor = min(rect.width / labelNode.frame.width, rect.height / labelNode.frame.height)

// Change the fontSize.
labelNode.fontSize *= scalingFactor

// Optionally move the SKLabelNode to the center of the rectangle.
labelNode.position = CGPoint(x: rect.midX, y: rect.midY - labelNode.frame.height / 2.0)
}

Here is the link to the other question.

Delay when calling SKLabelNode?

The delay is based on the loading of your font. Best to preload fonts, sounds, and any other assets you intend to use, so that you don't have a delay when it's actually used the first time.

You can preload in your setup with :

SKLabelNode *preload = [SKLabelNode labelNodeWithFontNamed:@"System"];
[preload setText:@"anything"];

As noted in the comments, preloading is only needed when using a font that is not available via iOS.

SpriteKit reducing SKLabelnode draw calls

Depending on what you're doing and when, you could render out the contents of the labels into textures at runtime (pre-loading / caching), and then manipulate them in any ways you'd like.

SKLabelNode *theThingToBecomeATexture;
//OR
SKSpriteNode *theThingToBecomeATexture;

SKTexture *theTexture = [theView textureFromNode:theThingToBecomeATexture];

But my follow up question or comment would be: I have a difficult time believing that you are running into performance problems by showing a few dozen label nodes on the screen. I can understand you hitting a load spike if you are trying to alloc and init a number of them all at the same time, in which case, I would preload them, or alloc them not on the main thread.



Related Topics



Leave a reply



Submit