Unity_メッセージボックスによる文字送り

2D脱出ゲーム

ほぼ全てのゲームで見かけるメッセージボックスとクリック→次のメッセージを表示する仕様を纏めたいと思います。

メッセージボックスの配置

ゲーム画面は右の通りになります。下準備として以下の通り行います。

・スマホの縦画面相当の背景(720*1280)

・panelを画面下に配置(720*140)

・panel上に子としてbutton配置(560*140)

・image上に子としてtext2つ配置

buttonがメッセージボックスになりますが、最後のtext2つは人物名と本文の2種類になりますので、本文をRectTransformにて一段分下に下げて文字が重ならずに表示できる様にします。ちなみに文字サイズは28にしてますのでこのボックスには本文が約60文字入る仕様になっています。

文字送りの準備

人物名と本文のtext2つを配置しましたが、主人公が1人の場合心の声など人物名が要らないパターンもありますよね。両方のパターンを想定して以下新規スクリプトを作成します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
public class canvasUI : MonoBehaviour
{
    public Text names, messages;//人物名と本文
    public bool playing = false;
    public bool onMassage = false;
    void Update()
    {
        if (onMassage && playing){onMassage = false;}
    }     
    public void onMessageButton()//次のページを表示させる用
    {
        onMassage = true;
    }
    public void DisplayMessage(string mes)//人物名不要用
    {
        names.text = "";
        StartCoroutine("CoDrawText", mes);
    }
    public void DisplayMessage(string name, string mes)//通常会話用
    {
        names.text = name;
        StartCoroutine("CoDrawText","「" + mes + "」");
    }
    IEnumerator CoDrawText(string mes)
    {
        playing = true;
        float time = 0;
        while (true)//無限ループ
        {
            yield return null;//毎フレーム実行
            time += Time.deltaTime;
            int len = Mathf.FloorToInt(time * 30);
            if (len > mes.Length) break;//文字を満たすとループを抜ける
            messages.text = mes.Substring(0, len);//(int 開始位置, int 長さ)
        }
        playing = false;
    }
}

完成したらbuttonのクリックイベントにonMessageButtonメソッドを指定します。メッセージの中身は別スクリプト(クラス)でDisplayMessageメソッドを使用するのですが、ここで呼び出されるCoDrawTextコルーチンが文字送り処理になります。

このコルーチン内にはwhile (true)で無限ループを配置しており、指定された文字数(別途DisplayMessageメソッドで指定)を整数の変数であるlenが満たすと抜ける仕組みになっています。yield return nullはUpdateメソッドのようなもので毎フレーム実行されるのですが、Time.deltaTimeで秒数変換→さらにそれを30で乗算する事でlenをカウント→Substringでlenの長さまで文字送りしていきます。つまり1秒間で約30文字づつ文字送りできるという訳です。

文字送りの実行

では作成したcanvasUIクラスを基に実行していこうと思います。以下新規スクリプトを作成しましょう。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class TextManager : MonoBehaviour
{
    public canvasUI ui;//canvasUIクラスを使用
    public bool nowMessage = false;//メッセージ中に他操作をさせない為活用
    void Start(){StartCoroutine("Introduction");}
    IEnumerator Skip()//クリック待ちのコルーチン
    {
        while (ui.playing) yield return null;
        while (!ui.onMassage) yield return null;
    }
    IEnumerator Introduction()//文章を表示させるコルーチン
    {
        nowMessage = true;
        ui.DisplayMessage("・・・・・・・・・・");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("?", "う・・・寒っ・・・あれ?ここどこ?");
        yield return StartCoroutine("Skip");
        Instantiate(imagePrefabTejou, content);
        ui.DisplayMessage("知らない部屋だ。・・・ドアには鍵がかかっている。手錠もされてるし監禁ってやつかな。");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("・・・思い出した。小学校の帰りに突然誰かに殴られたんだっけ。とりあえずドアの向こうに助けを求めてみるか。");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("?", "おーーーーい!!誰かいるーー?");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("怖そうな男の声", "うるせえぞ黙れ!!大人しくしねえと殺すぞ。");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("・・・この口調は犯人か。静かにしておこう。");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("聞き覚えのある声", "聞こえるかコウタ。静かにしてろ。");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("今度は幻聴かな。兄貴の声?");
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("");
        nowMessage = false;
    } 
}

2種類のDisplayMessageメソッドを活用しているのは見ての通りですが、Skipコルーチンでクリックしたら次のメッセージに進む処理を挟んでいます。このSkipコルーチンは playingフラグfalse(文字送り完了)→onMassageフラグtrue(メッセージボックスクリック)の二段構成ループ離脱になります。クリックでなく秒数で次のメッセージに進みたい場合は、Skipコルーチンの代わりにyield return new WaitForSeconds(1.0f);の処理を挟むと機能します*この場合は1秒後。

インスタント文字送りの実行

ノベルゲームは先程のやり方で良いのですが、アドベンチャーゲームなどで気になる所を多数クリックしていく場合はコードを書きまくってグチャグチャになりそうですよね。インスタント用としてTextManagerクラスに以下メソッドを追加しましょう。

public void Normalmessage(string normal)
    {
        if (!nowMessage)
        {
            StartCoroutine("normalmessage", normal);//コルーチンに引数を渡す
        }
    }
IEnumerator normalmessage(string normal)
    {
        nowMessage = true;
        ui.DisplayMessage(normal);
        yield return StartCoroutine("Skip");
        ui.DisplayMessage("");
        nowMessage = false;
    }

Normalmessageメソッドは下のコルーチンに文字列を渡す構成になっているので、適当なボタンに設定してinspectorウィンドウで好きな文字を入力するだけで機能します。

まとめ

それぞれのデモになります。この処理さえ使えればゲー無はもう作れたも同然です。

コメント

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