はじめに
今後エンジニアとして活動するか分からないので,ここを一旦の区切りとし,自分が作ったものの中で皆の役に立ちそうなものを共有します。
メイン
今回のスクリプトには,1文字ずつ表示する機能の他に下記のものを実装しました。
- 自動進行
- 一時停止
- 速度調整
この他に,UnityのTextMeshProに対応しています。
using UnityEngine;
using TMPro;
public class SentenceDisplay : MonoBehaviour
{
[SerializeField, TextArea]
private string[] _sentences;
[SerializeField]
private float _charaDisplayInterval = 0.1f;
[SerializeField]
private float _textAutoProgressInterval = 2.0f;
[SerializeField]
private bool _auto, _highSpeed, _wait;
[SerializeField]
private float _highSpeedValue = 2;
private float _progressTimer;
private float _autoProgressTimer;
// リッチテキストが進行中かどうか
private bool _inRichTextDuringProgress;
private string _currentSentence; // 現在の文
private int _currentLineIndex; // 現在の行数
private int _currentCharaCount; // 現在の文字数
private TextMeshProUGUI _textMeshPro;
private void Awake()
{
_textMeshPro = GetComponentInChildren<TextMeshProUGUI>();
}
private void Start()
{
SetSentence();
}
private void Update()
{
var inputAction = Input.GetMouseButtonDown(0);
// 文字の表示が完了している
if (SentenceDisplayIsComplete())
{
if (_auto) _autoProgressTimer += Time.deltaTime;
bool autoTimeElapsed = _textAutoProgressInterval <= _autoProgressTimer;
// 未表示のテキストが残っている,尚且つ(待機時間が完了,またはボタンが押される)
if (_currentLineIndex < _sentences.Length && (autoTimeElapsed || inputAction))
{
SetSentence();
}
return;
}
// 文字の表示が完了していない
else
{
_autoProgressTimer = 0;
if (inputAction)
{
// 文字を全て表示
_textMeshPro.text = _currentSentence;
_currentCharaCount = _currentSentence.Length;
}
}
var specifiedRangeIn = _currentCharaCount < _currentSentence.Length;
if (!_wait && specifiedRangeIn)
{
// 次に表示する文字によって処理を変更する
switch (_currentSentence[_currentCharaCount])
{
// RichTextを進行中に
case '<':
_inRichTextDuringProgress = true;
break;
// RichTextを終了
case '>':
_inRichTextDuringProgress = false;
_currentCharaCount++;
return;
}
if (_inRichTextDuringProgress)
{
_currentCharaCount++;
return;
}
_progressTimer += Time.deltaTime;
if (_highSpeed) _progressTimer *= _highSpeedValue;
if (_charaDisplayInterval < _progressTimer)
{
_progressTimer = 0f;
_textMeshPro.text = _currentSentence.Substring(0, _currentCharaCount + 1);
_currentCharaCount++;
}
}
}
private void SetSentence()
{
// 現在のテキストを更新
_currentSentence = _sentences[_currentLineIndex];
_currentLineIndex++;
_textMeshPro.text = string.Empty;
_currentCharaCount = 0;
}
private bool SentenceDisplayIsComplete() => _currentCharaCount == _currentSentence.Length;
}
かなりシンプルな構造だと思うので,機能追加や修正もしやすいと思います。
他,セットするテキストの配列をJsonから取得すると,使用の幅が広がるかなと(本来ならこの取得方法含めて記事を書く予定だった)