この記事はUnityAdventCalendar 2025の記事です。
時間ができたので書きました。
- やること
- 開発環境
- 再現シーン
- DOTextからの置き換え(DOMaxVisibleCharacters編)
- DOTween.Toを使ったやり方(無料版DOTween対応)
- DOTextからの置き換え(UniTask版)
- まとめ
- 過去のUnity アドベントカレンダー記事
やること
DOTweenのDOTextを使って日本語テキストを1文字ずつ表示するとき、
日本語の禁則処理が後から適用され、途中で改行位置が変わる現象が起こることがあります。

原因は表示中の改行位置再計算による再レイアウトです。
これが発生しない文字表示方法をまとめます。
PRO版ではない無料のDOTweenでもできるやり方も紹介します。

先に答えから
検索でこの記事に来た方は、すぐに解決方法を知りたいと思うので先に書いておきます。
DOText()は使わず、DOMaxVisibleCharacters()で最大表示文字数を変動させる。
// DOTextを text.text = string.Empty; text.DOText(message, message.Length * writeTimePerChara).SetEase(Ease.Linear);
// DOMaxVisibleCharactersに置き換える text.text = message; text.maxVisibleCharacters = 0; text.ForceMeshUpdate(); text.DOMaxVisibleCharacters(message.Length, message.Length * writeTimePerChara).SetEase(Ease.Linear);
開発環境
Unity 6000.3.0f1
DOTween Pro ver1.0.385
再現シーン
わかりやすいように再現シーンを用意しました。

Canvasを作成し、テキスト(TextMeshPro)と表示範囲を設定。
確認しやすいように改行が発生しやすい設定にしています。

まずは通常のDOTextで表示してみます。以下のスクリプトを使用。
using DG.Tweening; using TMPro; using UnityEngine; using UnityEngine.UI; public class TextTest : MonoBehaviour { [SerializeField] private TMP_Text text; [SerializeField] private Button button; [SerializeField] private string sentence; [SerializeField] private float writeTimePerChara = 0.1f; private Tween currentTween; private void Start() { button.onClick.AddListener(() => WriteText(sentence)); } /// <summary> /// string型文字列を受け取ってTextに表示 /// </summary> private void WriteText(string message) { currentTween?.Kill(); text.text = string.Empty; text.ForceMeshUpdate(); currentTween = text.DOText(message, message.Length * writeTimePerChara).SetEase(Ease.Linear); } private void OnDestroy() { currentTween?.Kill(); } }
紐づけたボタンを押せばTextに文字列を表示します。

表示する文字列はこちら。改行が起こりやすいような文章にしています。
ここに「日本語テキスト」を表示します。。。。急に改行が入ったりするかを確認だ。
実行するとこんな感じ。
禁則処理によって、すでに表示されている文字が改行されています。

DOTextからの置き換え(DOMaxVisibleCharacters編)
ここから本題。やり方としては最大表示文字数を変動させます。
DOText()をDOMaxVisibleCharacters()に置き換えるだけ。
/// <summary> /// string型文字列を受け取ってTextに表示 /// </summary> private void WriteText(string message) { currentTween?.Kill(); text.text = message; text.maxVisibleCharacters = 0; text.ForceMeshUpdate(); currentTween = text.DOMaxVisibleCharacters(message.Length, message.Length * writeTimePerChara).SetEase(Ease.Linear); }
コードを解説すると、
先に表示したい文字列を全てtextに流し込み、ForceMeshUpdate()で改行位置を確定させ。
後から最大表示文字数を0から増やしています。
実行してみるとこんな感じ。
途中で改行位置が変わることなく最後まで表示されます。

DOTween.Toを使ったやり方(無料版DOTween対応)
TextMeshProの拡張を使わないやり方も紹介します。
このコードなら無料版DOTweenでも機能します。
/// <summary> /// string型文字列を受け取ってTextに表示 /// </summary> private void WriteText(string message) { currentTween?.Kill(); text.text = message; text.maxVisibleCharacters = 0; text.ForceMeshUpdate(); // 0 から 文字数 まで値を変化させる currentTween = DOTween.To( () => text.maxVisibleCharacters, x => text.maxVisibleCharacters = x, message.Length, message.Length * writeTimePerChara ).SetEase(Ease.Linear); }
DOTween.To()で値のトゥイーンを行っています。
実行結果は同じ。
DOTextからの置き換え(UniTask版)
おまけにDOTweenを使わずUniTaskを使った書き方も紹介。
DOTweenを使わない・使いたくない方向け。
using TMPro; using UnityEngine; using UnityEngine.UI; using System; using System.Threading; using Cysharp.Threading.Tasks; public class TextTest_UniTask : MonoBehaviour { [SerializeField] private TMP_Text text; [SerializeField] private Button button; [SerializeField] private string sentence; [SerializeField] private float writeTimePerChara = 0.1f; private CancellationTokenSource cts; private void Start() { button.onClick.AddListener(() => WriteTextAsync(sentence).Forget()); } /// <summary> /// string型文字列を受け取ってTextに表示 /// </summary> private async UniTaskVoid WriteTextAsync(string message) { cts?.Cancel(); cts?.Dispose(); cts = CancellationTokenSource.CreateLinkedTokenSource(this.GetCancellationTokenOnDestroy()); text.text = message; text.ForceMeshUpdate(); for (var i = 0; i <= message.Length; i++) { text.maxVisibleCharacters = i; var isCanceled = await UniTask.Delay(TimeSpan.FromSeconds(writeTimePerChara), cancellationToken: cts.Token) .SuppressCancellationThrow(); if (isCanceled) return; } } }
実行結果はだいたい同じ。
まとめ
今回はDOTextで日本語を表示する時に発生する、”途中で改行位置が変わる”現象を防ぐ方法をまとめました。
比較してみるとこんな感じ。

Unity製のゲームでそこそこ見かけるので、気になる人は試してみるといいかも。
以上です。
過去のUnity アドベントカレンダー記事