Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
Help us understand the problem. What is going on with this article?

UI Textに様々な効果を付け加えるスクリプト「ModifyText」を作ってみた

More than 1 year has passed since last update.

はじめに

こんにちは、@yoship1639です。
普段は自作エンジンですが、最近Unityにはまっています。

皆様はユーザインタフェース(UI)をどの程度凝っていますでしょうか。UIの見た目や操作性がゲームの面白さを左右するといっても過言ではないくらいゲームにおいてUIは重要な役割を果たしています。

UnityのUIの代表格といえばTextです。
Textは説明文や会話などで何度も登場する無くてはならないUIですよね。

そんなTextですが、いまいちパッとしないなんて思った事ありませんか?
「特定の文章だけ別の色に変えたい…」「文字を振動させてもっと臨場感を出したい…」
少なくとも私はそう感じたので、何とかしたいと思いました。

そこで、ModifyTextなるものを作って様々な効果を付けられる様にしました。これはTextオブジェクトにModifyTextコンポーネントを追加する形でTextの見た目を変化させるスクリプトとなっています。
実際にどう変わるのか見てみたいと思います。

どう変わるのか

ModifyTextを使うと、ただのTextがこの様に変わります。

如何でしょうか。特定の文章のみ特定の効果を付け加えることが出来ます。しかも、特に面倒なスクリプトを書かなくてもTextにこの様なタグを付けるだけです。

031.png

一々スクリプトを書かずとも文章にタグを付けるだけで簡単に効果を付けられます。
それでは、どの様な種類の効果があるのか見てみたいと思います。

効果の種類

2018/12/24 時点で、以下の効果が適用可能です。

色付け

029.png

カラフル化

8r5je-fapi2.gif

振動させる

v5x6c-te1j6.gif

波打たせる

i3n2f-lingh.gif

円運動させる

ucvqp-bbqao.gif

サイズを変える

030.png

回転させる

rot.gif

もぞもぞ動く

rabd.gif

他にもこういうのが欲しい等がございましたら遠慮なく申し出てください!

ModifyEffectの仕組み

詳細はGithubのコードを参照

ソースコード全文を載せたいところですが、載せると長くなってしまうので、ソースコードはGithubのModifyTextを参照してください。コードをまるまるコピペすれば動くはずです。使い方もコードと同じ場所にあります。

それでは、どのような仕組みで動いているのか解説します。

BaseMeshEffectを継承したクラスを定義

UIのTextに効果を付け加えるには、生成されたメッシュを変更するエフェクトの基本クラスであるBaseMesheffectを継承したクラスを定義させます。生成されたメッシュというのはTextの場合、文字のメッシュの事を指します。今回はクラス名はModifyTextControllerという名前にします。
StartメソッドでGraphicとTextコンポーネントを取得しておきます。

ModifyTextController.cs
using UnityEngine.UI;
using UnityEngine;

[AddComponentMenu("UI/Effects/Custom/ModifyText")]
public class ModifyTextController : BaseMeshEffect
{
    Graphic graphic;
    Text text;

    void Start()
    {
        graphic = GetComponent<Graphic>();
        text = GetComponent<Text>();
    }
}

ModifyMeshをオーバーライド

次に、BaseMesheffectが持つModifyMeshメソッドをオーバーライドします。vh.GetUIVertexStream(vertices);という処理でストリームからTextの文字のメッシュを取得できるので、取得したメッシュを変更させる処理を行い、変更したメッシュをまたストリームに戻し変更が終了します。
UpdateメソッドではModifyMeshを毎フレーム実行するためにgraphic.SetVerticesDirtyをコールし続けます。

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

    List<UIVertex> vertices = new List<UIVertex>();
    vh.GetUIVertexStream(vertices); // ストリームから文字メッシュを取得

    // 文字メッシュを変更させる処理

    vh.Clear();
    vh.AddUIVertexTriangleStream(vertices); // 変更を加えたメッシュを戻す
}

