using UnityEngine; using UnityEngine.UI; [ExecuteAlways] [DisallowMultipleComponent] [RequireComponent(typeof(Text))] [RequireComponent(typeof(LayoutElement))] public sealed class BubbleTextWidthLimiter : MonoBehaviour { [Min(1f)] public float maxPreferredWidth = 224f; private Text textComponent; private LayoutElement layoutElement; private string lastText; private Font lastFont; private int lastFontSize; private FontStyle lastFontStyle; private float lastMaxPreferredWidth = -1f; private void Awake() { CacheComponents(); Apply(); } private void OnEnable() { CacheComponents(); Apply(); } private void OnValidate() { CacheComponents(); Apply(); } private void LateUpdate() { if (NeedsRefresh()) { Apply(); } } private void CacheComponents() { if (textComponent == null) { textComponent = GetComponent(); } if (layoutElement == null) { layoutElement = GetComponent(); } } private bool NeedsRefresh() { if (textComponent == null || layoutElement == null) { return false; } return lastText != textComponent.text || lastFont != textComponent.font || lastFontSize != textComponent.fontSize || lastFontStyle != textComponent.fontStyle || !Mathf.Approximately(lastMaxPreferredWidth, maxPreferredWidth); } private void Apply() { if (textComponent == null || layoutElement == null) { return; } textComponent.horizontalOverflow = HorizontalWrapMode.Wrap; textComponent.verticalOverflow = VerticalWrapMode.Overflow; var generationSettings = textComponent.GetGenerationSettings(new Vector2(10000f, 0f)); var rawPreferredWidth = textComponent.cachedTextGeneratorForLayout.GetPreferredWidth(textComponent.text ?? string.Empty, generationSettings) / textComponent.pixelsPerUnit; layoutElement.minWidth = 0f; layoutElement.preferredWidth = Mathf.Min(rawPreferredWidth, Mathf.Max(1f, maxPreferredWidth)); layoutElement.flexibleWidth = -1f; layoutElement.minHeight = -1f; layoutElement.preferredHeight = -1f; layoutElement.flexibleHeight = -1f; var rectTransform = transform as RectTransform; if (rectTransform != null) { LayoutRebuilder.MarkLayoutForRebuild(rectTransform); if (rectTransform.parent is RectTransform parentRect) { LayoutRebuilder.MarkLayoutForRebuild(parentRect); } } lastText = textComponent.text; lastFont = textComponent.font; lastFontSize = textComponent.fontSize; lastFontStyle = textComponent.fontStyle; lastMaxPreferredWidth = maxPreferredWidth; } }