Pixel-Perfect Dynamic Text for Unity®
(click to go to Asset Store)

Have you ever been frustrated in Unity when working with text?
(e.g. with GUIText or TextMesh, or with some other product)

If your answer is YES, please read on.


TL;DRPixel-Perfect Dynamic Text for Unity®! A component for displaying pixel-perfect camera-facing text.
Size & position are defined in world units. Sharp like built-in GUIText, but part of the scene like TextMesh.

This asset has its own niche:
  • it is meant for displaying pixel-perfect text (crisp anti-aliasing),
  • camera-facing text (even when camera has free orientation in 3D),
  • with size & position defined in world units (not in some custom UI scale or so).
When comparing Pixel-Perfect Dynamic Text (PPDT) to Unity's built-in text components:
  • "PPDT" is sharp with crisp anti-aliasing like the really old legacy built-in GUIText. (GUIText is from early days of Unity, many of you probably don’t even know what that is or was, but the text it rendered was nice and crisp).
  • "PPDT" text is part of the 3D scene, in similar way as classic Text Mesh (which is also known as “3D Text”). But “PPDT” looks better than Text Mesh.
  • No Canvas or Canvas Renderer is needed. "PPDT" is not part of the Unity’s UI system. The text is rendered by the regular Mesh Renderer component instead.

Unity Forum Thread


Hint: Test changing window size and shape to see how text adjusts.

Click to launch interactive demo
(opens a new window)


Note: Your browser needs to support WebGL to run the interactive demo.
Alternatively you can try the legacy demo for Unity WebPlayer.

You can also view presentation of the demo in YouTube:

"Lorem Ipsum"-demo version

Download the demo version as .unitypackage-file:
For Unity 4.x (at least Unity 4.2.2)
For Unity 5.x and all newer versions
Some warnings are shown with Unity 2018/2019/2020, as this Lorem Ipsum demo version is not fully up-to-date with the sold package.

You can freely download the "Lorem Ipsum"-demo version for the purpose
of evaluating of Pixel-Perfect Dynamic Text component before purchasing.
In the demo version your own text is not shown, but instead replaced
with characters from the well known lorem ipsum text.

What is this a solution for?

Some common issues when you work with text in game engines.

Example 1:

What can happen if you design for small screen (lo-res phone) first and then move over to larger screen (hi-res/hi-dpi desktop or tablet).

Starting point:
For example,
handcrafted layout
for LO-RES phone.
If you worked with absolute pixel sizes...
The same pixels represent only a tiny portion
of the larger screen and text is illegible.
Or if you scaled up sizes and positions, but
your font/images are too small bitmaps...

Up-scaled image looks fuzzy and out of focus.
What you want..
Resolution independent sizes and positions with
text in the correct size in any resolution.

Example 2:

What can happen if you design for large screens (hi-res/hi-dpi desktop or tablet) first and then move over to small screen (hi-dpi/lo-dpi phone).

Starting point:
For example, handcrafted layout
for HI-RES tablet or desktop.
If you worked with absolute sizes...
What you want..
Resolution independent sizes and positions with
text in the correct size in any resolution.
On HI-RES/HI-DPI phone
content might almost fit:
     On LO-RES phone you'd
get a tiny cropped area:

What features does Pixel-Perfect Dynamic Text have?

Most of the listed features are demonstrated in the Interactive Demo (Unity Webplayer).

Text size is proportional to world units, and not dependent on screen size in pixels or dpi resolution.

  • For example, if you use an orthogonal camera in Unity with Size=5, it means the total height of window is 10 units. Pixel-Perfect Dynamic Text with unit size of 2.0 will mean one row takes vertically 20% of screen so that there will be space for 5 rows of text.

For maximum sharpness, pixel size for text font rendering is dynamically selected to be the nearest matching size for text world unit size.

  • For example, suppose your window height is 512 pixels and you have a camera like in the previous example. If you make a text with size 1.0, the row height will be 1 unit, corresponding to 51.2 pixels. The font will be rendered sharp with pixel size of 51.

Pixel-Perfect Dynamic Text component also works with both orthogonal and perspective cameras.

  • For perspective cameras, it measures distance from text object to the camera plane. With the power of trigonometry it figures out what is the correct pixel size for the text (with its current position and size, measured in world units).
  • This is done separately for each different piece of text with varying distances.
  • Text can also be set to auto-orient itself towards the camera (like a billboard).

You can choose if text is pixel snapped to keep it sharp when it moves on screen.

  • With pixel snapping enabled, sub-pixel position of transform.position will be snapped to nearest pixel (of currently used screen resolution).

