おもちゃラボ

Unityで遊びを作ってます

【Unity】uGUIの文字を一文字ずつ別々に動かす

uGUIを使って文字列を表示するにはTextを使います。このTextを使って一文字ずつランダムに動かす方法を紹介します。UIの文字でも場所によっては動いている方が楽しいですね〜

f:id:nn_hokuson:20170521083830g:plain

UIのTextを一文字ずつ動かす方法

UGUIのTextはModifyMeshメソッドを使うことで、文字を構成するポリゴンにアクセスすることが出来ます。各ポリゴンの頂点座標を配列として得られるので、その頂点座標を一文字ごとに、違った方向に動かすことで文字がバラバラの動きをします。

f:id:nn_hokuson:20170521085157p:plain:w500

文字を構成するポリゴンは4頂点ではなく、6頂点で構成されるので注意が必要です。次のような並びになっているようです。

f:id:nn_hokuson:20170521085442p:plain:w180

したがって、頂点配列の頂点を6個ごとにばらばらの方向に動かすことで上のような文字の動きが実現できます。

ランダムに動かす方法はなんでも良いのですが、ここでは半径Rの円周上をランダムに指すベクトルを方向ベクトルとして使っています。

f:id:nn_hokuson:20170521085744p:plain:w230

では、具体的な実装方法を紹介します。

uGUIでTextを配置する

まずはuGUIでTextを配置します。ヒエラルキービューから「Create」→「UI」→「Text」を選択し、インスペクタから適当な文字を設定して下さい。文字の設定はText欄から行います。その他にも、FontやFont Size、Colorなども調整します。

f:id:nn_hokuson:20170521090146j:plain

テキストを動かすスクリプトを作成する

続いて、文字を動かすためのスクリプトを作成します。プロジェクトビューで右クリックして「Create」→「C# Script」を選択し、「TextController」という名前で保存して下さい。

スクリプトが作成できたら次のプログラムを入力して下さい。

using UnityEngine.EventSystems;
using System.Collections.Generic;

public class TextController : BaseMeshEffect {

    float time = 0;
    float radius = 1.5f;

    public override void ModifyMesh ( UnityEngine.UI.VertexHelper vh)
    {
        if (!IsActive())
            return;

        List<UIVertex> vertices = new List<UIVertex>();
        vh.GetUIVertexStream(vertices);

        TextMove(ref vertices);

        vh.Clear();
        vh.AddUIVertexTriangleStream(vertices);
    }

    void TextMove( ref List<UIVertex> vertices )
    {
        for (int c = 0; c < vertices.Count; c += 6)
        {
            float rad = Random.Range(0,360) * Mathf.Deg2Rad;
            Vector3 dir = new Vector3 (radius * Mathf.Cos (rad), radius * Mathf.Sin (rad), 0);

            for(int i = 0; i < 6; i++)
            {
                var vert       = vertices [c+i];
                vert.position  = vert.position + dir;
                vertices [c+i] = vert;
            }
        }
    }

    void Update()
    {
        time += Time.deltaTime;
        if (time > 0.05f)
        {
            time = 0;
            base.GetComponent<Graphic> ().SetVerticesDirty ();
        }
    }
}

uGUIのTextはBaseMeshEffectクラスのModifyMeshメソッドをオーバーライドすることで、テキストの表示に使われているポリゴンの頂点にアクセス出来るようになります。

このあたり、Unity5.1、5.2、5.3とどんどん仕様が変わっているようなので、バージョンによってはうまく動かないかもしれません。上のプログラムはUniy5.6で動作を確認しています。

toriden.hatenablog.com

取り出した頂点をTextMoveメソッドの引数に渡しています。TextMoveメソッドの中では6頂点ごとにランダムなベクトルを定義して、頂点座標をベクトル方向に移動させています。

最後にUpdateメソッドから逐次SetVerticesDirtyメソッドを呼ぶことで、文字が動くアニメーションを再生することが出来ます。

おまけ(もっと、もにょもにょ動かす)

上の例では、文字を構成する6頂点はまとめて同じ方向に動かしていましたが、これを1頂点ごとに方向も長さもランダムな方向に動かすと、さらにもにょっとした動きになりました。

f:id:nn_hokuson:20170521090514p:plain:w250

こんな感じです。綺麗かどうかは置いておいて(笑)

f:id:nn_hokuson:20170521090308g:plain

TextMoveメソッドの中は次のようになっています。頂点2と頂点3、頂点0と頂点5は同じ座標を指すので、同じ方向のベクトルを与えています。

            Vector3[] dirs = new Vector3[6];

            for (int i = 0; i < 6; i++)
            {
                float rad = Random.Range (0, 360) * Mathf.Deg2Rad;
                float r = radius + 6.5f * Random.value;
                Vector3 dir = new Vector3 (r * Mathf.Cos (rad), r * Mathf.Sin (rad), 0);

                dirs [i] = dir;
            }

            dirs [3] = dirs [2];
            dirs [5] = dirs [0];

            for(int i = 0; i < 6; i++)
            {
                var vert       = vertices [c+i];
                vert.position  = vert.position + dirs[i];
                vertices [c+i] = vert;
            }

まとめ

ModifyMeshメソッドをオーバーライドすることで、uGUIのTextの各頂点座標にアクセスする方法を紹介しました。動かし方はまだまだバリエーションが出せると思うので、是非試してみて下さいね〜

[asin:4839956405:detail]