void Update()
{
    graphic.SetVerticesDirty();
}

これで準備は整いました。あとは、効果を付け加えるだけです。
いくつか例を見てみます。

例:文字を赤色に変える

例えば、文字の色を赤に変えたい場合は以下の処理を行います。

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

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

    var charCount = vertices.Count / 6;
    for (var i = 0; i < charCount; i++)
    {
        for (int c = 0; c < 6; c++)
        {
            var vert = vertices[i * 6 + c];
            vert.color = Color.red;
            vertices[i * 6 + c] = vert;
        }
    }

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

verticesには文字の数*6の頂点データが渡されます。頂点データ6個で2つの三角メッシュを作り、四角ポリゴンである文字メッシュを表現します。頂点データは以下のように渡されます。
032.png
また、verticesにはpositionやcolor、noumalといった情報が含まれているので、ここの情報を書き換えることで、振動させたり色を変えたりという処理が可能となります。この例の場合はcolorをredに書き換えるだけです。
一応変更可能な項目を挙げておきます。

  • position
  • normal
  • tangent
  • color
  • uv0
  • uv1
  • uv2
  • uv3

これだけの項目を変更可能です。Textメッシュに関するほぼ全ての情報を書き換え可能なのは凄いですね。

もう一つ例を見てみます。

例:文字を波打たせる

文字を波打たせたい場合は以下の処理を施します。

public float WaveSpeed = 3.0f;
public float WaveRadius = 5.0f;

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

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

    var charCount = vertices.Count / 6;
    for (var i = 0; i < charCount; i++)
    {
        var delta = new Vector3(0, WaveRadius * Mathf.Sin(i + Time.time * WaveSpeed), 0);

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

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

deltaのy軸に時間で変化するsin波を適用させて、それをpositionにAddするだけで波打たせる処理を実装できてしまいます。思ったよりも簡単なのではないかと思います。

もう一つ紹介!

例:文字をカラフルにする

文字をカラフルにしたい場合はこの様に実装します。ある程度予想はつきますよね。

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

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

    var charCount = vertices.Count / 6;
    for (var i = 0; i < charCount; i++)
    {
        var color = new Color(UnityEngine.Random.value, UnityEngine.Random.value, UnityEngine.Random.value);

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

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

colorをランダムでセットするだけです。とてもシンプルですね。

ModifyMeshは毎フレーム呼ばれるので、文字ごとに毎回違う色を表現出来ます。graphic.SetVerticesDirtyを呼ぶ間隔変えれば、色が変わる間隔も変わるので、自分の理想とする処理をうまく見つけてみてください。

この様に効果を適用していけば、どう変わるのかに示した様なテキストスクリプトを作ることができます。もちろん、Text中のタグを調べ効果を適用していく等の処理は必要ですが、最初に示した様なスクリプトは、大体300行くらいで作れてしまいます。意外と簡単ですね!

まとめ

UIのTextに様々な効果を付け加えることができるModiftTextというスクリプトを作成し、軽く解説させていただきました。ソースコード全文を紹介することはできませんでしたが、どの様に作れば最初に示したような効果を実装できるのかは解説で理解する事が出来たのではないでしょうか。

主に会話シーン等で使えると思いますので、是非ご活用ください!
また、リクエストも受け付けていますので、こんな処理も欲しい等がございましたらコメントもしくは@yoship1639まで遠慮なくお願い致します!

ご覧いただきありがとうございました。

yoship1639
ゲームエンジニア。C#er。バックエンドも触る。ゲーム、ゲームエンジン、仮想通貨等を自作していました。フロントエンドから物理ベースシェーダまで幅広く対応可能。理解しやすく正しい記事を記述することを心がけます。
https://twitter.com/yoship1639
unity-game-dev-guild
趣味・仕事問わずUnityでゲームを作っている開発者のみで構成されるオンラインコミュニティです。Unityでゲームを開発・運用するにあたって必要なあらゆる知見を共有することを目的とします。
https://unity-game-dev-guild.github.io/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away