LoginSignup
30
25

More than 5 years have passed since last update.

Unity uGUIのTextをα値で1文字ずつ表示

Last updated at Posted at 2016-02-21

初めに

当たり前の方法なのかもしれませんが自分で思いついた方法が上手く動かせたのと
文章の書き方の練習もかねて記事にしておこうかと思います。

概要

ss00-compressor.gif

こんな感じのメッセージ表示をUnityで実装してみました。

やり方

BaseMeshEffectを継承したクラスを用意しModifyMeshをオーバーライド
そのメソッド内で頂点のアルファを書き換えます。
ソースはこのようになります。

using UnityEngine;
using UnityEngine.UI;
using System;
using System.Collections;
using System.Collections.Generic;

public class TextAlphaSending : BaseMeshEffect
{
    private const int OneSpriteVertex = 6;
    private bool _isEnd = false;
    private float _alpha = 0f;
    private int _charaCount = 0;
    private Text _text;
    public Text Text
    {
        get{return _text ?? (_text = GetComponent<Text>()); }
    }

    /// <summary>
    /// 文字表示終了判定
    /// </summary>
    /// <returns></returns>
    public bool IsEnd()
    {
        return _isEnd;
    }

    /// <summary>
    /// 文字数カウント初期化
    /// </summary>
    public void Initialize()
    {
        _charaCount = 0;
        _isEnd = false;
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="vh"></param>
    public override void ModifyMesh(VertexHelper vh)
    {
        var input = new List<UIVertex>();
        var output = new List<UIVertex>();
        var text = Text;

        vh.GetUIVertexStream(input);
        var vertexTop = _charaCount * OneSpriteVertex;

        if (vertexTop >= input.Count) {
            _isEnd = true;
            return;
        }

        for (int i=0; i<vertexTop; ++i) {
            output.Add(input[i]);
        }

        for (int i=vertexTop; i<vertexTop + OneSpriteVertex; ++i) {
            var uiVertex = input[i];
            uiVertex.color.a = (byte)(255f * _alpha);
            output.Add(uiVertex);
        }

        _alpha += 0.1f;
        if (_alpha >= 1f) {
            _charaCount++;
            _alpha = 0f;
        }        

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

using UnityEngine;
using UnityEngine.UI;
using System.Collections;

public class TextSenging : MonoBehaviour
{
    private Text _text;
    public Text Text
    {
        get
        {
            return _text ?? (_text = GetComponent<Text>());
        }
    }
    private TextAlphaSending _textAlphaSending;
    public TextAlphaSending TextAlphaSending
    {
        get
        {
            return _textAlphaSending ?? (_textAlphaSending = GetComponent<TextAlphaSending>());
        }
    }

    // Use this for initialization
    void Start ()
    {
        TextAlphaSending.Initialize();
        Text.text = "【王様】\nおお勇者よ,よくぞ参った";
    }

    // Update is called once per frame
    void Update ()
    {
        if (!TextAlphaSending.IsEnd()) {
            Text.SetAllDirty();
        }
    }
}

TextSengingのUpdateで表示される文字が残っている場合
Text.SetAllDirtyでModifyMeshが呼び出されるようにしています。

以上のような感じで1文字ずつα値を変化させて文字を表示することが出来ます。
問題点としてはα値の更新を行わないとならないため毎フレームSetAllDirtyで
頂点を更新しなければならないということです。
実際処理負荷を検証したわけではありませんがあくまでPC環境でちょっとした会話シーンなら問題にならないでしょう
モバイル環境だとさすがに厳しいかもしれません
uGUIの頂点は意外と簡単に編集できる一例として考えてください

30
25
1

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
30
25