State of Thai in Unity

Unity3D is one of the most popular games engine used in Thailand. In fact, it’s not far fetch from being the most popular one. We do enjoy using Unity3D as it’s quite intuitive (although I’d say it’s not that easy for beginners).

However, Thai remains one of the obstacle in making good games for Thai people. I mean, the language. Displaying Thai in Game Engine is one of the problem we are facing so far. The TLDR; version is, Unity3D is not able to display perfect Thai strings in game (on both UnityUI and TextMeshPro), due to the fact of missing essential text layout feature required for displaying Thai.

Why it is so difficult. Well, Thai writing is 4-level of characters.

  1. The base character. Base character stay on the baseline. Keep in mind that some character has part of it extends down below the baseline — ญ ฎ ฐ. Some other character has parts of it extends above the height of most character in the set – ป ฟ.
  2. The above base character level. In this level, it can be either above character vowel -ี -ิ, or tone mark -้ -่.
  3. The topmost level, which is tone mark on top of the above character vowel. In this case they can be -ี่ -ี้
  4. The under-baseline vowel like -ู.

Some combination like ปี่ or ญู can looks messed up when the renderer does not support feature like mark-to-mark and mark-to-base placement. Unfortunately our beloved Unity3D does not support this.

I won’t go for details for now, may be later.

Also there are some issue with Editor itself as well. I’ll explain that one later. Let’s move on to the game engine first.

In-Game

As I mentioned before, Unity3D only support a basic text shaping which is not adequate for display Thai properly. Here’s the proof.

I’m pretty sure at this point, some of you who’s not very familiar with the language might ask ‘what’s the problem here?’ Basically the tone mark in Unity just overlaps with the vowel under it. And in some case, the vowel also overlaps with the base character as well. The word ปี่ (flute) cannot be rendered in Unity3D correctly.

This is the same font and same string in other program that support advanced OpenType feature. Notice the extra tick on top of the second base character of the second and the third phrase. Also the above vowel on the third phrase are moved slightly to the left so it does not overlaps with the base character.

The font used in above example is Sarabun, from Cadsondemak.

So, back in the day when there’s no OpenType, we Thai people also has this kind of problem on most application we are using. Luckily, since the font foundries are aware of this problem, they designed the font so that it avoid or minimize the problem when the glyphs overlaps with each other.

Below is Loma from TLWG, rendered with Unity3D. Loma was created a decade back, by the team Thai Linux Working Group who brought Thai support to Linux (a big thanks to them).

Notice that the tone mark is visible even if there’s above-base character vowel there, because the tone mark’s default position is higher than the most present days fonts. The third phrase still have the vowel overlaps the base character, as the character has its long tail extended higher in the air. The default vowel position is slightly to the left to give the visual indication that this is -ี not -ิ, which is an different vowel (they are not exchangeable).

However, these technique might be good enough for displaying on screen, it’s not when it come to publishing works. Some of the software vendor has develop a technique to swap out glyph to a proper version when certain condition is met. Eg, when the input string is ป่ then swap the tone mark with the version that positioned lower than user. This technique is commonly referred as glyph substitution. It’s still in-use now a day, but as a compliment to mark-to-mark and mark-to-base positioning provided by OpenType.

Anyway, people at SaladLab has implement glyph substitution library called ThaiFontAdjuster to use with Unity 3D. There’s catch with using this library, you need to use specific fonts as the substitution map is hard-coded in the library. They do provide a special built of ‘NotoSans Thai’ that support the library. I think Loma above also support this library as well (I haven’t tried though.).

However, these are just workaround. Until Unity3D supports glyph positioning (mark and mkmk in particular), I’d say we still have to struggle with Thai text in the engine.

Editor.

The first problem you will encountered is, the input field does not display Thai text properly (again). I think it comes from the font that they are using in the UI. It’s probably due to the fact that I’m using Windows 10, as some UI fonts shipped with Windows 10 are different than one shipped with earlier versions of Windows.

