16
12

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 1 year has passed since last update.

TextMeshProUGUIで表示したTextの最後の位置を取得する方法

Last updated at Posted at 2023-01-22

概要

UnityのTextMeshProUGUIコンポーネントでTextを表示する際に、最後の文字の位置を取得したいと思ったことはありませんか?(ノベルゲームの末尾に点滅するアイコンを表示したいなど…)

今回紹介する手法を用いることで、末尾に任意のRectTransformを追従させることが出来るようになります。

※今回は 左上詰め のテキストに追従させていますが、
AnchorPivot位置、スクリプトを調整することで任意方向に詰めたテキストにも応用できると思います。

test2.gif

動作環境

Unity 2021.3.6f1
TextMeshPro 3.0.6

セットアップ

スクリーンショット 2023-01-22 151612.png
1.png

Back

背景用のGameObjectです。
Imageと共に、今回作成したスクリプトをアタッチしています。

Text(TMP)

テキストを表示するGameObjectです。
RectTransformの設定は、末尾に表示する画像等を考慮して右側を少し広めに取っています。
TextMeshProUGUI左揃え かつ 上揃え に設定しています。

Marker

末尾に追従させるGameObjectです。
RectTransform左上を基準 に設定し、位置の微調整は Pivot で行います。
また、今回はアニメーションも指定しています。

惜しい実装例

よく紹介されている手法として、PreferredWidthPreferredHeightを利用する手法があります。

[SerializeField] private TextMeshProUGUI _text;
[SerializeField] private RectTranform _marker;

private void Update(){
    var x = _text.preferredWidth;
    var y = _text.preferredHeight;
    _marker.anchoredPosition = new Vector2(x,-y);
}

test1.gif

しかしこの方法では、テキストの 最大横幅最大縦幅 を取得しているため、改行が入ると正しく動作しません。
(また、Wrappingの設定がONだと、自動改行時にpreferredWidthだけがドンドン大きくなるなど…)

提案する実装例

[SerializeField] private TextMeshProUGUI _text;
[SerializeField] private RectTranform _marker;

private void Update(){
    var texInfo = _text.textInfo;
    var x = texInfo.lineCount == 0 ? 0 : texInfo.lineInfo[texInfo.lineCount - 1].length;
    var y = _text.preferredHeight;
    _marker.anchoredPosition = new Vector2(x, -y);
}

test2.gif

TextMeshProUGUItextInfo.lineInfoより、各行の情報を配列で取得できます。
また、textInfo.lineCountより、現在表示中の行数を取得できます。
Wrappingによる自動改行でも、行数は加算されます。

texInfo.lineInfo[texInfo.lineCount - 1].length より、最終行の横幅 を取得できます。
任意行の横幅 を取得可能なため、Anchor位置やPivot、スクリプトを修正することで、
任意方向に詰めたテキストに対応できると思います。

//提案した実装
var x = texInfo.lineCount == 0 ? 0 : texInfo.lineInfo[texInfo.lineCount - 1].length;

//間違った実装
var x = texInfo.lineCount == 0 ? 0 : texInfo.lineInfo[^1].length;

「わざわざlineCountを用いなくても、lineInfo配列の最後のデータを取得すればいいのでは?」
と思う方もいるかもしれませんが、lineInfo配列はキャッシュされている情報です。
配列の要素数は現在の表示行数とは不一致で、消えてしまった以前の内容が残り続けます。
必ずlineCountを使用して下さい。

まとめ

TextMeshProUGUITextの最後の位置を取得する方法についてご紹介しました。
是非、ご自身の制作活動に活用してみてください。

16
12
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
16
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?