TextMeshProの使い方

# TextMeshProの使い方

![textmeshpro.PNG](https://qiita-image-store.s3.amazonaws.com/0/83393/bce4a4f8-6a31-e6d8-c5fe-6c693ec9f561.png)

### 追記
Unity6では完全にアセットとしてプロジェクトに取り込まれている状態になります
そのため、Package Managerなどでの導入対応も不要となりました
直接ヒエラルキーから右クリック`UI/Text - TextMeshPro`と選択すると初回時のみ設定の読み込みの`TMP Importer`が表示されますので、`Import TMP Essentials`を選択してください。設定ファイルがインポートされます。

また、サンプルも含まれているので適時削除などをしてください

---
AssetStoreで無料で手に入るようになった、TextをよりリッチにText演出が扱えるAssetです
Unity2017に導入されることも決まっており、現在そこまで日本語のドキュメントもあまりないのでまとめておきます
こちらはAssetStoreからダウンロードできるTextMeshProについてです
[TextMesh Pro Joins Unity](https://blogs.unity3d.com/jp/2017/03/20/textmesh-pro-joins-unity/)

現在、AssetStoreで無料で手に入ります。
AssetStore：[TextMeshPro](https://www.assetstore.unity3d.com/jp/#!/content/84126)
公式サイト：[DigitalNativeStudios.com](http://digitalnativestudios.com/)
サンプルなどもついているためわかりやすく、すぐに使える便利なアセットです
Importしたアセット内に`User Guide/TextMesh Pro User Guide 2016`というpdfのマニュアルもあります（英語） 
Unity5.6.1p1で動作確認

## 概要

### TextMeshProとは？

UGUIのTEXTにはない多くの機能がついたテキスト表現Assetです

- UGUIのTEXTと違って文字が滲まない
- Boldやitalic、Underlineなど基本機能
- 文字揃え機能（上下左右中央揃え、両端揃え）
- カーニング機能（文字間隔調整機能）
- フォントデータ(ttf,otf)からビットマップフォント作成機能（Font Asset Creator）
- UGUIだけでなくMeshRendererで表示でき、SurfaceShaderで光源に反射することも可能
- 文字にTextureを割り当てることもできる
- RichTextが使え、StyleTagなども
- 指数などの一部、数学的な表現ができる
- マルチスプライトの画像を文字列の中に埋め込みができる
- [TexturePacker](https://www.codeandweb.com/texturepacker)で作成したアトラステクスチャ（スプライトシート）と連携でき、上記の文字列に埋め込める画像アセットを作成できる(Jsonファイルのみ）

## 事前準備 TextMeshPro用のフォントアセットを作成する

### AssetStoreからTextMeshProをインポートする
UnityEditorのAssetStore画面から、TextMeshProを検索してインポートする
上記のリンクからダウンロードしてインポートしても大丈夫です
<b>フォルダ名の"TextMesh Pro"はAssetの内部でPathとして使用されているので変更しないように注意</b>

### 日本語フォントデータの準備
UnityのProjectにImportした段階では、TextMeshProは日本語には対応していません
デフォルトの設定で日本語を入力すると豆腐が出てきてしまいます
そしてTextMeshProでは通常のフォントデータ（ttf,otf）は対応しておらず専用のアセットが必要となるため

まずは日本語のフォントアセットを作成しよう

### 日本語フォントをFont Asset CreatorでTextMeshPro用のフォントアセットとして作成する

まずは日本語のフォントデータをProjectにImportしよう
フリーのフォントでもなんでもよいので、日本語の入ったフォントデータを用意してProjectにImportしておこう
このときフォントデータはもう使用しないのであれば、Resourcesフォルダ以外においておき、ほかで使用していなければけばビルドには含まれなくなるので無駄なリソースにならなくて済む

#### FontAssetCreatorウィンドウを開く
UnityEditorのメニューからFontAssetCreatorのウィンドウを開きます
`Window > TextMeshPro > Font Asset Creator`

![FontAssetCreator.PNG](https://qiita-image-store.s3.amazonaws.com/0/83393/2ef97966-7afd-a6c0-b155-0db470134dd3.png)

SDFフォントアセットを作成する際に必要となる設定項目です

|項目|説明|備考|
|:---------------:|:-----------------:|:-----------------:|
|Font Source      |元となるフォントデータ|ttf形式かotf形式のファイルが必要|
|Font Size        |アトラスに入る１文字のサイズ|数値が大きくなるにつれて文字はきれいになる|
|Font Padding     |アトラスに入る文字と文字との隙間のサイズ|基本的に５で。小さいとアウトラインなどができなくなる|
|Packing Method   |パッキング方法|Fast|
|Atlas Resolution |生成されるアトラスの解像度|使用する文字数や品質の高い文字にする場合は大きくする必要がある|
|Character Set    |アトラスに入る文字を指定する|プリセットの中から選択するか、文字を指定することができる|
|Font Style       |太字やイタリック体などを設定する|ビットマップフォントを使用するときのみ設定する。通常はNormalでよい|
|Font Render Mode |文字のレンダリングする方法|基本はDistance Field 16|
|Get Kering Pairs?|カーニング情報をフォントデータからコピーするか|フォントデータにそもそも含まれていない場合があり、falseでよい

以下、詳しい説明です

##### Atlas Resolution
ASCII文字の場合は512×512サイズで収まりますが、
１文字のサイズや入れる文字の量が多いと、特に日本語（ひらがな、カタカナ、常用漢字）などを含めると512×512のサイズでは入りきれません

###### 検証
以下の条件でぎりぎりに入るフォントサイズを求めてみた。フォントデータによっても変わる可能性があるので、あくまで参考程度です

Character Setは、常用漢字＋ひらがな＋カタカナ＋半角・全角数字＋大文字・小文字アルファベット＋空白文字などの記号群（、。！？ー…「」『』×(　) +-%.'･/:;）
Render ModeはDistance Field 16で行った

|解像度|フォントサイズ|
|:---:|:---:|
|4096×4096|81|
|2048×2048|34|
|1024×1024|10|

- 結果  
4096と2048ではEditor上フォントサイズ72での比較ではほとんど差はないように見えた。ただ1024まで下げるとかなり荒くなってしまった
モバイル向けであれば2048でも十分すぎると思う。

##### Character Set
テキストアセットに必要な文字を指定します

設定の項目にはいくつかのプリセットがあり、日本語を使わない文字などの場合はこれらを指定することでサイズを節約することができます
日本語などを使用する場合はCustom RangeやCustom Charactersなどで指定します
常用漢字・ひらがな・カタカナ・数字・アルファベット・記号などをすべて指定する必要があります

|項目|説明|
|:-:|:-:|
|ASCII|ASCII文字のみ|
|Extended ASCII|拡張ASCII文字|
|ASCII Lowercase|ASCII 小文字だけ|
|ASCII Uppercase|ASCII 大文字だけ|
|Numbers + Symbols|数値＋四則演算子やカッコ等の記号のみ|
|Custom Range|指定する文字の文字コードを10進数で指定(複数の場合は[,]コンマ区切り)|
|Unicode Range(Hex)|文字コードを16進数で指定|
|Custom Characters|実際に使用する文字自体を直接指定する。この項目を選択するとTextAreaが表示される|
|Characters from File|実際に使用する文字が入ったファイルで指定する(UTF-8形式のtextAsset)|

##### Font Render Mode
特に指定がなければDistance Field 16で出力するとよい
確認用にするならHinted Smoothがすぐに作成できる

|項目|説明|
|:---:|:---:|
|Hinted Smooth|スムージング表現（フォントヒンディング）|
|Smooth|スムージング表現|
|Raster Hinted|ラスター表現（フォントヒンディング）|
|Raster|ラスター表現|
|Distance Field 16|SDFシェーダを使用するために必要なテクスチャを作成する|
|Distance Field 32|上記のより高品質な設定。複雑な文字や小さな文字向け（作成に時間がかかる）|

#### 作成開始
Generate Font Atlasボタンを押すことで作成を開始します
高品質な設定・指定し文字数が大量にあるなどの場合は数分の時間を要しますので注意です
下の青いプログレスバーがいっぱいになるまで待ちましょう

#### 確認
右の部分に生成されたアトラステクスチャのプレビューが表示されたかと思います
そのまま保存する前に、正しく生成されているかを確認します
プログレスバーのすぐ下にメッセージが表示するテキストエリアがあり、そこに今回の生成の結果が書き込まれます
どのフォントリソースを使用したか、フォントサイズ等を表示しています。
ここで注目するのが`Characters packed`と`Missning Characters`という項目です
これはテクスチャに入った文字数と指定した文字数を表したものと、あぶれた文字の情報が載っています
基本的にCharacters packedの数値が左右同数であればすべての指定された文字が入っていますが、指定した解像度のテクスチャに入りきらなかった
そもそも指定した文字がフォントリソース内に存在していなかったなどがあった場合はどんな文字なのかという情報をMissing Charactersで表示しています
入りきらなかった場合は、解像度やフォントのサイズを調整してもう一度確認してください

![MissingCharacters.PNG](https://qiita-image-store.s3.amazonaws.com/0/83393/9b017a77-5f0e-5fb0-1598-d7c46e472e26.png)

#### 保存
Save TextMeshPro Font Assetボタンを押すことで、保存画面が開くので任意の場所に保存してください

これでTextMeshProで日本語が使用できる準備は整いました

### TextMeshProの基本設定
これからTextMeshProを使っていくうえで基本的な設定を確認する場合
設定ファイルはTextMesh Pro/Resources/TMP Settingsというアセットで設定を変更することができます

- 新しくTextMeshProのオブジェクトを作成したときに指定されるフォントアセットの設定
- 指定されていない文字の場合に検索される予備フォントの設定
- 新しいオブジェクトが作成されたときにデフォルトで設定される値の設定
- スプライトアセットの指定。文字列の中に入れることのできるスプライトのデフォルトアセットの設定
- スタイルシート設定ファイルの指定
- アジアライン打ち切り設定（どこでOverflow時にどの文字で改行するかなどの設定の模様（要調査））

## TextMeshProのコンポーネント

### UGUIにTextMeshPro-Textを追加する

`GameObject > UI > TextMeshPro-Text`
HierarchyのCreateボタンからも同様に作成できる。
CanvasがなければCanvasと一緒にTextMeshPro Textという名前のオブジェクトが作成される

### ゲームオブジェクトとしてTextMeshPro-Textを追加する
`GameObject > 3D Object > TextMeshPro-text`
MeshRendererを利用して文字列を表示することもでき、基本的な機能もUGUIと同じです
GameObject扱いなのでUGUIのOverlayではなく通常のカメラに映ることになるためフォントのサイズなどが違ったりしますので注意してください

### TextMeshPro(UGUI)コンポーネントの設定

![TextMeshProUGUI.PNG](https://qiita-image-store.s3.amazonaws.com/0/83393/be87edf3-88dc-8486-7fb8-17a89f46926e.png)

#### TEXT INPUT BOX
ここのテキストエリアに表示させたい文字列を入れます。
右上の`Enable RTL Editor`は右から読む文字（アラビア語やヘブライ語など）を記載する際に選択します（RTL：Right-to-left writing）

#### FONT SETTINGS
- Font Asset  
使用するフォントアセットを指定する
- Font Style  
太字・イタリック体・下線・取り消し線・小文字化・大文字化・小文字での入力で表記は大文字になるがサイズは小文字のままになる
- Color  
文字の色を指定する
- Color Gradient  
グラデーション。左上・左下・右上・右下それぞれに色の指定が可能。タグの設定よりも優先するかの設定も可能
- Font Size  
フォントのサイズを指定する。Auto Sizeを設定すると上限・下限の設定で、Rectに合わせて自動でサイズが変更されます
- Spacing Options  
間隔の設定。Charが1文字の間隔、Wordが単語(space区切り)の間隔、Lineで改行列の間隔、段落の間隔です
- Alignment  
文字揃えの設定  
水平方向：左揃え・右揃え・中央揃え・均等割付  
垂直方向：上端揃え・下端揃え・中央揃え　ベースライン・正中線整列？・キャップライン（文字のライン上の配置についてみたいです）
- Wrapping & Overflow  
折り返しするかなどの設定。UGUIの機能にもありましたね
- UV Mapping Options  
追加でテクスチャを文字に充てるときに、そのテクスチャのUVマッピングの設定です
- Enable Kerning? Extra Padding?  
フォントのカーニングを使用するかどうかと、文字のレンダリングに使用されるスプライトのサイズを最大化します

#### EXTRA SETTINGS

- Margins  
RectTransformのSizeからの余白の設定
- Geometry Sorting
- Enable Rich Text?  
リッチテキストを有効にするか？無効化するとプレーンテキストとして表示されます
- Raycast Target?  
テキストがUIのRaycastの対象となるかの設定です
- Parse Escape Characters  
エスケープ文字を有効にするかの設定です。\nや\tが有効になるかです
- Use Visible Descender  
- Sprite Asset  
<Spite>タグで使用する、埋め込み画像のアセットを指定します

### 文字演出機能
TextMeshProコンポーネントのshader部分には文字に対して、いくつかの効果をつけることができる
フォントアセットを作成したときのRenderModeによってできることは変わってくる

#### Face
テキストの境界線を拡張したりにじませたりする
また、テクスチャを割り当てることでテクスチャを文字に表示させることができる

|項目|説明|
|:-:|:-:|
|Color|境界線の色・文字に表示させるテクスチャの色、白がテクスチャの元の色になる|
|Texture|文字に表示させるテクスチャ|
|Softness|境界線のにじむ強さ|
|Dilate|境界線の拡張する大きさ|

#### Outline
テキストにアウトラインを表示する

|項目|説明|
|:-:|:-:|
|Color|アウトラインの色|
|Texture|アウトラインで表示するテクスチャ|
|Thickness|アウトラインの厚さ|

#### Underlay 影
テキストに影を追加する

|項目|説明|
|:-:|:-:|
|Underlay Type|影の種類（通常と内側がある）|
|Offset X|影が伸びる横方向の値(-1~1)|
|Offset Y|影が伸びる縦方向の値(-1~1)|
|Dilate|影の大きさ|
|Softness|影のにじむ強さ|

## Materialで文字演出の使い分け
このまま、1つのMaterialでシェーダの演出を設定した場合、そのフォントアセットを使用するすべての文字が同様の演出効果を受けてしまう
これだと、強調したい部分だけや同じフォントで演出をより分けたいといった方法ができなくなるため、
それぞれの文字演出を設定したMaterialを作成して、使い分けていく方法がある
ただし、Materialを増やすということなので複数の演出を使用する場合は、そのMaterial分だけSetPassCallsが増えるので注意してください

新しく演出Materialを作成するための手順

1. 生成したフォントアセット配下にあるMaterialを選択し、インスペクターに表示させてください
2. インスペクター上の上部にあるMaterialの小さなプレビューのようなところで右クリック
3. 画像のような、ポップアップメニューが表示されますので、その中から`Create Material Preset`を選択します
4. 新たにMaterialが作成されるので、目的に合った名前を付ける
5. TextMeshProコンポーネントのMaterial Presetに先ほど作成したMaterial名が追加されているか確認します

![MaterialMenu.PNG](https://qiita-image-store.s3.amazonaws.com/0/83393/a1920c49-3b32-82b5-71ca-38748d3c7440.png) ![selectMaterial.PNG](https://qiita-image-store.s3.amazonaws.com/0/83393/3b1f2c21-2ffc-54cd-28ea-fa569e8e3e68.png)

これで、文字演出をコンポーネントごとに設定できるようになります


## RichText & Style Tags
文字列中の一部分に対してのみに演出させたい場合に、HTMLやXMLのタグのように使える機能を一部分取り出しています

||タグ|説明|
|:-:|:-:|:-:|
|Text Alignment|\<align="center">～\</align>|文字揃え|
|Color|\<color="red">～, <#FF0000>～, \<color=#FF0000>～\</color>|文字が指定したカラーコードの色に|
|Alpha|\<alpha=#FF>|文字に透明度を設定できます|
|Bold|\<b>～\</b>|太字にします|
|Italic|\<i>～\</i>|イタリック体にします|
|Font|\<font="fontAssetName">～\</font>|指定したフォントアセットのフォントにします|
|Indentation|\<indent=15%>～\</indent>|インデントを指定できます|
|Sprite|\<sprite="assetName" name="spriteName">, \<sprite=0>, \<sprite name="spriteName" color="55FF55FF>|指定したスプライトアセットの画像を文中に表示します|

## Spriteとの連携

### TextMeshProコンポーネント
MeshRendererを使用したゲームオブジェクトのTextMeshProのコンポーネント
AddComponentしたときにMeshRendererも自動でAddComponentされる

``` CSharp
Start()
{
    TextMeshPro tmp = gameObject.AddComponent<TextMeshPro>();
}
```


### TextMeshPro/ TextMeshProUGUI API
Namespace : TMPro / Inherits from : MonoBehaviour

|プロパティ|型|説明|
|:-:|:-:|:-:|
|text|string|テキスト本体|
|alignment|AlignmentTypes|文字揃え|
|anchor|AnchorPositions|テキストのどの点がトランスフォームの位置を共有しているか。|
|anchorDampening|bool|変更がアンダーライン文字の幅の40％を超えない限り、アンカー位置が調整されないようにします。|
|bounds|Bounds|テキストオブジェクトの境界。（読み取り専用）|
|color|Color32|各文字に割り当てられたデフォルトの頂点カラーです。|
|characterSpacing|float|文字同士の間隔の追加量。|
|extraPadding|bool|各文字のジオメトリのサイズを大きくします。文字間の間隔には影響しません。|
|enableKerning|bool|カーニングの設定をします|
|enableWordWrapping|bool|単語の折り返しの設定をします|
|faceColor|Colo32|マテリアルの"_FaceColor"プロパティの色を指定します。値を変更するとマテリアルのインスタンスが作成されます|
|font|TMP_FontAsset|使用するTextMeshProのフォントアセット|
|fontMaterial|Material|このテキストオブジェクトに割り当てられたマテリアル。マテリアルを割り当てると、マテリアルのインスタンスになります。|
|fontSharedMaterial|Material|このテキストオブジェクトに割り当てられたマテリアル。fontSharedMaterialを使用しても、その素材のインスタンスは生成されません。|
|fontSize|float|使用するフォントのサイズ|
|horizontalMapping|TextureMappingOptions|フェイスとアウトラインのテクスチャをテキストオブジェクトに水平にマッピングする方法を制御します。|
|isOverlay|bool|テキストをシーン要素の最後と最後に強制的に描画するために、RenderQueueをZtestとともに設定します。|
|lineLength|float|単語の折り返しが発生する場所を指定します。|
|lineSpacing|float|テキストの各行の間に追加するスペースの追加量。|
|outlineColor|Color32|マテリアルの "_OutlineColor"プロパティの色です。outlineColorを変更すると、マテリアルのインスタンスが作成されます。|
|outlineWidth|float|文字の輪郭の太さ。この値を設定すると、フォントマテリアルのインスタンスになります。|
|overrideColorTags|bool|カラータグを上書きして、頂点カラーをデフォルトのフォントカラーに強制します。|
|verticalMapping|TextureMappingOptions|フェイスとアウトラインのテクスチャをテキストオブジェクトにどのように適用するかを制御します。|


|メソッド||説明|
|:-:|:-:|:-:|
|SetCharArray|void SetCharArray(char[] array);|文字配列をtextに追加する|
|SetText|void SetText<T>(string text, T arg0);|書式付き文字列。string.formatと同様にしてtextに追加する|
|UpdateMeshPadding|void UpdateMeshPadding();|クリッピングを防ぐために、マテリアルプロパティに基づいて必要なメッシュ再計算を強制して行う|


## TexturePackerとの連携

[TexturePacker](https://www.codeandweb.com/texturepacker)とは、複数のSpriteを一つのアトラステクスチャ（スプライトシート）にまとめるツールのことです
UnityでもSprite Packerとして似たような機能が提供されていますが、こちらのほうが高機能です
また、UnityのSprite Packerの場合、元のSpriteがResourceフォルダに置けない、枚数が多くなると起動時に時間がかかるようになるなどのデメリットも多いのが現状です


TextMeshProでは、出力されたスプライトシートをTextMeshPro用のSpriteAssetにインポートするツールがついています
`Window > TextMeshPro > SpriteImporter`
こちらで、TexturePackerからImportしたスプライトとJsonファイルをセットすることで、SpriteAssetを作成することができます
![SpriteImporter.PNG](https://qiita-image-store.s3.amazonaws.com/0/83393/c199523f-1c4f-eae6-0cf6-9859b0cb0ab4.png)

### TexturePackerで出力する際の設定の注意
TextMeshProではJSON形式のみのサポートで、なおかつTrimしていないスプライトシートのみになっており、TexturPackerの出力設定を変更しておかないと正しくアセットが作成されない可能性があるので注意してください

- Data FormatをJSON(Array)に設定する
- SpritesのTrim ModeをNoneにする

## 参考

- [TextMeshProのオンラインドキュメント](http://digitalnativestudios.com/textmeshpro/docs/)
- [UnityのText Mesh Proアセットで日本語を使うときの手順](http://qiita.com/thorikawa/items/03b65b75fa9461b53efd)
- [3D人 TextMesh Pro Free - Unityの高機能テキストソリューションがUnity標準機能化に伴い無料公開中！](http://3dnchu.com/archives/textmesh-pro-free/)