Also if you copy the string from text field, and then paste it, you notice that the pasted content is different than what it was copied into.

Probably this worth a bug report ?

Appendix

Here’s the font I uses in above example.

Feature Image taken from Araya by MAD Virtual Reality Studio. I’m not associated nor affiliated with the company nor the title in anyway.

State of Thai in Unreal Engine 4

In this post, I’d like to talk a bit about displaying Thai text in Unreal Engine 4. I’ve been playing with this engine for months now. What I’ve seen so far is the engine does support Thai, but with a little bit of catch. I’ll talk about them a little bit later in this post.

Some might ask, what is so special about Thai? Well I’ve seen more and more awareness in getting games localized for Thai. AAA titles like Sekiro, Dying Light, or Jump Force ships with Thai localization. Many more are rumored to have one. Anyway Thai is also one of the difficult language to display due to its 4-level of glyph positions.

To give you some head ups, at a given horizontal position, there are 4 possible positions. These names are my madeups, which might different than other documents. Please keep this in mind.

  • Base character, which always stay on the base line. Part of the character might be under the base line.
  • Above base character, this can be either floating vowel character, or tone mark.
  • Above floating vowel character. In this position it can be only tone mark.
  • Below base character vowel.

For example ‘คนที่ไม่มีความกตัญญูกตเวที’

I won’t go further than these details. May be later I’ll write some article about that.

Because of these position, most game engine which only support TrueType layout (advance + bearing) won’t be able to render Thai string currently, let alone those only support fixed-width font.

Unreal Engine 4, in the other hands, support OpenType shaping. Things like mkmk, mark, etc. are directly supported, thanks to Harfbuzz, an open source OpenType shaping engine.

In-Game

As I mentioned before, support for Thai is pretty good out of the box. Just add a Thai font, create a TextBox with that font, and done, it’s ready.

But here’s the catch. Not all fonts are created equally.

The one on top is Sarabun, while the one on the bottom is NotoSans Thai. Notice that the above-vowel tone mark is not placed correctly. I don’t know why either. Since NotoSans Thai work fine on many software (including Android OS) my guess is UE4 has some problems with this font specifically.

Actually Sarabun is not perfect either, here’s why:

Sarabun has it’s ascender and descender too small to cover the lower vowel and above-vowel tonemark. If you have multi-line string, it’s possible that these characters will clash with each others, resulting in some nasty looking. This is something with the font. I’ve already contacted Cadsondemak on this matter, but they have yet to reply. May be I should visit Emquartier sometime, as their office is there :).

The one that looks better than those 2 above is Loma from TLWG.

The takeaway here is, you have to do some experiment to find which works and which does not.

Editor

Since the engine’s editor run on the engine itself, the editor is also capable to display Thai text as well as the game does. However, the game engine is not shipped with fonts that has Thai glyphs, every Thai character displays as ‘Tofu’s.

They are not ordinary Tofu, but still Tofu nonetheless. Anyway as I mentioned earlier, the editor itself runs on top of the engine, so if the engine can displays Thai, then what only missing is Thai fonts. Adding Thai fonts is not a difficult tasks to do, but it requires a little bit of coding. You have to then rebuild the engine from source. I hope that we could have Thai fonts shipped with the engine, but that’s up to the team at Epic to decide.

And here is the proof that it’s capable of doing that, after some modifications.

Anyway, in order to add font, firstly you have to get source code and build it. Please refer to this article for how to do that.

Secondly, after have all the code and build the engine, we needs some Thai fonts. I’m using Sarabun from Cadsondemak in this example, as the font looks amazing and render almost correctly most of the time by UE.

The path is /Engine/Editor/Slate/Fonts.

Finally, add some code to TSharedRef<const FCompositeFont> FLegacySlateFontInfoCache::GetDefaultFont() function to let the engine cache the fonts we’ve added.

