Search Unity

TMP_Text.SetText cannot read .text in device build in TextMeshPro 2.0.1

Discussion in 'UGUI & TextMesh Pro' started by yuewahchan, Feb 27, 2020.

  1. yuewahchan

    yuewahchan

    Joined:
    Jul 2, 2012
    Posts:
    309
    Code (CSharp):
    1.  
    2. [ICODE][/ICODE]textMesh.SetText("hello");
    3. Debug.Log(textMesh.text);

    In Device build, it doesn't print "hello", but In Editor, it print "hello"
     
  2. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Since the text property is a string, copying of the content passed to the SetText() function requires the use of the string.ToString() function which results in allocations.

    As such this only happens in the Editor to keep these properties in sync.

    Given the above, I could add an option overload to the SetText function to control this behavior. But keep in mind, this would then result in allocations at runtime.
     
  3. Gladyon

    Gladyon

    Joined:
    Sep 10, 2015
    Posts:
    389
    There are 2 ways to solve that problem (by modifying TextMeshPro's source code):

    1. Always have '.text' updated
    But not when 'SetText()' is called, only when 'text' is accessed and not up-to-date.
    In order to do that, you just need a bool (let's call it '_isTextUpToDate'), and when 'SetText()' (or another method modifying the content of the text) is called, then you set '_isTextUpToDate' to 'false'.
    The 'text' property will check '_isTextUpToDate', and if it's 'false', then it will do the GC-generating 'ToString()', and set '_isTextUpToDate' to 'true'.

    That way, you have no GC generated, except when you access '.text' (and even there, it will happen only if it's a new text).
    The result is that the behaviour is the expected one, and people who do not want GC can avoid it by avoiding to use '.text'.
    It is, in my opinion, a lot better than having the current broken behaviour (which will undoubtly generate the bug reports now and then for many many years).


    2. Having a GC-free access to the text
    Here, the solution is not to make '.text' GC-free, as it's not possible.
    The idea is to provide a way to access the text under the form of a StringBuilder.
    Just add the method 'void GetText(StringBuilder outText)'
    That method will just clear 'outText' and then fill it with the content of the internal array containing the actual text.
    That way, it is GC-free as long as the user re-use the StringBuilder, but that is his responsibility, not TextMeshPro's.


    Of course, both methods can be implemented at the same time, as they do not do the same thing and are both interesting.
     
    CPlusSharp22 likes this.
  4. yuewahchan

    yuewahchan

    Joined:
    Jul 2, 2012
    Posts:
    309
    As I am using the TextMeshPro 2.0.1 in Unity Package, Is the new SetText function overload be added to 2.0.2 or next release ?
     
    Faimen likes this.
  5. 00jknight

    00jknight

    Joined:
    Mar 28, 2014
    Posts:
    34
    This is unexpected behavior that is insufficiently documented. Just lost several hours due to this. The function should be named differently. SetX is commonly just a simple setter. If people really want to try to optimize setting of a string, they can and should look into the documentation. People shouldnt need to read the documentation to simply call a setter. Also, making it differ between Editor and Player caused my team to dig in to all kinds of red herrings. Just massively bizarre.

    Glad to hear it's being fixed. The documentation really let me down here though. There is no explanation of the bool overload "sync input field". That should be explained. It should probably be explained in the comments in the file when you command+click to the function definition.
     
    Last edited: Dec 11, 2020
  6. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Sorry about the confusion. When I have time, I do plan on updating these SetText functions along with proper documentation.