6

at the moment I'm coding a little app with SpriteKit, which works perfectly fine, but the only problem is an SKLabelNode, which I initialize with the following normal piece of code:

​self.scoreLabel = [SKLabelNode labelNodeWithFontNamed:@"Futura"];
self.scoreLabel.fontSize = 190.0f;
self.scoreLabel.color = [SKColor whiteColor];
self.scoreLabel.alpha = .2;
self.scoreLabel.text = @"00";
self.scoreLabel.position = CGPointMake(screenWidth/2,self.scoreLabel.frame.size.height/2);
[self addChild:self.scoreLabel];

There a many more things to initialize, but they doesn't affect anything. If I comment out the code above, the app loads in the usual time. With the SKLabelNode it delays the loading by few seconds...

Hope anyone can help me.

maelswarm
  • 1,163
  • 4
  • 18
  • 37
appcodix
  • 342
  • 2
  • 15
  • Does it lag on simulator, actual device, or both? In general with sprite kit I've found that using the simulator isn't reliable. – maelswarm Apr 23 '14 at 21:14
  • More precisely: In general Simulator isn't reliable as in "not an accurate representation of device behavior, performance and visuals". Where in doubt (that's basically every inexplicable issue) always verify on a device. – CodeSmile Apr 23 '14 at 21:18
  • Does the behavior change if you use other fonts like Arial, Helvetica or Courier? – CodeSmile Apr 23 '14 at 21:20
  • 1. It lags on the actual device. It's fluently in the simulator (or a bit more fast). 2. Other Fonts doesn't change the behavior... – appcodix Apr 23 '14 at 22:05

3 Answers3

9

Actually, you don't need to preload the font for an SKLabelNode. The delay is caused by the fact that you're using the wrong font name. There's no "Futura" font on iOS - what you probably mean is "Futura-Medium". Replace "Futura" with "Futura-Medium", and you should see the load time drastically fall.

(You can still preload your fonts, but it's not necessary; lazy loading is pretty fast provided you use a correct font name.)

cc.
  • 3,041
  • 1
  • 21
  • 24
  • 1
    Amazing. You have no idea how much time I'd put into profiling and looking into possible resource-intensive culprits. And in the end it was one misplaced hyphen in the font name that was freezing my app for 2 seconds! – Stan James Oct 01 '14 at 21:58
  • Glad to help. I had spent a long time trying to figure it out, too. – cc. Oct 08 '14 at 16:13
  • I've got the same problem, and have used (supposedly) installed fonts http://support.apple.com/en-gb/HT202771 and I still get the delay. Preloading just moves the delay sooner.. Is there a way to preload in a thread? – GilesDMiddleton Jan 12 '15 at 21:56
  • 1
    Yours is the correct answer - I've added another answer that distinguishes from loading the entire font family - which will appear to 'work' but be really really slow. – GilesDMiddleton Jan 16 '15 at 13:06
5

Be careful you aren't loading the entire font family. If I load "Chalkboard SE" it will take 4-6 seconds, and appear to work.

But if I load ChalkboardSE-Regular , it's virtually instantaneous ~100ms or less.

If you want to know more, I've got various links and timings on my humble blog. https://gilesey.wordpress.com/2015/01/14/ios-spritekit-font-loading-times-of-sklabelnodes/

GilesDMiddleton
  • 2,279
  • 22
  • 31
  • 1
    This is the correct answer. Problem with delay happens only when loading entire family fonts. If a font name is properly set, loading times are instant. – sabiland Sep 01 '15 at 10:16
2

You need to preload the font so that when you first call your SKScene sprite kit already has the font ready in memory. The best way to do this is to either use the app delegate or a singleton as soon as you can in your games life cycle.

self.scoreLabel = [SKLabelNode labelNodeWithFontNamed:@"Futura"];
self.scoreLabel.text = @"preload";

You don't need to make the label global, just make sure you keep a strong reference to let the compiler know you want it to keep the font in memory. Also make sure you set the text property (the font is only loaded when you set this).

EDIT:

This is what I am using:

- (void)setupFonts {
    SKLabelNode *preloadFontLabel = [SKLabelNode labelNodeWithFontNamed:@"HelveticaNeue-UltraLight"];
    [preloadFontLabel setText:@"Preload"];
}

This is called from a game assets singleton right when the game starts, I also have a call-back that stops the "PLAY" button appearing before the assets have loaded so the user can't jump the gun until everything is up and loaded. My game assets only take 1.03secs to load so its not an issue, but you could also hide a longer load behind a splash/startup screen if needed.

If your still seeing a problem I would check you don't have any other fonts in your SKScene that your not preloading. Also it could be an issue with loading a custom font, try changing the font to "HelveticaNeue-UltraLight" and see if you get the same issue.

fuzzygoat
  • 26,573
  • 48
  • 165
  • 294
  • I actually put my code in the AppDelegate and it delays the start of the app as mentioned. First I had it in the SKScene, so it delayed the start of the game from the Menu. – appcodix Apr 23 '14 at 22:10
  • Thank you so much !!! The problem was indeed the font... With AvenirNextCondensed e.g. there are no issues. – appcodix Apr 24 '14 at 20:57
  • No problem at all, glad you got it sorted. – fuzzygoat Apr 24 '14 at 21:48
  • Note that preloading fonts is not typically necessary unless you're doing a lot of different fonts; this problem usually stems from using an incorrect font name. When you use the correct font name ("Futura-Medium" instead of "Futura", for instance), the SKLabelNode loads almost instantaneously. – cc. Jun 25 '15 at 15:45