// Thai (editor-only)
if (GIsEditor)
{
    FCompositeSubFont& SubFont = MutableDefaultFont->SubTypefaces[MutableDefaultFont->SubTypefaces.AddDefaulted()];
    APPEND_RANGE(SubFont, Thai);
    APPEND_EDITOR_FONT(SubFont.Typeface, "Regular", "Sarabun-Regular.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "Italic", "Sarabun-Italic.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "Bold", "Sarabun-Bold.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "BoldItalic", "Sarabun-BoldItalic.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "BoldCondensed", "Sarabun-Bold.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "BoldCondensedItalic", "Sarabun-BoldItalic.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "Black", "Sarabun-ExtraBold.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "BlackItalic", "Sarabun-ExtraBoldItalic.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "Light", "Sarabun-Light.ttf", EFontHinting::Default);
    APPEND_EDITOR_FONT(SubFont.Typeface, "VeryLight", "Sarabun-ExtraLight.ttf", EFontHinting::Default);
}

Feel free to change the font files to the one you’re using, if you’re not using Sarabun as I am.

Anyway I’ve came across some fonts that works fine in-game but not in editor, Loma is one of them. It just display ‘Tofu’ like this font does not exist. I don’t know why. If you happen to come across any font that works fine in both in-game and editor, please feel free to leave some comments.

Appendix

Here’s the font I uses in above example.

Feature Image taken from Home Sweet Home by YGGDRAZIL GROUP. I’m not associated nor affiliated with the company nor the title in anyway.

Starbucks Thailand 24 Hr. – Montien

So, the branch that I’m going to tell you is actually the one that I pass by quite often. However, I’ve just noticed not long ago that it opens 24 hours.

Starbucks – Montien

And… the branch that I’m talking about today is the Montien branch. This branch locates at the Montien Mall, in front of Montien Hotel Bangkok. This hotel is on the Surawongse road, NOT the Rama 3 road Montien Riverside Hotel. Please make sure you don’t go to the wrong place!!

Travelling

Montien Hotel locates on the Surawongse Road. You can get there either from Surawongse road or Rama 4 road.

If you’re using public transport, Saladang BTS station is pretty near. From there you can walk through the soi Pat Pong to the Surawongse road. Also the MRT Sam Yarn is not too far. From there, you can walk on the Rama 4 road.

If you’re driving, you could get to the hotel from either Surawongse rd. or Rama 4 rd. as mentioned. This hotel has a pretty large parking building, so finding parking lot is not really hard. However, the parking building is quite dark in my opinion. Also the way inside and the parking lot are both quite narrow.

Driving larger car like Honda Stream proves to be quite a challenge.

Parking fee here is 50 baht per hour. However, you can ask for a stamp at any store in the hotel including this Starbucks coffee. This stamp worth 3 hours of parking.

In the store

This store is approximately 70-80 square meters. Most table are high ones, so you can happily work in the store. There’s a large bar table with 12 seats, more than 10 of high table that you can work at, and the shorter tables that you might want to sit at when discussing something.

Because this store is close to the tourism (Soi Pat Pong), office space (Saladang), and education institution (Sam Yarn), there are tourists, office workers, and students at the store almost all the time.

This store is moderately large with a lot of table, but there are a lot of customers almost all the time. It might be difficult to get a table/seat. Also if you drive here and decided to leave without buying, you have to pay for enter fee for 50 baht.

The temperature at this store can be freezing. It’s a good idea to bring your jacket.

Facility around the store

This area, as you might already know, is quite lively. There’s even a pub at the opposite side of the store, if I’m not mistaken.

In the mall, there are a Japanese Restaurant, another cafe’ which opens to late hour (haven’t tried this one), and Burger King which also opens 24 hrs. You won’t be starving as long as your pocket don’t let you be.

Also it’s not really difficult to find a convenient store or two around. Just make sure you remember the way to get back.

One problem is about toilet. This toilet belongs to the mall, and it closed at 24.00 along with the mall as well. So if you need to use one after that hour, good luck finding one. Also this toilet will cost you 5 baht per use. Make sure to prepare some coin before hand, as using large bill can upset the keeper!