Unity3D for iOS: Switching From GUI to UIToolKit for Text & Menus to Improve Performance

UIToolkit is an open source Unity plugin specifically created for optimized performance on mobile devices (via reduced number of draw calls). Here’s a good summary of why Unity3D’s default GUI is not a good choice for mobile devices, key ones being:

  • Excessive draw calls…
  • Draws excessive processing power when using GUI, even worse with GUILayout… In-game GUI still requires high performance, and the overhead of calling GUI, or GUILayout are just too big to overlook even on today’s high-powered phones.

Setting Up

1. Download the .unitypackage from UIToolkit’s downloads page on GitHub.

2. I mostly followed the developer’s instructions, using a mix of:

  • “Setup” instructions on their Github page
  • the two intro videos
  • the code examples in the demo scenes that come with the package download (Github).

You can also try this quick “how to” from UnityAnswers. Just remember, to add UIToolkit elements via code you also have to create a public var in your script & use the Inspector to assign a one of the UIToolkit instances under the UI GameObject in your Hierarchy.

NOTE: don’t expect TweenLite or iTween style performance from UIToolkit’s built-in animation engine. Also note, UIToolkit-based UI can’t be animated with iTween, as far as I’ve seen.

Make the texture atlases for your buttons

Created 2 texture maps for the buttons containing Up and Down states for the 4 buttons using the free version of TexturePacker. The 2nd texture map had the “2x” added to each file name, for iPhone retina display. CORRECTION: When creating the individual graphic slices in GIMP or Photoshop, make sure to name the regular and “2x” versions of the same slice the same exact file name (no “2x”). This will ensure that the respective .txt JSON files generated by TexturePacker will have the 2 sizes named the same and as long as the retina sprite sheet .png file generated by TexturePacker has the “2x” in it’s file name, UIToolkit will grab the correct image size automatically.

Note: the free version of Texture Packer won’t allow you to efficiently size the image to minimize empty space.

UPDATE, 08.09.2012: Unity3D doesn’t allow TexturePacker Pro’s “Allow free sizes” checkbox to do it’s thing. It’s tempting to use it because it cuts the overall size of the sprite sheet but looks like Unity ends up flipping out and stretches the resultant image, forcing it into value it recognizes like 256, 512, 1024, 2048.

UPDATE, 08.10.2012: UIToolkit currently doesn’t support TexturePacker Pro’s rotated sprites (“Allow rotation” checkbox). Looks like someone tried to add that functionality but didn’t have time to finish.

Convert fonts to bitmaps (.png and .fnt files) for use with TexturePacker and Unity: AngelCode’s BMFont on Windows

Converted my fonts to Bitmap font files with .fnt extension. Hiero, the free bitmap font conversion tool for Mac has some limitations (like it doesn’t allow you to turn off antialiasing for small copy fonts). There’s a free Windows tool that does called Angelcode Bitmap Font Generator. Glyph Designer is relatively inexpensive alternative.

I first tried using AngelCode’s BMFont tool on Windows XP via Parallels and it generated these two .png & a .fnt files for my font:

Prior to Unity import, I renamed .fnt files to .txt.

Here’re some screenshots of Font and Export settings I used in Angelcode’s bitmap font tool (click to for larger image):

After importing the .png, .txt (.fnt) and .txt (JSON) files into an empty Unity scene and setting it up correctly, I got no errors in the Console and no fonts on screen (link to .unitypackage of this project).

I suspect the problem is in the font files and not in my UIToolkit or Project setup because I also included the Text demo files from UIToolkit in the .unitypackage above. When I tried to simply switch the font to the “prototype” example and it’s associated texture in Inspector, everything worked. It’s only when I switched the .fnt and texture from Angelcode that the text failed to show up. UPDATED, 04.09.2012: After taking a look at UIText.cs, I realized I was wrong – the problem was in the way I was calling the UIText constructor. For correct usage, see the mainMenuScript.js code example below.

Convert fonts to bitmaps: Hiero on Mac

Hiero ran fine the first time for the standard fonts version, however when I tried to change the settings for the “2x” version of the font it got super sluggish on me. I reinstalled the Hiero .jnpl numerous times, restarted my system, etc., to no avail. Hiero ran super slow 1 minute or so after launch on OS X 10.6.8, java version “1.6.0_31”, JRE build 1.6.0_31-b04-413-10M3623. UPDATE: after looking into it more, it seems like the main performance culprit with Hiero is the ASCII button under the “Sample Text” text box. When, instead of hitting that button, I manually copy/pasted in some of the extra characters I needed, the freezing & sluggishness issues didn’t happen.

