- Home /
 
How do I calculate a text size with the Best Fit option using a TextGenerator
My goal is to link several Text components that they all have the same text size. Text size should be the minimum 'best fit' size of all components.
How I try to achieve it is by turning the 'best fit' option off and calculate the size with a custom TextGenerator, copying all TextGenerationSettings from the original Text components.
My Problem is: The calculated Text size is too small. It adjusts according to the RectTransform size, but is just wrong. Any thoughts about this?
Here is the code:
 using UnityEngine;
 using System.Collections;
 using UnityEngine.UI;
 using UnityEngine.EventSystems;
 
 [ExecuteInEditMode]
 public class kgLinkedBestFit : UIBehaviour 
 {
     public int minTextSize = 5;
     public int maxTextSize = 35;
     public Text[] linkedTexts;
 
     //TEMP: Editor Update
     public void Update()
     {
         TextGenerator textGenerator = new TextGenerator();
         int minimumBestFit = 1000;
 
         foreach(Text t in linkedTexts)
         {
             //get current text generation settings for the text field
             TextGenerationSettings settings = t.GetGenerationSettings(t.rectTransform.rect.size);
 
             //change to best fit settings
             settings.resizeTextForBestFit = true;
             settings.resizeTextMinSize = minTextSize;
             settings.resizeTextMaxSize = maxTextSize;
 
             //calcuclate with text generator
             textGenerator.Populate(t.text,settings);
         
             //set new bestFit if new calculation is smaller than current bestFit
             minimumBestFit = textGenerator.fontSizeUsedForBestFit < minimumBestFit ? textGenerator.fontSizeUsedForBestFit : minimumBestFit;
 
         }
 
         /*at this stage minimumBestFit is calculated too small. When the original textfield is set to best fit, the text size will be 22, the calculated text size is only 12*/
 
         foreach(Text t in linkedTexts)
         {
             //adjust font sizes
             t.fontSize = minimumBestFit;
         }
     }
 }
 
              Answer by hugojacob · Nov 25, 2015 at 09:19 AM
Hey.Old post, but for others i will answer.
I ran into the same problem. When using fontSizeUsedForBestFit variable the size returned did not match in the editor. After a long research the short answer to the problem is to divide the fontsize with the your canvas scale factor like this:
fontsize = fontsize / canvas.scaleFactor;
hope this helps others.
It sure did help!
Here's my full code for getting the current dynamic font size. Place these in a public static class.
             public static int GetCurrentDynamicFontSize(this Text text)
             {
                 if (text == null) return -1;
 
                 float multiplier = 1;
                 Canvas canvas = text.GetHighestCanvas();
                 if (canvas)
                     multiplier = 1 / canvas.scaleFactor;
 
                 return (int)(text.cachedTextGenerator.fontSizeUsedForBestFit * multiplier);
             }
 
             public static Canvas GetHighestCanvas<T>(this T component) where T : Component
             {
                 if (component == null) return null;
                 Canvas[] parentCanvases = component.GetComponentsInParent<Canvas>();
                 if (parentCanvases != null && parentCanvases.Length > 0)
                 {
                     return parentCanvases[parentCanvases.Length - 1];
                 }
                 return null;
             }
                 Answer by Gwom · Apr 19, 2017 at 03:09 PM
In case anyone else wants it, you have to wait a frame so the fontSizeUsedForBestFit gets calculated. I get consistant size of an item by adding anything I want to an array in the inspector and on play, wait a frame, find the size and apply it:
 using UnityEngine.UI;
 
 /// <summary>
 /// Cant work in editor, but will when the play button is pressed
 /// </summary>
 public class ConsistantTextSize : MonoBehaviour {
     public Text[] m_TextList;
     private int m_Size = 1;
 
     // Use this for initialization
     void Start () {
         SetSizes();
     }
 
     public void SetSizes()
     {
         foreach (var item in m_TextList)
             item.resizeTextMaxSize = 1000;
 
         StartCoroutine(WaitFrame());
     }
 
     public IEnumerator WaitFrame()
     {
         // returning 0 will make it wait 1 frame
         // need to wait a frame in order for the layout to work out the size
         yield return 0;
         ApplySizes();
     }
 
     public void ApplySizes()
     { 
         // Get the first one
         if (m_TextList.Length > 0)
             m_Size = m_TextList[0].cachedTextGenerator.fontSizeUsedForBestFit;
 
         // See if any are smaller
         foreach (var item in m_TextList)
         {
             if (item.cachedTextGenerator.fontSizeUsedForBestFit < m_Size)
                 m_Size = item.cachedTextGenerator.fontSizeUsedForBestFit;
         }
 
         // Apply as max size to all of the images
         foreach (var item in m_TextList)
             item.resizeTextMaxSize = m_Size;
     }
 }
 
 
              Your answer