はじめに
今回はTextMeshProUGUI
で描画したテキストに座布団(テキストの後ろの背景)をつけてみるという記事になります。

TextMeshPro
ならUnityEngine.Bounds
を利用することで割と簡単に実現できるのですが、TextMeshProUGUI
ではその手法が上手く使えずどうすれば良いかなーと考えていました。
TextMeshPro に背景色(Background-color)を付けてみる | Unity+AssetStoreおすすめ情報
またContent Size Fitter
とHorizontal Layout Group
の合わせ技でも似たことができますが、テキストが改行されたときの挙動が私の目的とするものと違ったので見送ってます。
見出しを表示する。uGUI。文字の長さに合わせて背景のサイズ変更したい。 - Qiita
ひとまず以下の手法で実現することができたので書き残しておきますが、実装のコレジャナイ感があり他に良さそうな手法を見つけたら直そうかなという感じではあります。
TextMeshProUGUI
のテキストのサイズ(preferredWidth
・preferredHeight
)にRectTransform.sizeDelta
を合わせる- 背景の
Image
を予め設定しておいたPadding
を考慮しながら、RectTransform.sizeDelta
を合わせる
ゲームオブジェクトの関係
Image |-----TextMeshProUGUI

コード
TextMeshProUGUI
コンポーネントがアタッチされているゲームオブジェクトに以下のコンポーネントをアタッチします。
[RequireComponent(typeof(TextMeshProUGUI))] public class TextMeshProUGUIZabuton : MonoBehaviour { private const float Tolerance = 0.00001f; [SerializeField] private Image image; [SerializeField] private float paddingWidth; [SerializeField] private float paddingHeight; private TextMeshProUGUI _tmp; private float _preWidth; private float _preHeight; private void Start() { _tmp = GetComponent<TextMeshProUGUI>(); } private void Update() { if (Math.Abs(_preWidth - _tmp.preferredWidth) < Tolerance && Math.Abs(_preHeight - _tmp.preferredHeight) < Tolerance) return; UpdateTMProUGUISizeDelta(); UpdateImageSizeDelta(); } /// <summary> /// RectTransform.sizeDeltaをテキストにぴっちりさせる /// </summary> private void UpdateTMProUGUISizeDelta() { _preWidth = _tmp.preferredWidth; _preHeight = _tmp.preferredHeight; _tmp.rectTransform.sizeDelta = new Vector2(_preWidth, _preHeight); } /// <summary> /// 背景のImageのRectTransform.sizeDeltaを指定したパディングで更新 /// </summary> private void UpdateImageSizeDelta() { if (_preHeight == 0 || _preWidth == 0) { image.rectTransform.sizeDelta = Vector2.zero; return; } image.rectTransform.sizeDelta = new Vector2(_preWidth + paddingWidth, _preHeight + paddingHeight); } }
あとは背景となるImage
をインスペクターから設定すればOKです。
ひとこと
調べたところWrapping
がEnabled
になっていると、新しく文字を追加したときに1フレームだけpaddingHeight
の値が大きくなってしまうようです。
一応Wrapping
をDisabled
にしたら治ったので共有しておきます。