Search Unity

ForceMeshUpdate not updating correctly after RectTransform resized

Discussion in 'UGUI & TextMesh Pro' started by Lo-renzo, Jun 23, 2019.

  1. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,511
    I want to manually set the width of two TextMeshProUGUI elements that are part of a tooltiping system, one for Title and the other for the Body. Given that width, I want the Title/Body to determine their own height. With manual width and generated height in hand, I want to then resize the rect of an Image that provides a Background to the text.

    Code (CSharp):
    1.  
    2.  
    3. titleText.text = titleString;
    4. bodyText.text = bodyString;
    5.  
    6.  
    7.  // note sizes of things before setting anything
    8. Vector2 titleSize = titleText.GetRenderedValues();
    9. Vector2 bodySize = bodyText.GetRenderedValues();
    10. Vector2 renderedSize = new Vector2(Mathf.Max(titleSize.x, bodySize.x), titleSize.y + bodySize.y);
    11. Debug.Log($"BEFORE: textsRendered:{renderedSize} title:{titleText.rectTransform.rect} body:{bodyText.rectTransform.rect}");
    12.  
    13.  
    14. float manualWidth = GetManualWidth(titleString, bodyString); // this examines strings for some custom tags to exclude from width calculations
    15. titleText.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, manualWidth);
    16. bodyText.rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, manualWidth);
    17.          
    18.  
    19. titleText.ForceMeshUpdate(false);
    20. bodyText.ForceMeshUpdate(false);
    21.  
    22.  
    23. // note sizes of things after setting
    24. titleSize = titleText.GetRenderedValues();
    25. bodySize = bodyText.GetRenderedValues();
    26. renderedSize = new Vector2(Mathf.Max(titleSize.x, bodySize.x), titleSize.y + bodySize.y);
    27. Debug.Log($"AFTER: textsRendered:{renderedSize} title:{titleText.rectTransform.rect} body:{bodyText.rectTransform.rect}");
    28.  
    29.  
    30. // resize background image based on rendered sizes
    31.  
    32. this.backgroundPanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, renderedSize.x);
    33. this.backgroundPanel.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, renderedSize.y);
    34.  


    The problem is that GetRenderedValues - when called after ForceMeshUpdate - does not give me the correct values and so the backgroundPanel does not size the width correctly. GetRenderedValues seems to be delayed, printing for the previous time it was set. It was my impression that ForceMeshUpdate would cause GetRenderedValues to be correct, but it seems like specifying manualWidth with SetSizeWithCurrentAnchors has a delay before being accessible to GetRenderedValues?

    What is the proper way resize a RectTransform of a TMP text then to get its RenderedValues right away?
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Using the follow test script, this appears to be working as expected. See if you get similar results...

    Code (csharp):
    1.  
    2. using UnityEngine;
    3. using TMPro;
    4.  
    5. public class PreferredValueCheck : MonoBehaviour
    6. {
    7.     public TextMeshPro TextComponent;
    8.     public TextMeshProUGUI TextComponentUI;
    9.    
    10.     private string m_Label_01 = "A few lines of text for testing preferred values.";
    11.    
    12.     private void Awake()
    13.     {
    14.         // Set text value for testing
    15.         TextComponent.text = m_Label_01;
    16.  
    17.         // Force update of the text component
    18.         TextComponent.ForceMeshUpdate();
    19.  
    20.         // Get Rendered values
    21.         Vector2 renderedValues = TextComponent.GetRenderedValues();
    22.  
    23.         // Without ForceMeshUpdate() = (-Infinity, -Infinity)
    24.         // With ForceMeshUpdate() = (17.27, 20.58)
    25.         Debug.Log(renderedValues.ToString("f2"));
    26.     }
    27. }
    28.  
    Any reason you are using RenderedValues as opposed to PreferredValues()? Rendered values provide the mesh bounds results whereas preferred values returns the text based metrics which is what you usually want.

    Let me know if the above works as expected for you.

    BTW: Is your text object active in your scenarios / scene?
     
  3. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,511
    Thank you for a quick response. I have your test script working, and my test script working in, and I am now trying to isolate the difference between them and my real-world scene. The real-world scene reports (-Infinity,-Infinity) both before and after the first ForceMeshUpdate() so something is obviously wrong there, then subsequent changes to the text result in the right RenderedValues for the previously-provided text. I'll update once I figure it out.

    I'm using RenderedValues because my typical text looks like this:

    So, I provide a ManualWidth based on the bulleted lines then I use the height from RenderedValues to resize the Image background.

    Yes, it's active. The ForceMeshUpdate(false) was from testing. It is getting set to active right before updating the text.text = someString
     
    Last edited: Jun 24, 2019
  4. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,511
    If I leave all GameObjects (Background Image, Title Text, Body Text) active, this problem does not manifest at all. However, with how I currently activate/deactive the Background Image (which is parent to the TitleText and BodyText), GetRenderValues is reported incorrectly.

    Right now, the parent is disabled, deactivating all children whenever there's nothing to tooltip. Then, when there's something to tooltip, (1) the Background Image is activated, (2) titleText.text and bodyText.text = someString, (3) then I resize, and that's where GetRenderValues is wrong - right after activation after previously being deactivated via the parent G.O.
     
  5. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    I did make changes related to ForceMeshUpdate where it wasn't handling correctly the active / inactive state of objects. This should behave as you need for your workflow / use case.

    This change will be in the next release which should be available in the next 2 - 3 weeks.

    The changes were not significant and I believe I may have posted those somewhere here. I'll try to track these down specifically and post the changes here if I can.
     
  6. Lo-renzo

    Lo-renzo

    Joined:
    Apr 8, 2018
    Posts:
    1,511
    Good to know, thank you. For the meanwhile, I've narrowed the source of the bug to activating/deactivating the parent of the text. When I change the Background Image to be a sibling of the text, instead of its parent, and then I activate each child individually (Title Text, Body Text, and Background Image) the issue disappears.

    I'll try to remember to test the old system again with the next Unity release to let you know whether the issue with activating/deactivating the parent has been solved.