Search Unity

TextMesh Pro Textmesh pro is not updating when changing text programatically

Discussion in 'UGUI & TextMesh Pro' started by Ledrec, Aug 24, 2017.

  1. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Please make sure you are testing with the latest release which is preview 11 as I did address some of those potential issues.

    Please confirm if you are still having or not this issue with the latest release.
     
    Rodolfo-Rubens likes this.
  2. Rodolfo-Rubens

    Rodolfo-Rubens

    Joined:
    Nov 17, 2012
    Posts:
    1,197
    Issue is no longer occurring in this version! No need for Is Scale Static.
    Thanks a lot!
     
    soorya696 and Stephan_B like this.
  3. soorya696

    soorya696

    Joined:
    Dec 13, 2018
    Posts:
    71
    Updating to the latest version fixed the issue, Thanks.
     
    Stephan_B likes this.
  4. mrsimmo

    mrsimmo

    Joined:
    May 4, 2013
    Posts:
    12
    I'm having a version of this problem, using preview 14.

    For me, I'm using a very simple .text method to update the TextMeshProUGUI asset, which is updating in the inspector but not in the game window.

    The weird thing is, this problem seems limited to strings that I'm getting from a backend server. Like lots of the previous posts, if I manually change an inspector property, the text appears.

    noob question - but Is it possible that there's some hidden characters in the string that are causing this behaviour?

    The text updates fine using this method locally if I invoke it using a button and just pass a string from the inspector.

    Apologies if I'm missing something, but I've been banging my head against my desk with this for a few hours now. This method has always worked fine previously....
     
  5. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    First I would recommend using the latest release to see if the behavior persists.

    The latest releases are version 1.5.0 for Unity 2018.4, version 2.1.0 for Unity 2019.x and version 3.0.0 for Unity 2020.x.

    It is possible.

    Are you able to reliably reproduce the behavior? If so can you submit a bug report with the project along with steps to reproduce? This would enable me to know exactly why it is occurring and resolve it in the event it is a bug.
     
  6. mrsimmo

    mrsimmo

    Joined:
    May 4, 2013
    Posts:
    12
    HI Stephan,

    UPDATE -
    Okay - so the only thing that fixed this for me was using the main thread dispatcher script linked to earlier in this thread. https://github.com/PimDeWitte/UnityMainThreadDispatcher
    (missed it earlier, sorry!)

    Sorted now!

    ---





     
    Last edited: Jul 18, 2020
    malabari likes this.
  7. AgaDeoN

    AgaDeoN

    Joined:
    May 19, 2020
    Posts:
    9
    Hi. I faced a similar problem.

    I have a canvas with UIHandler.cs script attached which is listening for some data changes via simple Event.
    Script has a link to TextMeshProUGUI component set through the inspector.

    I tried to change the text both via .text property and SetText() method, but neither works. SetActive(false/true) and ForceMeshUpdate(true) don't work either. The thing is I see new text in the inspector but not on the screen and the changes appear on the screen only if I click something in the "TextMeshPro - Text (UI)" component in the inspector.

    And some code...

    Code (CSharp):
    1. public class UIHandler : MonoBehaviour {
    2.     [SerializeField] private TMPro.TextMeshProUGUI textComponent;
    3.     [SerializeField] private DataSource dataSource;
    4.  
    5.     void Awake() {
    6.         dataSource.onDataChange += dataChangeHandler;
    7.     }
    8.  
    9.     private void dataChangeHandler(string newTextData) {
    10.         textComponent.SetText(newTextData);
    11.         // textComponent.text = newTextData;
    12.     }
    13. }
    TextMeshPro version is 2.1.1 (was trying also with 2.0.1 installed by default).
     
  8. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Can you provide me with a project, scene that will enable me to reproduce this behavior or submit a bug report with the project and steps to allow me to reproduce this?

    This should be trivial to resolve but I need to be able to reproduce it.
     
  9. AgaDeoN

    AgaDeoN

    Joined:
    May 19, 2020
    Posts:
    9
    Thank you for your reply.

    I'm using the unity socket.io package with a node.js socket-server so, unfortunately, it is not so easy to share.

    I've found that if I just use a regular event system, the text updates as intended. But if I try to listen to the socket.io event, that doesn't.

    As far as I can see it in the socket.io package code, the event should be triggered in the main thread, but it seems like i'm missing something. So I've tried the UnityMainThreadDispatcher and it solved the problem.
     
  10. Magasenakwa

    Magasenakwa

    Joined:
    Oct 13, 2018
    Posts:
    91
    I just ran into the same problem but I think I might be able to point ppl in the right direction as to WHY this is happening (especially that guy who asked "Why does putting it in Update() fix the problem").

    I had this problem a few years ago which is why it took me a while to remember the solution and also why I think I might HAVE the solution. It seems that enabling the TMP text in the same frame that the text is being set causes it to not display even though the .text value now contains the correct value.

    Ppl who suggest calling SetActive(false) and then SetActive(true) and having THAT work for them, that surprises me. My solution way back then (an what I am about to go implement again now is something like this):
    Code (csharp):
    1. IEnumerator SetText(TextMeshProUGUI obj, string value) {
    2. obj.text = value;
    3. yield return null;
    4. obj.gameObject.SetActive(true);
    5. }
     
  11. Magasenakwa

    Magasenakwa

    Joined:
    Oct 13, 2018
    Posts:
    91
    I managed to get the text to show, finally, after about 9 days of trying...
    Code (csharp):
    1.  
    2.       IEnumerator SetText(TextMeshProUGUI obj, string value)
    3.         {
    4.             obj.gameObject.SetActive(false);
    5.             obj.text = value;
    6.             yield return new WaitForEndOfFrame();
    7.             obj.gameObject.SetActive(true);
    8.         }
    9.  
    10.         void ShowText(TextMeshProUGUI tmptext, int value, float posx, float posy)
    11.         {
    12.             //TODO: Find a way to make text actually SHOW on screen
    13.             tmptext.text = $"Value: {value}";
    14.             tmptext.rectTransform.anchoredPosition = new Vector2(posx, posy));
    15.             tmptext.gameObject.SetActive(true);
    16.             tmptext.SetAllDirty();
    17.             tmptext.ForceMeshUpdate(true);
    18.             tmptext.gameObject.SetActive(false);
    19.             tmptext.gameObject.SetActive(true);
    20.  
    21.             //if that still doesn't work...
    22.             StartCoroutine(SetText(tmptext, tmptext.text));
    23.         }
    24.  
    Victory!!!!
     
  12. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    304
    This started happening in my project after updating from 2018.4 --> 2019.4 and updating TMP to 2.1.3. However, this only happens in builds - I can't make it happen in the editor. I also can't make it happen in a separate project so something with the complexity of my project is influencing the issue in some way.

    I tried many of the workarounds here but none worked consistently for me. I also tried all of the following methods for nullifying text and none worked:
    Code (CSharp):
    1. // NONE of these worked in the build (they work fine in the editor)
    2. TMP.text = string.Empty;
    3. TMP.text = "";
    4. TMP.text = " ";
    5. TMP.SetText(string.Empty);
    6. TMP.SetText("");
    7. TMP.SetText(" ");
    Using the override of TMP.SetText(char[]) I was able to get it to work as long as the array had something in it. Passing an empty char[] array did NOT work. What worked was:
    Code (CSharp):
    1. // DOES NOT WORK
    2. var arr = "".ToCharArray();
    3. TMP.SetText(arr);
    4.  
    5. // WORKS
    6. var arr = " ".ToCharArray();
    7. TMP.SetText(arr);
    Hopefully that helps in some fashion!
     
  13. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Long shot but see if making the following change makes any difference.

     
  14. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    304
    Doesn't seem to have done the trick. I'll stick with the single space nullifier via SetText(char[]) for now as that appears to be working. But let me know if there's anything else You'd like me to try (might take me a day or so to swing back around to it)
     
  15. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Can you provide me with a sample scene / project to test the above. I am making changes to SetText and the likes so while at it, I may as well see if I can track this issue down and kill two birds with one stone.
     
  16. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    304
    I tried to repro the issue in a separate project but so far have been unsuccessful :(. My current project is over 100gb and involves a networked client/server etc so it's not easy to separate out.
     
  17. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Any chance that when you are trying to update the text you are not on the main thread?
     
  18. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    304
    I don't think so. The assignment (that triggers this whole thing) is running from a MonoBehaviour Update loop; I am basically I'm checking for a rewired input event in the update loop which in turn triggers populating text from the target the player selected at the same time as showing the window via changing the alpha on a canvas group. I have optimized the text assignment so that it only happens once and doesn't do the assignment again until the value changes.
     
  19. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Is it just the assignment to string.Empty; or "" or null that doesn't work? Ie. if you were to set the text to "A" does that always work?

    Just trying to narrow this down.
     
  20. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    304
    Just tried setting the fields to "A" and it still occurred.
     
  21. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Can you set a break point in the OnPreRenderCanvas() to see if it gets called and then whether it ends up calling
    GenerateTextMesh() after you set the text?

    If it does end up calling GenerateTextMesh() see if it makes it into Phase III which is where the geometry is uploaded or if it returns out of that earlier.

    Assuming your are using the Canvas system, these functions are in the TMPro_UGUI_Private.cs file.
     
  22. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    304
    It's a little rough given that this is getting called a bunch, but after setting a conditional break point based on my targeting system it does appear to be hitting GenerateTextMesh().
     
  23. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Does it get all the way thru the Phase III where the geometry is uploaded?
     
  24. mons00n

    mons00n

    Joined:
    Sep 18, 2013
    Posts:
    304
    I did a little more digging today and it turns out I was muddying my own water due to my nameplates having a number of TMP objects and my break points were triggering on the wrong one. I was able to repro the issue in a separate project by the following steps in a built client (I'm doing it via UI buttons):
    1. set text via TMP.SetText(char[]). [text shows fine here]
    2. nullify text via TMP.text = string.Empty. [text properly nullifies and no longer shows]
    3. set text again via TMP.SetText(char[]). [text shows fine here]
    4. nullify text via TMP.text = string.Empty. [nothing happens, previous text remains]
    Again as a reminder - I can only get this to happen in a built client - it works fine in the editor. @Stephan_B I am PM'ing you a link to the repro script/scene.
     
  25. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Thank you for providing the repro scene and script.

    This has enabled me to identify the source of the issue and to fix it as well. The fix will be included in the next release of the TMP package which I am in the process of finalizing.

    In terms of the source of the issue, it is due to using a mixture of methods to set the text resulting in the following:

    • Text is set using a char array
      • In the Editor and to keep the Inspector Text Input Box in sync with this newly set text, the char[] is copied to the text property backing field. This is only done in the Editor to avoid runtime allocations.
    • Text is set to null using the text property
      • Text property backing field is different than previous invocation and not null so we process the text.
    In the Editor and as a result of the text backing field remaining in sync with the char[], everything works. But at runtime, the text backing field is not updated when SetText is used where the text backing field (after the first null or string.Empty is used, remains always null / empty which causes an early exist hence the lack of update.

    In the next release of the TMP package, I have re-worked (not specific to this issue) the whole text setting handling as more and more users have been using a mixture of methods to set the text. In some cases, users will set the text using SetText and then check the text property for the content which outside of the editor would result in similar / out of sync issues.

    In the new implementation, there is a new internal backing string buffer (needed for improve input field stuff btw) where regardless of the text input method, results in this backing buffer being used. As such, I added a new getter on the text property where it tracks if the text backing string is out of sync and if so and only then does it update at runtime the backing string.

    When using SetText to change the text and then using the text property to check the text, allocations are unavoidable as we need to convert the internal SetText content to a string but these allocation only occur when getting the .text.

    This change will ensure everything behaves as expected in and out of the Editor while providing the ability to use any SetText method and still be able to access the text property. This has also resulted in cleaning up several internal methods related to parsing of the input text where everything now gets converted to the internal text backing buffer for parsing.

    Anyway... long explanation to say thank you for providing me with the test scene and script and I have resolved the issue and was able to test it using the revised implementation :)
     
    travlake and mons00n like this.
  26. Gangsta-Geek

    Gangsta-Geek

    Joined:
    Aug 11, 2012
    Posts:
    32
    This helped me out. Thank you very much for this
     
  27. HerbherthK

    HerbherthK

    Joined:
    Mar 13, 2015
    Posts:
    1
    I was having this problem (I'm using the version 2.1.1) and what fixed it is put the code in another object and don't call it with GetComponent<> but set it as a public/serializefield variable and set in the inspector.

    Just posting in case someone is having this issue yet and haven't found how to fix.
     
  28. fnavarrensis

    fnavarrensis

    Joined:
    Aug 1, 2020
    Posts:
    9
    Super Late on the topic, but if anyone still having trouble with this:

    For some reason my TMP was working on first load but after reloading scene it wasn't (I would get better results via TMP.text = "whatever" rather than TMP.setText("Whatever")). Anyways, first discover that if instead of modifying text just one I put it on FixedUpdate, it would work, but ofc this is super wasteful.

    Solution? I turned my function that Updated the TMP into a Coroutine, with tiny .01f delay before updating the TMP. This was enough to get it working.

    I hope this helps anyone, one of my firsts posts in this awesome community of Gamedevs :)

    Cheers!
     
  29. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Can any of you provide a simple repro project for me to look at? I am curious to figure out why the text would not be updating as it should.
     
  30. franMx

    franMx

    Joined:
    May 27, 2013
    Posts:
    30
    Hello, on instancing a prefab that has Input Fields, I can't set the Text. Funny thing is that placeholder text can be updated and rendered correctly.

    Tried:
    Code (CSharp):
    1.        
    2.         textobj = loi.transform.GetChild(3).GetChild(0).GetChild(2).gameObject;
    3.         if (textobj != null)
    4.         {
    5.             textobj.gameObject.SetActive(false);
    6.             Debug.Log("found Alias "+alias);
    7.             textobj.GetComponent<TextMeshProUGUI>().text = alias;
    8.             textobj.GetComponent<TextMeshProUGUI>().ForceMeshUpdate(true);
    9.             textobj.gameObject.SetActive(true);
    10.         }
    If needed, I think I can send a scene, just let me know how to send it privately.
     
  31. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    You can send me a private message with repro project or simply submit a bug report with project and then provide me with the Case # once you have it.
     
    franMx likes this.
  32. franMx

    franMx

    Joined:
    May 27, 2013
    Posts:
    30
    Hello Stephan, just to confirm if you received project (sent on pm). Regards.
     
  33. franMx

    franMx

    Joined:
    May 27, 2013
    Posts:
    30
    Hi @Stephan_B, hope you're doing great. Not to nag you, were you able to have a look on the files? Regards.
     
  34. Sharikoff

    Sharikoff

    Joined:
    Jan 29, 2018
    Posts:
    2
    Had a similar issue with TextMeshProUGUI.text updating in editor but drawing new values over the old ones in the play view (and in build). Found out that the issue was in trying to render text elements outside of camera field of view - my camera is 4:3 while the game renders to 16:9 with black bars on both sides. Apparently that doesn't work, text renders ok when positioned within camera view though. Gonna look for workaround to rendering UI elements on the sides of 4:3 main game view.
     
  35. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Any chance you could provide a simple repro project or scene for me to look at? I am curious to see why this might be happening.
     
  36. ltomov

    ltomov

    Joined:
    Aug 3, 2017
    Posts:
    96
    I had the same problem and in my case it turned out to be because I had mistakenly added two TMPPro_Text instances on the gameobject. Removing the second instance fixed it.
     
    StarArcher likes this.
  37. StarArcher

    StarArcher

    Joined:
    May 23, 2020
    Posts:
    12
    I appreciate that you posted this because I'd spent about 1.5 days chasing this bug down and it turned out I had the same problem as you. I wouldn't have even thought of looking in this direction if it wasn't for your comment. Thank you!!
     
    ltomov likes this.
  38. danhayesgamer

    danhayesgamer

    Joined:
    Nov 17, 2013
    Posts:
    6
    This is an old post, but people are still talking about it so I may have a fix. If you're using SetText or doing stuff with char arrays anywhere, check that none of your chars are set to /0. This can happen if you do something like CharArray[0] = (char)0;
     
  39. danhayesgamer

    danhayesgamer

    Joined:
    Nov 17, 2013
    Posts:
    6
    Perhaps textmeshpro could log a warning when null chars are passed in, rather than not showing
     
  40. danhayesgamer

    danhayesgamer

    Joined:
    Nov 17, 2013
    Posts:
    6
    I should post a solution really, but instead of casting chars or strings, I use System.Convert.ToChar and that seems to fix it for numerical values at least, so no more hex values being passed in because of casting
     
  41. MickyX

    MickyX

    Joined:
    Dec 4, 2016
    Posts:
    2
    Not sure if this will help anyone, but I was having this same issue when setting the text via .text = it would not refresh

    I use a number of TextMeshProGUI to display inventory information, when the player was finished with the inventory I cleared the text so the next time the player opened the inventory there was no item information displayed.

    I had a clear text function which called

    Code (CSharp):
    1.  itemName.text = "";
    2. itemDescription.text = "";
    3. cashValue.text = "";
    Then when an inventory item was selected it would not display until the gameobject was turned on or off

    as soon as I changed the code to include a space it worked as expected and the next time an item was selected it instantly refreshed

    Code (CSharp):
    1.  itemName.text = " ";
    2. itemDescription.text = " ";
    3. cashValue.text = " ";
     
  42. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    What version of the TMP package are you using?

    I believe I revised this behavior a while back so just curious.
     
  43. Pytez

    Pytez

    Joined:
    Mar 23, 2022
    Posts:
    3
    Just use normal text not TMP that worked for me
     
  44. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    normal text is considered legacy and no longer on active development. As such, unless you already have an existing project using UI text, you should be using TMP.

    If anyone runs into issues in TMP, then please keep reporting those so we can address them.
     
  45. Saillot

    Saillot

    Joined:
    Jan 31, 2017
    Posts:
    5
    this bug occurs because CanvasUpdate is not working properly!
     
  46. MickyX

    MickyX

    Joined:
    Dec 4, 2016
    Posts:
    2

    Using TextMeshPro 3.0.6 - all other versions say [Preview]
    Unity 2020.3.30f1
     
  47. aloshon

    aloshon

    Joined:
    Aug 8, 2022
    Posts:
    1
    I don't know if anyone is still struggling with the script not updating the TMPro text, but for me the issue was my width was 0 until I clicked something on the script
     
  48. malabari

    malabari

    Joined:
    May 21, 2022
    Posts:
    1
    Thank you so much, this worked!
     
  49. Rubiix

    Rubiix

    Joined:
    Nov 20, 2019
    Posts:
    4
    Hello all,

    Bit of an older thread but still seeing the same issues, hopefully I'm doing something silly...

    I had a project updating UI text with the below which worked fine. I was retrieving the TextMeshPro - Text (UI) component by assigning it prior to runtime, the text updated and life was good.

    Code (CSharp):
    1. public TMP_Text AllyCoinText;
    2.  
    3. private void Awake()
    4. {
    5.         AllyCoinText.text = "0";
    6. }
    7.  
    8. public void AddCoin(int amount, bool ally)
    9. {
    10.     AllyCoinAmt = AllyCoinAmt + amount;
    11.     AllyCoinText.text = AllyCoinAmt.ToString();
    12. }

    After making some structural changes, the gameobject that needs to do this update is a prefab and so is the parent canvas so I have to rely on grabbing the TextMeshPro - Text (UI) component dynamically, the rest of the code is essentially the same.

    Code (CSharp):
    1. coinBank.humanCoinText = mainCanvas.gameObject.transform.Find("Coin").Find("AllyCoinUI").gameObject.GetComponent<TMP_Text>();
    2.  
    3. public void AddCoin(int amount)
    4.     {
    5.         CoinAmt += amount;
    6.  
    7.         if (gameObject.name.Contains("Human"))
    8.         {
    9.             humanCoinText.text = CoinAmt.ToString();
    10.         }
    11.     }

    This works in the editor, I have the component, I can update the TMPro.Text field and can see this in the editor, the issue is I cannot see this in the Unity GUI of Text Mesh nor does this update on the canvas. As soon as I stop the game running then the UI updates on the game to the value that I can see in the editor.

    Things I've tried...

    - Setting the TMP_Text element to not active and back to active to refresh it
    - Using forcemesh to update it
    - Adding a variable holder to the parent canvas and attaching the TMPro component so I can be sure this is the correct component

    I've also tried all of these with TextMeshProUGUI instead of (the more generic?) TMP_Text

    Any help would be appreciated, thanks

    EDIT: Unity 2020.3.24f1, TMP 3.0.6 (Both working and not working versions of my projects)
     
    Last edited: Dec 22, 2022
  50. Rubiix

    Rubiix

    Joined:
    Nov 20, 2019
    Posts:
    4