2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

【Unity】テキストを1文字ずつ表示する処理

Last updated at Posted at 2022-01-18

はじめに

今後エンジニアとして活動するか分からないので,ここを一旦の区切りとし,自分が作ったものの中で皆の役に立ちそうなものを共有します。

メイン

今回のスクリプトには,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から取得すると,使用の幅が広がるかなと(本来ならこの取得方法含めて記事を書く予定だった)

2
5
0

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
2
5

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?