This week I focused on the basic implementation of two UI panels; the History panel (which shows a list of historical events that have happened) and the Family panel, which shows a list of the characters that are related (by blood or marriage) to a particular character. I also spent some time getting the text to look sharper.
Smoothly Scrolling Lists
The main challenge was performance; I’m using ScrollRect objects in Unity and they are surprisingly slow. I’m not just talking about the need for object pooling (where you reduce the number of game objects used to render a list by re-using a small number of them to populate just the visible portion at any one time), but in the way ScrollRect inherently functions. To the best of my understanding a ScrollRect recalculates the layout of its contents and rebuilds each graphical element every time the scroll position is changed. The implication is that if you’re going to use a ScrollRect and want smooth scrolling, you need to make sure it’s contents are as lightweight as possible for Unity to rebuild. One of the components I am using liberally in the UI is the character card, a character portrait with some decoration, to give you at a glance; Faction affiliation, House affiliation, the character’s general importance (i.e. are they a leader, a ruler, etc.), the character’s happiness, your opinion of the character, and the character’s opinion of you.
In the History panel list, I can have up to four of these character cards per row. The control was using an “Auto Layout” based layout, and I got a significant speed up switching to a RectTransform based layout (i.e. where I calculate the position of each element manually once rather than let Unity dynamically recalculate it each rebuild).
The other tweak that seems to have helped considerably is an implementation detail of how I was doing object pooling on the list itself. It turns out that changing the parent of a UI element also triggers a significant amount of rebuilding, so it is cheaper to leave one or two masked out list elements past the edge of the visible area, rather than temporarily reparenting them to somewhere else until they are reused to show new items.
Sharper Text Rendering
I’m using TextMeshPro to render the text, primarily because I need the ability to embed links and sprites within the text (I’m under the impression that TextMeshPro is also generally the most robust text rendering solution available for Unity). A weakness of all the text renderers in Unity I’ve tried is that they struggle with drawing small text sharply. The text ends up looking quite fuzzy, rather than nicely anti-aliased but still sharp. The only solution that I can see (at least with TextMeshPro) is to find or roll your own bitmap fonts that are of the exact size you need and use them at the explicit size they were designed for (i.e. no scaling at all of either the canvas, game object, or text component font size). If you want text at different sizes you will need to use different bitmap fonts at each seperate size, but the results are then pixel perfect. And past a certain size, TextMeshPro’s ability to dynamically resize a font works just fine.