The Next-Gen User Interface kit is a plugin for Unity 3D. It has the great advantage of being easy to use, very powerful, and optimized compared to Unity's built-in GUI system, UnityGUI. Since it is written in C#, it is easily understandable and you may tweak it or add your own features, if necessary.
The NGUI Standard License costs $95. With this, you will have useful example scenes included. I recommend this license to start comfortably—a free evaluation version is available, but it is limited, outdated, and not recommended.
Let's have an overview of the main features of this plugin and see how they work.
With Unity's GUI, you must create the entire UI in code by adding lines that display labels, textures, or any other UI element on the screen. These lines have to be written inside a special function,
OnGUI(), that is called for every frame. This is no longer necessary; with NGUI, UI elements are simple GameObjects!
You can create widgets—this is what NGUI calls labels, sprites, input fields, and so on—move them, rotate them, and change their dimensions using handles or the Inspector. Copying, pasting, creating prefabs, and every other useful feature of Unity's workflow is also available.
These widgets are viewed by a camera and rendered on a layer that you can specify. Most of the parameters are accessible through Unity's Inspector, and you can see what your UI looks like directly in the Game window, without having to hit the Play button.
Sprites and fonts are all contained in a large texture called atlas. With only a few clicks, you can easily create and edit your atlases. If you don't have any images to create your own UI assets, simple default atlases come with the plugin.
That system means that for a complex UI window composed of different textures and fonts, the same material and texture will be used when rendering. This results in only one draw call for the entire window. This, along with other optimizations, makes NGUI the perfect tool to work on mobile platforms.
NGUI also comes with an easy-to-use event framework that is written in C#. The plugin comes with a large number of additional components that you can attach to GameObjects. These components can perform advanced tasks depending on which events are triggered: hover, click, input, and so on. Therefore, you may enhance your UI experience while keeping it simple to configure. Code less, get more!
NGUI comes with its own localization system, enabling you to easily set up and change your UI's language with the push of a button. All your strings are located in the
.txt files: one file per language.
Lighting, normal mapping, and refraction shaders are supported in NGUI, which can give you beautiful results. Clipping is also a shader-controlled feature with NGUI, used for showing or hiding specific areas of your UI.
We've now covered what NGUI's main features are, and how it can be useful to us as a plugin, and now it's time to import it inside Unity.
Create a new Unity project.
Navigate to Window | Asset Store. Select your download library.
Click on the Download button next to NGUI: Next-Gen UI.
When the download completes, click on the NGUI icon / product name in the library to access the product page.
Click on the Import button and wait for a pop-up window to appear.
Check the checkbox for NGUI v.3.0.2.unitypackage and click on Import.
In the Project view, navigate to Assets | NGUI and double-click on NGUI v.3.0.2.
A new imported pop-up window will appear. Click on Import again.
Click any button on the toolbar to refresh it. The NGUI tray will appear!
The NGUI tray will look like the following screenshot:
You have now successfully imported NGUI to your project. Let's create your first 2D UI.
Before we continue, please save your scene as
Layer: This is the layer on which your UI will be displayed
Camera: This will decide if the UI will have a camera, and its drop-down options are as follows:
None: No camera will be created
Simple 2D: Uses a camera with orthographic projection
Advanced 3D: Uses a camera with perspective projection
Click on the drop-down menu next to the Layer parameter.
Select Add Layer.
Create a new layer and name it
Go back to the UI Wizard window and select this new GUI2D layer for your UI.
You can now click on the Create Your UI button. Your first 2DUI has been created!
UI Root (2D)
Let's now review each in detail.
The UIRoot component scales widgets down to keep them at a manageable size. It is also responsible for the Scaling Style—it will either scale UI elements to remain pixel perfect or to occupy the same percentage of the screen, depending on the parameters you specify.
Select the UI Root (2D) GameObject in the Hierarchy. It has the
UIRoot.cs script attached to it. This script adjusts the scale of the GameObject it's attached to in order to let you specify widget coordinates in pixels, instead of Unity units as shown in the following screenshot:
Scaling Style: The following are the available scaling styles:
PixelPerfect: This will ensure that your UI will always try to remain at the same size in pixels, no matter what resolution. In this scaling mode, a 300 x 200 window will be huge on a 320 x 240 screen and tiny on a 1920 x 1080 screen. That also means that if you have a smaller resolution than your UI, it will be cropped.
FixedSize: This will ensure that your UI will be proportionally resized depending on the screen's height. The result is that your UI will not be pixel perfect but will scale to fit the current screen size.
FixedSizeOnMobiles: This will ensure fixed size on mobiles and pixel perfect everywhere else.
Manual Height: With the FixedSize scaling style, the scale will be based on this height. If your screen's height goes over or under this value, it will be resized to be displayed identically while maintaining the aspect ratio (width/height proportional relationship).
Minimum Height: With the PixelPerfect scaling style, this parameter defines the minimum height for the screen. If your screen height goes below this value, your UI will resize. It will be as if the Scaling Style parameter was set to FixedSize with Manual Height set to this value.
Maximum Height: With the PixelPerfect scaling style, this parameter defines the maximum height for the screen. If your screen height goes over this value, your UI will resize. It will be as if the Scaling Style parameter was set to FixedSize with Manual Height set to this value.
Even though the UI will look the same on different resolutions, the aspect ratio is still a problem since the rescale is based on the screen's height only. If you want to cover both 4:3 and 16:9 screens, your UI should not be too large—try to keep it square. Otherwise, your UI might be cropped on certain screen resolutions.
On the other hand, if you want a 16:9 UI, I recommend you force this aspect ratio only. Let's do it now for this project by performing the following steps:
Navigate to Edit | Project Settings | Player.
In the Inspector option, unfold the Resolution and Presentation group.
Unfold the Supported Aspect Ratios group.
Check only the 16:9 box.
Now that we have seen the UI Root's different parameters, let's discuss the camera.
Its purpose is to send different messages concerning events that happen to UI elements such as colliders attached to a button. Some of the more frequently used events are
You may have multiple cameras if you consider it necessary; for example, you can have an orthographic camera for 2D in-game UI elements and a separate perspective camera for a 3D pause menu.
For the purpose of this book, we will stick with only one camera.
Event Type: Select which event type this camera will send.
World: This is used for interacting with 3D-world GameObjects
UI: This is used for interacting with the 2D UI
Event Mask: Select which layer will be used to receive events.
In our case, we will set it to GUI2D since our UI will reside on it.
Debug: This consists of the enable or disable debug mode options. This option is useful when you have unwanted behavior.
Enabled: When Debug is enabled, the currently hovered object will be displayed on the top left-hand corner of the screen
Allow Multi Touch: This consists of the enable or disable touch mode options that allow simultaneous touches. This is mandatory if you want to use pinch-to-zoom or other such gestures on mobile platforms.
Enabled: If you drag your finger out of a pressed button, it will remain in the pressed state and no other element will receive upcoming events from that finger until it is released
Disabled: If you drag your finger out of a pressed button, it will no longer be pressed and other elements will receive upcoming events from that finger
Sticky Tooltip: It consists of the enable or disable sticky tool tip mode options.
Enabled: The tool tip disappears when the mouse moves out of the widget
Disabled: The tool tip disappears as soon as the mouse moves
Tooltip Delay: It consists of the required stationary time in seconds before the widget's tool tip is displayed.
Raycast Range: A raycast is an invisible ray that is cast from one point towards a specific direction and is stopped if it encounters another object. The camera uses raycasts from the mouse or touch position towards the camera's forward direction to detect collisions and handle events. You may set the range of this raycast if you need to limit the interaction to a certain range. The default -1 value implies that the raycast's range will be as far as the camera can see.
Event Sources: These Booleans let you specify what events this camera listens to.
Mouse: This is used for mouse movements, left/right/middle click, and scroll wheel.
Touch: This is used for touch-enabled devices.
Keyboard: This is used for keyboard input. It uses the
Controller: This is used for joystick-based devices. It uses the
Thresholds: These values come in handy when you want to specify the minimum values before a particular event is triggered. This may vary from one game/app to another.
Mouse Drag: When a mouse button is pressed (the
OnPress()event is triggered), this value determines how far in pixels the mouse must move before it is considered a drag, and sends
OnDrag()events to the dragged object
Mouse Click: When a mouse button is pressed (the
OnPress()event is triggered), this value determines how far in pixels the mouse can travel before the button release has no effect (the
OnClick()event is not triggered)
Touch Drag: This is the same as Mouse Drag, but for touch-based devices
Touch Tap: This is the same as Mouse Click, but for touch-based devices
Horizontal: This is the input axis for horizontal movement (the left and right key events)
Vertical: This is the input axis for vertical movement (the up and down key events)
Scroll: This is the input axis for scrolling
Submit 1: This is the primary keycode for validation
Submit 2: This is the secondary keycode for validation
Cancel 1: This is the primary keycode for cancel.
Cancel 2: This is the secondary keycode for cancel.
Ok, we have seen what the main parameters of the
UICamera component are. We have to see what the camera's anchor child is.
Select the Anchor GameObject in the Hierarchy view. It has the UIAnchor component attached to it. It is configured to center content on the screen based on the parent camera.
Before we create widgets, we must understand how these UIAnchor parameters modify their placement behavior.
These parameters are as follows:
Ui Camera: This is the reference camera from which our anchor bounds are determined. By default, it is set to the camera used by the UI.
Container: If you drag and drop a GameObject in this field, it will overwrite the camera anchoring. This can be useful if you need to anchor your panels or widgets based on a container GameObject, instead of a camera. Your content will be placed using the assigned container's position.
Side: Do you want your child GameObjects to be centered or attached to one side or corner of your referenced camera/container? You can choose your anchor point here.
Half Pixel Offset: You should leave this Boolean checked. It makes widget positions pixel perfect on Windows machines.
Run Only Once: This Boolean can be checked if your screen resolution never changes, or if you want it to remove it on start. As a result, your anchor will be executed at the start and then removed and no longer be updated.
Relative Offset: This
Vector2class takes two values between -1 and 1 to add a relative offset to the final position. With a value of 0.12 for X and 0.32 for Y, it will result in an offset of 12% horizontally and 32% vertically—it will look the same on any resolution because the offset depends on the screen size.
Pixel Offset: This parameter is like Relative Offset, but it is absolute instead of relative. You can enter the offset in pixels—it will look different depending on the resolution because the offset will stay identical in pixels on all screen sizes.
Depth: This is used to define which panel is rendered over another. A panel with a depth value of 1 will appear in front of a panel with a depth value of 0. You can use either the Back or Forward button to change the Depth or simply enter a number in the field. Panels can also have negative depth.
Normals: This Boolean must be checked if you need it to react to lighting using shaders. It will calculate normals for your UI geometry.
Cull: This Boolean gives you the ability to disable the child widgets rendering while the panel is being dragged, which improves performance.
Static: If all your panel's widgets are static and won't ever move, check this—it will improve performance!
Panel Tool: This is a panel managing tool. You can visualize and select each panel in the scene. You can open it with Alt + Shift + P or navigate to NGUI | Open | Panel Tool. Will this panel show in the Panel Tool parameter? This should be unchecked for dynamically created temporary panels through code, like a warning message or ammo pick-up notification.
Clipping: This will let us hide widgets outside a given rectangle. When turned on, you will be able to choose the clipping rectangle's dimensions with the
Sizeparameters. Anything outside this rectangle will be hidden.
None: No clipping—the entire panel will be displayed.
Hard Clip: Clipping enabled—rough clipping of widgets outside the box.
Soft Alpha: Clipping enabled—soft clipping with fade-out / fade-in borders.
We've now taken a look at the parameters of the UIPanel component, which will be used to hold our widgets.
During this chapter, we discussed NGUI's basic workflow—it works with GameObjects, uses atlases to combine multiple textures in one large texture, has an event system, can use shaders, and has a localization system.
After importing the NGUI plugin, we created our first 2D UI with the UI Wizard, reviewed its parameters, and created our own GUI 2D layer for our UI to reside on.
Finally, we analyzed the four GameObjects that were created automatically for us by NGUI. After reviewing their parameters, we can summarize their roles as follows:
The UI Root holds the UI and scales it for pixel perfect or fixed sizes
The Camera views the UI and sends messages to the widgets for interactions
The Anchor can attach elements to the borders of screen or objects and add offsets
The Panel holds our widgets and renders them, with or without clipping
We are now ready to create our first widget. It's time to move on to the next chapter.