はじめに
すいません、記事のタイトルをうまく日本語でまとめられませんでした。
以下で改めて解説します。
ゲーム中に会話シーン等で表示されるテキストは、一度に全文が表示されるのではなく、一文字ずつ徐々に表示されていくことが多いと思います。
このとき、テキストが表示しきる前に、ボタンを押したりクリックしたりすることで、残りのテキストがすべて表示される機能、ありますよね。
これのことです。
色々方法はあると思うのですが、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を呼び出します。
(ここは他の要素によって実装の仕方が変わると思います)
できあがったのはこちらです。
クリック回数を載せてみましたが、クリックのタイミングによって
挙動が異なることがわかりますかね・・・?
※例によって、動画中の環境部分はこちらのアセットを使用しています。
こちらもお借りしています。
おわりに
いろいろと書きましたが、このリンク先がすべてを教えてくれます。
神の参考記事