The Pixel-Perfect Dynamic Text component uses Unity's internal font renderer and atlasing.

  • So you can use same fonts what you can use with the built-in Text Mesh or GUI Text — use custom truetype fonts.
  • Regular Font Styles are supported: normal, bold, italic, bold and italic.
  • Change color dynamically.
  • Standard built-in font material & shader is used. No need for custom heavy-weight shaders.
  • Note: There's no support for Rich Text with html-like syntax (for now, at least).

Text can be aligned and anchored, similar to how Unity's built-in Text Mesh (3D Text) works.

  • Text can be left-, center- or right-aligned.
  • Horizontally text can be left-, center- or right-anchored.
  • Vertically text can be upper-, middle-, lower- or baseline-anchored. Pixel-Perfect Dynamic Text defaults to baseline anchoring for easier working with text (baseline anchor is not featured by built-in Text Mesh).

You can ask for font metrics and use tabs for alignment.

  • The component has baseline, ascent and descent properties.
  • You can also get size of the whole text (bounds of the generated mesh).
  • Tab size is defined in world units and tab char in text moves to the next tab stop.

The code contains many small tweaks to make it better.

  • Mesh is regenerated/reallocated only when necessary. E.g. when there's longer text than previous frame, or if text properties change (size, style, anchor, alignment, ...). Previous mesh arrays are reused when possible.
  • Pixel-Perfect Dynamic Text is compatible with dynamic batching. It can even combine with built-in text meshes as same font material and texture can be used with both.
  • Aware of different texel sampling between graphics APIs, and adjusts as needed to keep your text sharp.
  • Automatically converts & replaces existing Text Mesh objects if you add a new Pixel-Perfect Dynamic Text component to them.
  • You can update text dynamically, even every frame. See the last screen (10/10) of interactive demo. It has a "text mode" effect consisting of over 2000 characters updated every frame.
    • NOTE: When updating text with dynamic content, you should change it using the textSB string builder field instead of the text string. And after you have finished constructing the new string, call FinishedTextSB().
      C# example:
      int playerScore; // assume you have an int like this
      DynamicText dt = GetComponent<DynamicText>();
      dt.textSB.Length = 0; // clear previous text content
      dt.textSB.Append("Score: ");
      dt.FinishedTextSB(); // signals that your new text is ready!