The PNG created from Hiero had the text upside down, so I had to open the PNG in Photoshop & do a Edit > Transform > Flip Vertical to fix that.

Still same problem – no Console errors and no text showing up on screen in Unity. Here’s the .unitypackage that uses the Hiero fonts. Now fixed, see below.

GlyphDesigner is a good not-free alternative to Hiero on Mac. It’s around $30.

Make texture atlases for your fonts with TexturePacker

Created 2 more texture maps for Fonts using the .png files created by your bitmap fonts program. One for each device resolution (standard & retina), using Unity’s “2x” naming convention for the retina sprite sheet’s name. Basically, you need this step to generate the JSON formatted .txt files that will serve as a map for the .png that contains all of the font characters.

NOTE: When creating the individual graphic slices in GIMP or Photoshop, make sure to name the regular and “2x” versions of the same slice the same file name. This will ensure that the respective .txt JSON files will have the 2 sizes named the same and as long as the retina sprite sheet .png file generated by TexturePacker has the “2x” in it’s file name, UIToolkit will grab the correct image size automatically.

If you used Hiero – your font .png files will be flipped upside down. Just open them in Photoshop & do a vertical flip.

Import .txt (.fnt), .png (font texture atlas) and .txt (JSON texture atlas info) into a Unity project

Here’s a working UIText .unitypackage for iOS and one w/ Build Settings changed to Android (still developed on Mac). NOTE: If you’re on Windows, the iOS sample might not import because you’re missing the iOS SDK (blame Steve Jobs). I included the Android version – hopefully it will work for Windows users (let me know in the comments, either way). This sample is using two UIToolkit objects under one UI parent, including a UIText instance. Compare the mainMenuScript.js with it’s counterpart in earlier unsuccessful attempt for iOS.

If the font shows up with vertical bleeding at the top of the letters and the bottom of the letters being cut off, here’s an easy fix. Open the gunplayDemoSheet2x.txt (JSON) file and change the “y” value of the “frame” from 0 to 2.

"frame": {"x":0,"y":2,"w":1024,"h":321},

mainMenuScript.js

#pragma strict

var textToolkit2:UIToolkit;
var buttonToolkit:UIToolkit;

function Start() {

	//this gives no errors BUT fonts don't show up...: 
	//var text = new UIText( textToolkit2, "gunplayDemoSheet", "gunplay.png" ); //UIText(obj, "name_of_texture_in_Resources_folder", 'line 3 in .fnt file')	
	
	//set Game panel to iPhone 4G Tall (640x960): 
	var text = new UIText( textToolkit2, "gunplay", "gunplay.png" ); //UIText(obj, "name .fnt (.txt) file in Resources folder", 'line 3 in .fnt file')	
		
	var x = UIRelative.xPercentFrom( UIxAnchor.Left, .1f ); //0.1f = 10% from Left
	var y = UIRelative.yPercentFrom( UIyAnchor.Top, .05f ); //0.5f = 5% from Top
	text.addTextInstance( "Finally some \ntext. Oops, there's \nbleeding. Need to \nfix the \ntexture map.", x, y );	
	

	var newGameBtn = UIButton.create( buttonToolkit, "playAgainUp.png", "playAgainDown.png", 0, 0 );
	newGameBtn.positionFromTopLeft(.5f, .2f); 	
	newGameBtn.highlightedTouchOffsets = new UIEdgeOffsets( 30 );

}

Here’re the settings screenshots to hook everything up (NOTE: In the screenshots below and code sample above I’m using a True Type font called Gunplay; in the AngelCode and Hiero screenshots I was using Gotham – sorry, if that’s confusing, I haven’t had the time to update those.):

Here’s an example of the UI parent object set up with more than one child. UI > “UIToolkit – buttons” object:

UI > “UIToolkit – text” object:

Advertisements

2 thoughts on “Unity3D for iOS: Switching From GUI to UIToolKit for Text & Menus to Improve Performance

  1. Pingback: Unity3D for iOS: UIToolkit Text & Buttons Animation Example « timshaya

  2. Pingback: Unity3D for iOS: Multiple Fonts with UIToolkit « timshaya

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s