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
(akaz-index
). You should disableignoresSiblingOrder
for having control overzPosition
.
Make your allSKLabelNode
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
Storing and Retrieving Image in SQLite with Swift
Mobile Safari Position:Fixed Z-Index Glitch When Scrolling
Downloading Uiimage via Alamofireimage
Uibutton Touch Is Delayed When in Uiscrollview
Format Uilabel with Bullet Points
How to Set Uitableviewcellstylesubtitle and Dequeuereusablecell in Swift
Swiftui: Make Scrollview Scrollable Only If It Exceeds the Height of the Screen
Different Font Size for Different Devices in Xcode 6
Webkit Overflow Scrolling Touch CSS Bug on iPad
How to Handle iPhone Screen Sizes/Resolution for Background Images
How Do We Create a Bigger Center Uitabbar Item
Swift Stack and Heap Understanding