Of GUI and Tooltips
I’m starting a series of articles on the technical side of things, to show what’s the solution taken for common problems in game development, trying to improve them and share it with fellow developers.
Nantucket is made with Unity, it has been awesome so far, after more than a year in development we feel quite comfortable using both the engine and the editor. But there are situations where we preferred to implement the solution ourselves instead of using built-in libraries or getting asset store packages. The whole UI library is an example of this.
Possible UI Solutions
At time of starting the development of it (mid 2014) there was no uGUI
, so the only feasible built-in solution was the legacy OnGUI
. We scrapped it right away because was not flexible enough to handle overlapping interfaces and different resolutions.
We evaluated the idea to purchase nGUI
, but at that time was too expensive for us for what we needed.
We haven’t tested the new uGUI
yet, but at this point of development is too much work of refactoring to switch.
So we went for building our solution from the ground up, so we could implement a library that contains only what we needed and is easily extendable.
Collider Manager
Each in-game component that interacts with the player has a Collider2D
, in order to be detected by mouse movements.
The Collider Manager
provides a series of functions which give information about colliders, their position, and their Z order. It’s used mainly to understand which objects are pointed by the mouse pointer, both GUI components and game objects.
To handle Z order, the Collider Manager
has a list of Layers
ordered by priority. That’s all we need to handle overlapping user interfaces and detect whether the player is interacting with the map or with the interface.
In this picture, there are three Layers
ordered from high to low priority: UIClickable, UIBackground, MapCity
. Using the Collider Manager
, is possible to detect whether the mouse is pointing to the ship slot and show the tooltip, or decide to accept the click on a city and handle cases like: the city is covered by the interface background, if the user clicks where the city is, the Collider Manager
understands that the user is clicking on the interface and not on the city.
GUI
The first big choice we had is to implement the whole interface in world space coordinates. This let us design the UIs in the Unity scene together with the other scene objects, and it was great for us, because we had the possibility to see how the UI fit in the screen, and how it’s placed relative to the other objects, even in edit mode, reducing a lot the turnaround times.
But using world space coordinates has its drawbacks:
- Aspect ratio is fixed. In case the player uses one different from 16:9, there are black bars on the sides
- The interface is designed for FullHD resolutions. For different resolutions there could be a lot of aliasing in text and sprites due to texture filtering
Everything in the GUI is a GUI Component
, a simple script that provide functions to change the state (i.e. edit text, change color, change sprite) and it handles mouse events that happen on the component itself.
All the GUI state and behaviours are handled by the GUI Manager
, which has 2 main tasks:
- Dispatches mouse events like Mouse Over, Click, Drag & Drop to the GUI component
- Updates the info to show in each component, but only when needed to avoid performance issues
We use built-in TextMesh
components for UI texts, they are good enough for our purposes, but we didn’t find a good solution to avoid aliasing. We might consider using another solution for text in the future.
Tooltips
As you may have seen in some gameplay footage, we use tooltips a lot in Nantucket. We think is the best way to provide the player all the information he needs at the moment, without letting him confused and doing the best to help him to take the right decision.
Every object with a Collider2D
component in the scene can be a target for tooltips, all it needs is to have a TooltipComponent
attached. The TooltipComponent
provides a text to the Tooltip Manager
, which in order shows a tooltip with that text when the player moves the mouse over the object.
The text content in the tooltip varies a lot in terms of size, and the target object can be in any position in the screen. So we added a database of different versions of Tooltip Objects
, which varies in: text lines number, arrow direction, arrow position.
There is a central Tooltip Manager
which handles all the tooltip functionality, its main loop is:
- Pick an object pointed by the mouse with a Tooltip Component, using the
Collider Manager
- Wait a delay while the mouse always points to that object
- Select a
Tooltip Object
from the database depending on: Text lines, Component position, Tooltip preferred direction. The tooltip object will be placed just outside of the collider of the target object, so the object won’t be obscured by the tooltip - Show the tooltip
- Hide the tooltip when the mouse doesn’t point to that object anymore
The Tooltip Manager
makes sure that the tooltip object is always on screen so, for example, if the object is on the far right, the tooltip will go on the left even if the preferred direction is on the other side.
The tooltip object database handles until 6 lines of text for now, but we already have tooltip texts longer than that, so we added a special tooltip objects which is a big flat rectangle that encloses all the text. Before the game ships we may implement a solution to have modular tooltips, in order to handle all the text sizes.
—
That’s all, I’d like to hear voice in the comments, any feedback or question is welcome.
Daniele
Tags: code