No native code & small footprint.

  • Works with Desktop, Mobile and Webplayer platforms.
    (probably with consoles as well, but we haven't tried)
  • Supplied as only a small DLL with the component and with bit of C# source for editor extension.
  • No native code — works with the Free version of Unity!

Pixel-Perfect Dynamic Text works also with the new Unity 2D.

  • The default font material & shader seems to render using the Default Sorting Layer with Order 0. So, to make sprites render behind text, you can make a new Sorting Layer and drag it to be before Default. Or you can use Default Layer for your sprite but set the Order in Layer to negative value. And, of course, in similar way to force sprites render front of text.


What is it not good for?

As usual, there are some trade-offs and caveats, and this is not an exception.

Exact font metrics and glyph sizes vary a little bit when the font's actual pixel size is adjusted to the best match.

  • So, if text size varies slowly and smoothly over time, the text "pops" a bit.
  • This problem can be alleviated a little bit by using a custom font imported using Smooth Rending Mode (not Hinted Smooth).
  • However, changing text size all the time leads to constant updating or re-generation of font atlas, so in any case this kind of use is not optimal for this component.

This is not a good choice when combined with a camera moving and rotating freely in 3D.

  • For example, if your camera can get very close to text, it can dynamically resize to be very large on screen. This can lead to constant update of the font texture, which causes a drop in frame rate.
  • 3D-rotating text semi-far from camera can still trigger constant font atlas update, since the actual size on screen may change all the time. This is basically the same limitation than with camera-facing text changing size all the time, as mentioned above.

This is not a solution for all your UI needs.

  • Pixel-Perfect Dynamic Text is just a component to show only text in your scene, nothing more.
  • There's no support for rich text with html-like syntax (for now).

No support for special effects like gradients, drop shadows or outline. (For now.)

  • But you can do basic versions of some effects yourself, by using some old tricks. For example, to make a simple drop shadow: Duplicate your text, setting color to black. Offset Y down a little bit and Z behind the original text.
  • Some support for special effects may be added in a future version.

Questions and Answers

If you're still wondering about something... or if you bought the Pixel-Perfect Dynamic Text and have an issue! (oh no)

But there's GUI Text, and it's not blurry or jaggy like in the examples. Why isn't it enough?
Yes the GUIText is there. But it forces you to work in screen space using pixels. Same text can look way too small or big if you move it to a screen with different resolution or dpi than what you used initially. Check out again the two "What is the problem?"-examples on this page. By the way, Pixel-Perfect Dynamic Text looks just as sharp as the classic legacy GUI Text looks.

Why does my text look garbled?
Verify that the Mesh Renderer has material correctly set up. Normally it should be correct automatically, but sometimes one can set it wrong by mistake. (Expand the font in Assets view and drag Font Material to Element 0 in list of Materials of the Mesh Renderer.)

I can't see text, what's wrong?
1. Check that you have a font specified (i.e. DynamicText component's Font field doesn't display "None"). Drag a font there, or click the small dotted circle and select Arial from the list.
2. Try right-clicking DynamicText component in Inspector and choose "Regenerate Mesh".
3. Make sure the material is correctly set up (see previous question's answer above).
4. As always, make sure rendering of some other mesh doesn't obscure your text.

Why is the text sometimes blurry in the editor Scene view?
Text in the scene view shows with the size it is currently needed to be displayed sharply in the camera (game) view, which is the point of Pixel-Perfect Dynamic Text. So, the text is blurry if it is small on the final view (either with small specified size when using orthogonal camera, or it is far when using a perspective camera). Also, check if your text is not visible in the camera view and instead of that it's behind the camera. In this case the text is also clamped to minimum font size in pixels ("Min Font Px Size").

Why is this particular text blurry or jaggy in the game view?
Make sure your text has a reference to the currently active camera. Or, if you have multiple cameras and text is on a custom layer rendered by one of the cameras, make sure the text refers to the correct camera which renders that layer. Text size on the game view is determined with the camera it refers to.

I have some of my own custom UI movement/alignment code. Pixel snapping "fights" with it, moving each frame. How can I fix this?
Move the DynamicText down in scene hierarchy so that it's a child of the object having your code (which has custom movement).

Is there garbage collector (GC) problems?
No, in the extent what can be reasonably expected. Pixel-Perfect Dynamic Text allocates memory only when it needs to enlarge mesh arrays (e.g. if you switch to display a longer text than what you had previously). Also, if you want to update to dynamically built text from script code, you should change the text content using the supplied textSB field (String Builder) and call FinishedTextSB() when you're done. This way there's no leaks of strings of the previous content.

What if I have performance problems?
First, try these steps:

  • Lower your "Max Font Px Size" and maybe don't use that big text in your design. Big letters take lot of texture space and there's a limit how much you can have. It seems on some mobile platforms the max atlas may be limited to smaller than you can get on a desktop machine.
  • Use less characters for the "Metrics Ref Chars". These characters (and the baseline ref char) are always requested to be in the font atlas texture, so if you are using a large text size, Unity has to try to fit all of these letters in that large size to the atlas. So, if for some text you only use numbers, put only "0123456789" here. Or, with normal text, it may be enough to have only 1-2 lowercase low-hanging characters like 'j' or 'g' and 1-2 full-height capital characters like O or X.
If that doesn't help, please read the following about other possible situations:
As mentioned and shown in the interactive demo, it is not a good idea to have a screen with a camera rotating in 3D (see screen 8/10). Also it's not a good idea to constantly adjust size of a text in 2D either (see screen 5/10). That is, if the final text size on screen changes constantly due to 3D rotation or changing distance to camera. This will force Unity to flush and re-create the font atlas often. You can try to alleviate the problem by lowering the Max Font Px Size of DynamicText objects. However, in this case the text will appear blurry if it gets close to camera. This is one of the cases where you still might want to use the standard Text Mesh instead. If you need text in varying 3D angles which is also sharp when close to camera, then you should consider using one of the font packages which use distance field based font rendering. Note that those typically don't support dynamic fonts but use bitmapped pre-processed fonts instead, and they will require use of a custom heavy-weight shader, so what they're good at comes with their own set of limitations. If you know you need such a thing, here's links to some assets you might want to check out: Text Mesh Pro, Text Box. (note: we haven't tried these, so we don't know how good they are in practice)

How to fix this error message: No camera - can't generate mesh?
The DynamicText component needs to have a reference to the camera where it is meant to be visible in. It will automatically grab the Camera.main (first camera with the "MainCamera" tag) if there is one.

Does Pixel-Perfect Dynamic Text work with third party GUI packages like NGUI or Daikon Forge?
It isn't officially supported or tested on any such package, so you can assume that the answer is no. Many GUI solutions have their own renderer system and canvas/camera logic, which cannot be combined with world space scene nodes like a Pixel-Perfect Dynamic Text object. However, of course in some cases it can still be possible with some extra work and scripting, but that's up to you. (See also the next question.)

Does Pixel-Perfect Dynamic Text work with the new uGUI introduced in Unity 4.6?
No, with some exceptions. It is possible to have Pixel-Perfect Dynamic Text in a scene which uses uGUI. But if you want a Pixel-Perfect Dynamic Text object to be part of the GUI, then it will reasonably work only if you use World Space render mode in the Canvas. Additionally you may have to use only a single camera (no separate UI camera with dynamic rotation or so). In addition you have to add a script to tweak sorting order of Pixel-Perfect Dynamic Text objects - for example in C# something like this:
  GetComponent<DynamicText>().renderer.sortingOrder = 1;
This will allow you to use Pixel-Perfect Dynamic Text as a label or in buttons with uGUI. However, you still can't use it to represent text with uGUI Input Fields. (See also previous question.)

I like the interactive demo, does it come with the asset package?
Yes, it's an example scene which comes with the asset. While source code of the DynamicText component itself is omitted (it's inside a DLL file), source code of the interactive demo is included.

Can I try it before buying?
Check out the "Lorem Ipsum"-demo version.

This is just like basic text should work!
That's not a question... but, thanks! That was the goal.

Version History

// 2019-11-16, 1.2.4 - For Unity 2019.3+: Support for Enter Play Mode without
Domain/Scene Reload. Removed GUILayer components to fix a warning.

// 2019-04-16, 1.2.3 - Minor changes to fix Unity 2018.3 & Unity 2019.1 compatibility.

// 2018-04-22, 1.2.2 - Minor fix for latest Unity 2017 & 2018 deprecation warnings.

// 2017-05-06, 1.2.1 - Fixed issues related to text reverting when enabling&disabling.
Tested Unity 2017 compatibility.

// 2017-04-06, 1.2.0 - Fix for combination of DirectX9 and Unity versions 5.5 or newer.

// 2015-08-11, 1.1.0 - Support for Unity 5 added.

// 2015-02-17, 1.0.6 - Modified initialization to prevent doing it many times.
Fixed a mesh memory leak. Fixed error case when Camera rect size is zero (can
occur momentarily when starting Unity with autoloaded scene). Don't snap if
transform lossyScale (XY) is zero. Added autoFaceCam checkbox which keeps
text auto-oriented text towards given camera (like a billboard). Preliminary
support for Unity 5 (compatibility for auto-upgrading dll).

// 2014-09-23, 1.0.5 - Fix: In some cases SetText didn't work properly
when called from Start(). Added automatic fallback to smaller font pixel
sizes in case of font atlas rebuild loop (due to low memory or using too
large text). Can suppress debug logging by setting dt.suppressDebugLogs=true
from script code.

// 2014-08-05, 1.0.4 - Added new feature: Letter Spacing (relative to
selected text size). Fix: GetText returned empty string for game objects
which were disabled when loading the scene (and had a DT component). This
resulted in custom inspector clearing text in editor when viewing such objects.

