Pixel-perfect fonts in Unreal Engine 4

April 02, 2021
Pixel-perfect fonts in Unreal Engine 4

Chances are if you're making a low-resolution game you also want a low-resolution font that looks good.

You have two options:

  1. Look for free pixel-art fonts that suit the aesthetic of your game
  2. Become a typographer

Luckily for you, the second option is much easier. This guide will not teach you how to design beautiful fonts, I'm far from being a savvy typographer myself, but it will help you putting a simple font in your UE4 game.

The problem with free fonts, however cool they may look, is that they are often not pixel perfect or have intrinsic parameters that will cause the characters to slightly deviate from your grid. Making your own font takes less time than you expect, and can also be used creatively, since you have control over which glyphs are associated with the text you're sending to the screen. For example, I use a font with pictorial representations of the gamepad buttons for tutorial and power-up explanations.

You can make your font in pixel art in any software you want. I use Aseprite, but you can use photoshop or even paint. You should make an image like this one. This image has been scaled up for you to see how I built the font, but you should make it with a 1-1 pixel ratio. I used the light red lines to keep a consistent baseline e left margin.

If you need a more in-depth guide on how to draw the image, you can follow this amazing tutorial by MortMort. I used a different approach, but the outcome is the same.

The font source image

When you have drawn all the characters you need, head over to Pixel Font Converter! Load your image in the center panel and turn your attention to the settings in the left panel. They are self-explanatory and you can hover on the inputs for a quick explanation. Hovering on the boxes in the center panel you will see how they're being cut and it will help you figure out the settings. When your settings are correct, the right panel should display the resulting font with a well-known pangram.

A quick note on spaces: if you take a look at my example, the space character is represented by a small line. This line will define how wide the space between words is (excluding inter-character spacing) but it won't be exported in the font.

Pixel Font Converter interface

Before you export the font, you must define how big the font actually is in typography terms. Click on the output tab in the left panel and get ready for some math. Here's what each setting does:

  • Em size

    The actual size in points of your font. This is the last value to set. I'll explain this later.

  • Line gap

    Leave this to 0 and keep things simple.

  • Ascent

    How tall your font is ABOVE the baseline

  • Descent

    How tall your font is BELOW the baseline. Use this to account for tailed letters.

  • Pixel size

    Leave this to 128. Makes your life easier, but you can change it once you know what you're doing.

Below these settings, you will see a wrong expression, but you should just care about the last two values. Those are the actual height of your font and the em size. We want them to be equal, so we follow a few steps:

  1. Set the ascent to the height of your characters multiplied by 128. Usually, this is the same value as the baseline in the previous tab, but you could input more or less, to leave some space between lines or to have your font bleed out from the top of the line.
  2. Set the descent to the pixels you want to be honoured below the baseline, multiplied by 128. Again, this will leave some space or it will force the font to bleed.
  3. Increase or decrease the em size until it matches the total height of your font (ascent + descent).
  4. Hovering on the characters in the center you can check if the ascent and descent line up with your pixel art. This is important. If they don't line up, making the font pixel perfect anywhere else will be almost impossible.
  5. One last step: the em size, divided by 128, should give you a multiple of four. This is not strictly required, but I highly recommend it for Unreal, until you figure out how the whole process works and you want to tweak things.

In the last tab of the left panel you'll be able to input some metadata for your font.

Click on the "Save TTF" button on the top right to export the font you can import into Unreal.

The font imported into Unreal Engine 4

In the image above you can see the example font compared to Nexatli's small font.

There's only one last step I need to talk about: how to size your font correctly in the widget editor.

When you add your font to a text block or rich text block it won't look right most of the time. Unreal engine is designed with classic fonts in mind, so 1px off is usually not a big deal, but for us it is. If you hover on the "size" setting of your text block it will give you a quick explanation of how UE4 handles fonts.

Basically, Pixel Font Converter builds a font at 72 dpi, while UE4 displays the UI widgets at 96 dpi. That's where that "multiple of four" requirement comes into place. With a simple proportion we can find the appropriate size for our font in UE4:

font size = line height * 72 / 96 / pixel size;

As I explained before, the ascent and descent together consitute the line height, so multiply your line height by 3/4 and you get your default font size, to be divided by 128. To keep the font pixel-perfect, the size should only be multiples of that values. Let's see the math breakdown with my example font:

fs = (asc + des) * 72 / 96 / ps
fs = (1152 + 384) * 3 / 4 / 128
fs = 1152 / 128
fs = 9

Another example: the small font in nexatli has ascent 6*128 and descent 2*128. (768 + 256) * 3 / 4 / 128 = 6. Since Nexatli displays one pixel every 6 pixels on screen, the font size is usually 36, but that's just the way I handle the rest of the UI. Unfortunately, UE4 doesn't handle fractional font sizes yet so that's why you'll be better off using line heights that are multiples of 4.

Now, compare the font to the UE4 grid in the widget viewport. Make sure you're viewing your widget at DPI scale 1. You can check this in the lower-right corner of the widget viewport. By default, choosing a screen size of 1920x1080 should give you the correct DPI.

If the text is slightly raised above the text box that's because, by default, UE4 sets a shadow for your text, even if it's invisible. The shadow works differently from what you may have used in CSS or Adobe programs, and it will displace your text. Set the shadow size to 0 to fix this (in every text block you make).

Below you can download the assets used to generate the font and the font itself, so you can see how it's made, import it in Unreal and try things out.

Download Assets