Search Unity

TextMesh Pro Text info not being updated when using ForceMeshUpdate(true)

Discussion in 'UGUI & TextMesh Pro' started by ihgyug, Mar 7, 2020.

  1. ihgyug

    ihgyug

    Joined:
    Aug 5, 2017
    Posts:
    194
    Hi,

    I currently disable and enable canvases to make transitions between one another, but I encounter issues with the textinfo not being updated, albeit using ForceMeshUpdate(true). Is this intended behaviour?

    It would be very handy if it worked even if the text was under a disabled canvas as I wouldn't have to check and re-check if the canvas is active while playing a "text effect" (such as fading in/out the text).

    Currently using unity 2019.3.3, TMP version 2.0+ all have the same issue.

    Thanks
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Please test with version 2.1.0-preview.5 as I believe this issue should be resolved in those newer releases.
     
  3. ihgyug

    ihgyug

    Joined:
    Aug 5, 2017
    Posts:
    194
    Tested, but the issue persists in that version as well.
     
  4. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Let me see if I can reproduce the behavior to check it out.

    One thing is for certain, if the Canvas is disabled, any layout components potentially affecting the text object might incorrectly affect the RectTransform of the text object thus resulting in an incorrect layout and text info.

    Nonetheless, I'll take look and follow up when I have more information.
     
    ihgyug likes this.
  5. ihgyug

    ihgyug

    Joined:
    Aug 5, 2017
    Posts:
    194
    Was there any update on the issue?
     
  6. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Any chance you can provide a simple reproduction project for me to look at? This always makes it so much easier / faster for me to look at this issue and to ultimately resolve the issue quicker for the user(s).
     
  7. ihgyug

    ihgyug

    Joined:
    Aug 5, 2017
    Posts:
    194
    Here it is :
     

    Attached Files:

    Stephan_B likes this.
  8. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Thank you for providing the reproduction project.

    I had a chance to take a closer look at the behavior which is the result of the reference to the canvas being null when you call ForceMeshUpdate() in Awake().

    A closer look at the implementation in the Graphic class reveals that "this.canvas" returns null if the canvas is disabled. As such, TMP early returns out since from its point of view there is no canvas.

    I will check tomorrow with the Philip at Unity to get more information on this and follow up as soon as I have more information.
     
    ihgyug likes this.
  9. ihgyug

    ihgyug

    Joined:
    Aug 5, 2017
    Posts:
    194
    Was there any update?
    I am not in a hurry, but I am curious if a fix for this is expected, so that I can decide whether to polish the workarounds for this issue, or peacefully wait a beautiful fix :)
     
  10. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    I have a potential solution which is as follows:

    As per my previous post, the reason why ForceMeshUpdate(true, true); is not working as expected is because the canvas property in the Graphic class returns null instead of returning a valid reference when the Canvas is disabled. This in turn results in TMP skipping the text regeneration process because it doesn't have a valid canvas.

    So in order to get around this behavior, I can add a GetComponentInParent<Canvas>() in ForceMeshUpdate().

    To minimize the additional overhead of GetComponentInParent() I would check if m_Canvas is null internally which would ensure we don't get this additional overhead when calling ForceMeshUpdate when the Canvas is active / enabled.

    Code (csharp):
    1.  
    2. public override void ForceMeshUpdate(bool ignoreActiveState = false, bool forceTextReparsing = false)
    3. {
    4.     m_havePropertiesChanged = true;
    5.     m_ignoreActiveState = ignoreActiveState;
    6.     m_isInputParsingRequired = m_isInputParsingRequired ? true : forceTextReparsing;
    7.  
    8.     // Special handling in the event the Canvas is disabled
    9.     if (m_canvas == null)
    10.         m_canvas = GetComponentInParent<Canvas>();
    11.  
    12.     OnPreRenderCanvas();
    13. }
    14.  
    However, when the Canvas is disabled, we would get the GetComponnetInParent() which would get us a valid Canvas so that we can process the text to populate it with valid textInfo.

    Using your test project, works as expected.

    It is important to note that with the Canvas disabled, it is likely all Layout Components won't behaves as expected so in these cases, although the text will be processed, we may not get valid data in terms of # of lines, preferred values, etc. since the RectTransform of the text object will be bunkers given the Layout Components are not doing their job in that state.

    Thoughts?
     
    Last edited: Apr 23, 2020
    ihgyug likes this.
  11. ihgyug

    ihgyug

    Joined:
    Aug 5, 2017
    Posts:
    194
    It's a step forward, and I thank you for the update, but I'll most likely drop the "canvas enabled/disabled" set-up for now.

    It was nice to enable/disable the component itself, since it's literally a few lines change to my canvas manager for the sake of some small, but free performance, and it seemed like the way to go.

    But it's currently not worth the benefit, as I keep on running into issues, such as layout components "going crazy", calculations based on rect transforms "going off", and more...(as an example : https://issuetracker.unity3d.com/is...tached-to-is-disabled-when-entering-play-mode).

    What I've noticed tho, is that by using Canvas Groups for main canvases aswell, I retain the same benefits (by setting the canvas group's alpha to 0) and everything works as it should, so I'll consider working with them rather than the canvas components.
     
  12. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Disabling a Canvas to simply hide its child content is indeed problematic and potentially costly depending on how many children, layout components, etc. It is a lot of potential processing to just hide its content.

    I think using a Canvas group to fade the Alpha is a good idea. I still wish we had a way to just disable CanvasRenderers just like we can disable a MeshRenderer as a component. This has always been a super efficient way to hide stuff.