【Unity2D】スプライトフォントを実装する

![001.png](https://qiita-image-store.s3.amazonaws.com/0/43772/f2938b27-670b-5b3d-3db5-07056d9a6eea.png)
こんな感じのテクスチャ画像をフォントとして表示する実装方法を紹介します。

実際には下の画像を使用します。(ファイル名は「font8x8.png」とします)
![font8x8.png](https://qiita-image-store.s3.amazonaws.com/0/43772/f9a4a496-8d2a-2821-46d0-f8c0636c92b5.png)

## 1. Spriteの作成
![002.png](https://qiita-image-store.s3.amazonaws.com/0/43772/b3c1dd67-cef8-6eef-56bb-ae5faefc8c63.png)
まずは「font8x8.png」をProjectビューにドラッグ＆ドロップして、フォルダ構成を以下のように配置します。

![003.png](https://qiita-image-store.s3.amazonaws.com/0/43772/2ae93a94-8e69-b603-ecb3-6f24baa7610f.png)
Inspectorビューで以下のように設定します。

* Texture Type:「Sprite」
* Sprite Mode:「Multiple」
* Filter Mode:「Point」

今回は拡大したときの補完を無効にしたいので、Filter Modeを「Point」にしました。

そして、「Sprite Editor」を開きます。
![004.png](https://qiita-image-store.s3.amazonaws.com/0/43772/33781e36-56ad-219d-2664-dc1a54ffa3fb.png)

* Type:「Grid」
* Pixel size:「X=8 Y=8」

にしてSliceボタンをクリックし、Applyボタンを押して適用します。

## 2. GameObjectの作成
![005.png](https://qiita-image-store.s3.amazonaws.com/0/43772/21004ea9-b2f5-fd18-d3f9-6f3b6723c680.png)
空のGameObject「SpriteFont」「SpriteChar」を作成します。
SpriteFontに渡された文字列を元に、SpriteCharを動的に追加する処理を作ります。

## 3. スクリプトの作成
「SpriteChar.cs」「SpriteText.cs」を作成します。

```csharp:SpriteChar.cs
using UnityEngine;
using System.Collections;

public class SpriteChar : MonoBehaviour {
  // 指定のスプライト番号でスプライトを動的に変更する
  public void SetChar(int idx) {
    string name = "font8x8_" + idx;
    SpriteRenderer sr = GetComponent<SpriteRenderer>();
    Sprite[] sprites = Resources.LoadAll<Sprite>("Sprites/font8x8");
    Sprite sp = System.Array.Find<Sprite>(sprites, (sprite) => sprite.name.Equals(name));
    sr.sprite = sp;
  }
}
```

SpriteChar.cs は、SpriteFont から1文字ずつスプライト番号を渡して、それを指定のスプライトに変更する処理を行います。

続いて、SpriteFont.cs です。

```csharp:SpriteFont.cs
using UnityEngine;
using System.Collections;

public class SpriteFont : MonoBehaviour {

  private static string _decode = "0123456789"; // 変換用文字列テーブル
  const float FONT_SIZE = 0.01f; // フォントサイズ。フォントのスケールやカメラの設定によって要調整

  // Use this for initialization
  void Start () {
    // テスト用
    SetText ("5813497620");
  }

  // 指定の文字でスプライトフォントを作成する
  public void SetText(string text) {
    int i = 0;

    foreach(char c in text) {
      GameObject obj = null;
      if(i < transform.childCount) {
        // 作成済みであればそれを使う
        obj = transform.GetChild(i).gameObject;
      }
      else {
        // SpriteCharをプレハブから取得
        GameObject prefab = Resources.Load ("Prefabs/SpriteChar") as GameObject;
        Vector3 pos = new Vector3(i * transform.localScale.x * FONT_SIZE, 0, 0);
        obj = Instantiate(prefab) as GameObject;
        // 子に設定する
        obj.transform.parent = transform;
        obj.transform.localPosition = pos;
        obj.transform.localScale = new Vector3(1, 1, 1);
      }
      
      // 文字を対応するスプライト番号に変換する
      int idx = _decode.IndexOf(c);

      // SpriteCharを取得してスプライトを変更する
      SpriteChar sc = obj.GetComponent<SpriteChar>();
      sc.SetChar(idx);
      i++;
    }
  }
}
```

プレハブから SpriteChar を取得して、動的に子ノードとして追加しています。そして文字をスプライト番号に変換して、SpriteCharにその番号を渡しています。

## 4. GameObjectを再び設定する

* SpriteFont
    * SpriteFont.csをアタッチする
    * Scaleを(X,Y,Z)=(8,8,8)に変更する
* SpriteChar
    * SpriteChar.csをアタッチする
    * Add ComponentでSprite Rendererを追加
    * プレハブ化し、Hierarchyビューから削除

![006.png](https://qiita-image-store.s3.amazonaws.com/0/43772/b88ed251-ca69-65c7-1b49-78a3ef61b426.png)
SpriteCharのプレハブは、「Resources/Prefabs」に配置しました。

## 5. 実行する
![007.png](https://qiita-image-store.s3.amazonaws.com/0/43772/f22f285b-50d5-1214-4769-3cd90a9d656c.png)
実行するとこんな感じで、スプライトフォントが表示されます。

## 6. 課題
ただしこの実装方法には色々な問題があります。

* 左寄せしかできない
* 改行できない
* フォントサイズを変更するたびに、SpriteFont.cs の FONT_SIZE を変更する必要がある
    * 実行時にサイズ変更できない