31
24

More than 5 years have passed since last update.

Unityで文字の3Dモデルを作る(FlyingText3Dアセット編)

Posted at

文字を3Dモデルとして扱う事で、巨大な文字を積み上げたり転がしたりしたいと思い、試してみました。
前回はVTextというアセットを試してみましたが、Dynamic Batching問題があって断念しました

結論を先に書くと、このFlyingText3Dは動作はもちろん、ドキュメントがとても分かりやすく詳細で、APIも必要なものが揃っているため、とても良い感じです。

FlyingText3Dについて

Asset Storeで公開されている有料アセットです。
FlyingText3D
https://www.assetstore.unity3d.com/en/#!/content/3627

※クリックでYouTubeの説明動画に飛びます
FlyingText3D説明動画

Requires Unity 3.5.7 or higher.
Create real dynamic 3D text from TrueType fonts right in Unity, quickly and easily! Everything you need for killer title screens and menus, or anywhere else you need to go beyond bitmaps. One simple command will make dynamic text at runtime, either as a single object or as multiple objects, where each one can have a collider and rigidbody. Or you can make text 3D prefabs directly in the editor.

価格は $19.95 (2016年9月11日時点)

確認環境

  • Unity v5.4.0f3
  • Xcode v7.3.1
  • MacBook Pro (OS X 10.11.5)

デモを動かす

このアセットは全てimportするだけで動作します。

  1. FlyingText3Dアセットをインポート(全てチェックでOK)
  2. Assets/FlyingText3D/Demos/GameOver Demo/_GameOver シーンを開く
  3. 実行

GAME OVERデモ動画

日本語フォントの利用

結論から書くと、日本語は使えますが若干の手順が必要です。
上記のデモシーンでそのまま試します。

フォントファイルを用意する

今回はサンプルとしてIPAが公開しているIPAexフォントを利用します。
1. 使いたいフォントの .ttf ファイルを用意する
2. Finder上で拡張子を .ttf -> .bytes に変更する。例) ipaexm.ttf -> ipaexm.bytes
3. このファイルを Assets 以下の任意の場所に置く

※拡張子を変える理由は、このアセットとしてはフォントの生データを扱う必要があるが、.ttfだとUnityがフォントとして扱ってしまいそれを許さないため、と説明されています。
参考: Unityマニュアルアセットバンドルにバイナリデータを含めて読み込む

フォントを指定する

  1. Hierarchy で FlyingText を選択する
  2. Inspector の Font Settings で、下図のように chintzy というフォントが指定されている右の選択アイコンをクリック flyingtext3d_japanese_sample2.png
  3. 上記で準備したフォントファイルを指定する。例) ipaexm
  4. 実行する(この時点でフォントの読み込みに問題が無いかどうかの確認)
  5. GameOver Demo ディレクトリにある GameOverControl.js をエディタで開き、12行目あたりにある"GAME<br>OVER"を日本語に書き換える
FlyingText.GetObjects ("ゲーム<br>オーバー")

実行すると日本語が表示される。
flyingtext3d_japanese_sample1.png

スクリプトファイルの文字エンコーディングについて

日本語(マルチバイト文字)を扱う場合、文字エンコーディングは以下にする必要があります。(ドキュメントのP.17参照)
- C#: UTF-16
- UnityScript: UTF-8 または UTF-16

フォントの複数指定について

上記の手順では既存のフォント指定を変更していますが、追加する事も可能です。これは、1つのFlyingTextオブジェクト中で複数種類のフォントを利用したい場合に用います。

  1. Font settings+ Add Font をクリックする
  2. フォント名の右の選択アイコンで、追加したいフォントを選ぶ
  3. Character settingsDefault Font で、無指定の場合に用いるフォント番号を指定する。

手順3.に注意して下さい。複数フォントを指定した場合、何も指定しないと手順3.で指定したものが常に採用されます。つまりそのフォントデータに指定した文字が含まれていない場合(英字フォントで日本語を表示した場合など)、次のフォントから検索されたりはせず、単に表示をスキップされるという事です。