// 2014-07-04, 1.0.3 - Overall better performance and robustness. Fixed
problem when internal sampling setting might be out of sync until toggling
"Use Direct3D 11" in Player Settings. Metrics are now updated when
switching font (fixes incorrect change in position). New "Auto Set Font
Material" checkbox to control overwriting renderer.sharedMaterial. Added
example of how to dynamically create DT prefabs aligned after each other.
Default font is now automatically set when creating a new dynamic text
object from code and leaving font as null (worked previously only in
editor like this). Added custom inspector which indicates more clearly if
camera or font reference is missing. Fix for changing text from script
code in Start(). Removed need for deferred mesh generation (must have
proper camera & font). Direct text string access replaced with SetText
and GetText methods. Fixes for Windows Store and Windows Phone 8 support.

// 2014-03-09, 1.0.2 - Added support for using a StringBuilder (textSB field).
// 2014-03-04, 1.0.1 - Fixed an unnecessary allocation when reusing mesh arrays.
// 2014-02-16, 1.0.0 - Initial version.


TL;DR — Get pixel-perfect fonts for Unity® with Pixel-Perfect Dynamic Text.
It is a component for displaying pixel-perfect camera-facing text.
Size & position are defined in world units. Sharp like built-in GUIText, but part of the scene like TextMesh.

Did you like how Pixel-Perfect Dynamic Text is built? — Also from Strobotnik for Unity®:
Klattersynth TTS (NEW!)
Google Universal Analytics for Unity®
Internet Reachability Verifier

Strobotnik is a member of the Unity Affiliate Program.