Unity技術検証

テキストを一文字ずつ流し、クリックしたら残りのテキストをすべて表示する実装方法【Unity】

はじめに

すいません、記事のタイトルをうまく日本語でまとめられませんでした。
以下で改めて解説します。

ゲーム中に会話シーン等で表示されるテキストは、一度に全文が表示されるのではなく、一文字ずつ徐々に表示されていくことが多いと思います。
このとき、テキストが表示しきる前に、ボタンを押したりクリックしたりすることで、残りのテキストがすべて表示される機能、ありますよね。

これのことです。

色々方法はあると思うのですが、DOTweenを利用した方法が簡単そうなので、やってみました。

実装例

using UnityEngine;
using UnityEngine.UI;
using TMPro;
using DG.Tweening;

public class DialogueManager : MonoBehaviour
{
    [SerializeField] TextMeshProUGUI speakerText;
    [SerializeField] Image speakerImage;
    [SerializeField] TextMeshProUGUI messageText;
    [SerializeField] Dialogue dialogue;
    [SerializeField] GameObject nextIcon;
    int currentIndex;

    [SerializeField] float messageSpeed = 0.05f;

    void Start()
    {
        ResetDialogue();
    }

    public void OnClickScr()
    {
        if (DOTween.IsTweening(messageText))
        {
            messageText.text = dialogue.Nodes[currentIndex - 1].Message;
            messageText.DOKill();
            nextIcon.SetActive(true);
        }
        else
        {
            ToNextNode();
        }
    }

    public void ToNextNode()
    {
        ResetDialogue();
        speakerText.text = dialogue.Nodes[currentIndex].Speaker;
        speakerImage.enabled = true;
        messageText.DOText(
            dialogue.Nodes[currentIndex].Message,
            dialogue.Nodes[currentIndex].Message.Length * messageSpeed)
            .SetEase(Ease.Linear)
            .OnComplete(() => nextIcon.SetActive(true));
        currentIndex++;
    }

    public void ResetDialogue()
    {
        speakerText.text = "";
        speakerImage.enabled = false;
        messageText.text = "";
        nextIcon.SetActive(false);
    }

}

※実装の前提
上記DialogueManagerクラスにいろいろな参照を持たせる実装を想定しています。
DialogueクラスはScriptableObjectで、Nodeクラスのリスト(Nodes)を持っています。
Nodeクラスは2種類のstring、Speaker(話者の名前)とMessage(本文)を所持。

ToNextNodeメソッドにDOTextを利用した文字送りの処理を入れています。
ここで個人的にポイントだと思うのは、第二引数のduration部分
dialogue.Nodes[currentIndex].Message.Length * messageSpeedです。
ここに入力したfloat値が、文字表示が完了するまでの時間となるのですが、
その場合、文章量が多ければ多いほど文字送り速度が速くなってしまいます。
そこで、表示するテキストのLength(文字数)を引数に入れることで、
テキスト量に依存せずに表示速度を一定にできるという方法になります。

このメソッドだけで単純な文字送りはできているのですが、
実装例では、画面上がクリックされたときに、OnClickScrメソッドを実行しています。
ここでは、まずDOTween.IsTweening()で引数であるmessageTextのトゥイーンが実行中であるか判定しています。

実行中の場合、この記事の目標どおり、残りのテキストをすべて表示させます。
なお、実装例では文字送り(ToNextNode)を開始する度にcurrentIndexを増やして管理していることから、ここで残りのテキストを一気に表示するためにcurrentIndex-1で指定しています。
その後、DOKillでmessageTextのトゥイーン(エア文字送り)を中断します。

実行中でない場合は、すでに文字送りが完了し、テキストがすべて表示されている状態であるといえます。そのため、次の文字送りを行うべく、単純にToNextNodeを実行します。

あとは、画面全体を透明なボタンで覆って、
ボタンが押されたとき(画面上がクリックされたとき)にOnClickScrを呼び出します。
(ここは他の要素によって実装の仕方が変わると思います)

できあがったのはこちらです。

クリック回数を載せてみましたが、クリックのタイミングによって
挙動が異なることがわかりますかね・・・?

※例によって、動画中の環境部分はこちらのアセットを使用しています。

Low Poly Ultimate Pack | 3D Props | Unity Asset Store
Elevate your workflow with the Low Poly Ultimate Pack asset from polyperfect. Find this & other Props options on the Unity Asset Store.

こちらもお借りしています。

アイコン素材ダウンロードサイト「icooon-mono」 | 商用利用可能なアイコン素材が無料(フリー)ダウンロードできるサイト | 6000個以上のアイコン素材を無料でダウンロードできるサイト ICOOON MONO
6000個以上のアイコン素材を無料でダウンロードできるサイト ICOOON MONO

おわりに

いろいろと書きましたが、このリンク先がすべてを教えてくれます。

神の参考記事

タイトルとURLをコピーしました