この例では、IPAex明朝フォントを追加した上で、デフォルトをそちら(#1)にしています。
flyingtext3d_japanese_sample3.png
4. デフォルト指定したフォント以外を使う場合は、文字列中に Tag(マークアップのタグ)を書きます。閉じるタグは不要(無視される)、クォートも不要という事で見た目ちょっとモヤモヤしますが、無駄にパースさせても仕方ないので我慢します。

FlyingText.GetObjects ("<size=0.5>ゲーム<br><font=0><size=1>OVER")

この例は以下の指定を行っています
- <size>で文字の大きさ
- <br>で改行
- <font>で使用するフォント番号

実行すると無事に2種類フォント混在で表示されました。
flyingtext3d_japanese_sample4.png

スクリプトで動的に文字を生成する

(1)文字列全体を単一オブジェクトとして扱う

  1. シーンに空のGame Objectを追加する
  2. そのオブジェクトに Add Component -> FlyingText3D -> FlyingTextでコンポーネントを追加する
  3. 追加したコンポーネントの Font settings -> + Add Fontでフォントを追加し、利用するフォントを指定する(上記のデモ手順参照)
  4. 同オブジェクトに、更にAdd Componentで新規スクリプトを追加する
OneObjectSample.cs
using UnityEngine;
using System.Collections;

public class OneObjectSample : MonoBehaviour {

    void Start () {
        FlyingText.GetObject("これは1つのGame Objectです");
    }

    void Update () {
    }
}

実行結果は以下です(全体が見えるように位置は適当に手動でずらしました)
flyingtext3d_coding_1.png

GetObject()は、指定した文字列を1つのMeshとして作ります。
flyingtext3d_mesh_1.png

ここでは必須パラメータである文字列のみ指定しましたが、位置やサイズ、マテリアルや行間などを指定する事もできます。これらを指定しなかった場合は、手順2.で追加したコンポーネントの Inspectorで設定した値が使われます。もしくは、 コードでもデフォルト値を設定する事ができます。詳しくはドキュメントを参照して下さい。

(2)1文字ごとに別のオブジェクトとして扱う

スクリプト以外は(1)文字列全体を単一オブジェクトとして扱うと同じです。

なお例として文字に重力を与えたかったので、各文字にRigidbodyをつける設定をしました。
Flying TextのInspector -> GameObject settings -> Add rigidbodies にチェック
flyingtext3d_coding_3.png

MultiObjectSample.cs
using UnityEngine;
using System.Collections;

public class MultiObjectSample : MonoBehaviour {

    void Start () {
        GameObject objectParent = FlyingText.GetObjects("1文字ごとに別オブジェクト");
        Rigidbody[] rigidBodies = objectParent.GetComponentsInChildren<Rigidbody>();
        for(int i = 0; i < rigidBodies.Length; i++) {
            if(Random.value < 0.5f) {
                Rigidbody rb = rigidBodies[i];
                rb.useGravity = false;
            }
        }
    }

    void Update () {
    }
}

実行結果。重力を無効にされなかった文字(ランダム)のみ落ちていきます。
flyingtext3d_coding_2.png

GetObjects()は、1文字ごとにメッシュを分けて生成した上で、それらを保持する親となるGame Objectを作成します。
flyingtext3d_mesh_2.png

この例では先述の通りRigidbodyを作成するオプションをつけているので、各文字のRigidbodyを GetComponentsInChildrenで取得する事ができます。

なおこの2関数以外にも、以下のようなAPIが用意されています。

  • 最初から配列で文字単位のGameObjectを作る
  • 文字列を更新する
  • 初回のモデル作成時間によるカクつきを避けるために事前にモデルを作る

以上により、もともと私がアセットを試した目的である、巨大な文字を転がしたり積み上げたりというのが実現できそうな事が分かりました。

補足

初期化処理の実行タイミング

FlyingText3Dの初期化処理はAwake()で行われます。初期化処理前に自前スクリプトからGetObjectなどを呼び出してしまうとエラーになるため、実行順が確実に初期化処理よりも後になるようにします。
Start()やUpdate()であればAwake()より確実に後になります(Unity - マニュアル: イベント関数の実行順)。もし何らかの理由で順序を指定したい場合は Edit -> Project Seetings -> Script Execution Orderで指定します。

31
24
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
31
24