Search Unity

  1. Megacity Metro Demo now available. Download now.
    Dismiss Notice
  2. Unity support for visionOS is now available. Learn more in our blog post.
    Dismiss Notice

TextMesh Pro Null Reference Exception with Empty String

Discussion in 'UGUI & TextMesh Pro' started by John-B, Mar 16, 2018.

  1. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    TextMesh Pro returns a null reference exception error if I try to reference text that's empty. I get the error even if I try to get the text.length. Unity UI text does not generate such an error, as I discovered when I switched my project over to TMP. Unity text correctly returns an empty string or length of zero. Is there any way to prevent this crash, make TMP behave like Unity text, other than to always make sure TMP text always contains at least one character?

    I don't know if this is something different or I never noticed before, but if I define a String variable and don't assign it a value, it returns a null reference error if I try to get its length.
     
    Last edited: Mar 16, 2018
  2. nygren

    nygren

    Joined:
    Feb 13, 2014
    Posts:
    33
    It doesn't sound like your TextMeshPro.text is empty, it sounds like it's null. TextMeshPro.text is a simple string property and just like your variable example, if it's null you can't access members such as length on it. If it's an empty string length will work - it's regular C# and not anything TextMesh Pro controls.

    Assigning String.Empty to your TextMeshPro.text or checking if it has contents with String.IsNullOrEmpty(myTextMeshProString.text) might help you out.
     
  3. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    As @nygren stated, if you assign null to a string and then try to check the length of this string, you will get en error.

    Code (csharp):
    1. string text = null;
    2. Debug.Log(text.Length); // This will result in an error since the string is null.
    3.        
    4. text = string.Empty;
    5. Debug.Log(text.Length); // This will return 0 since the string is empty as opposed to null.
    If your intent is to clear or "empty" then text then I suggest you use string.Empty.
     
  4. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    This happens when I don't assign a string to a TMP object. The program starts with nothing in the field (as shown in the Inspector), then gives the error if I try to access the text before putting a string in the field.

    I have code that saves the current contents of a text field before changing it, then restores the original contents later. With Unity text, this wasn't a problem, it returns an empty string or length of zero if there's nothing in the the field. When I switched this project over to TMP, it started crashing. So now I have to make sure that TMP text objects always start with something in them, and make sure they're never empty. It's not a serious problem, just TMP behavior that is not the same as regular Unity UI text.
     
  5. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    I can certainly make the change where a new text object has string.Empty assigned by default.

    Just to make sure I don't overlook anything. Can you provide an example of how you were ending up with this? Were you creating text object via scripts?
     
  6. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    I don't know what's going on, but now I can't reproduce the problem. I can only get the null reference error now if I assign an unassigned string to the text object:

    var tt: String;
    infoText.text = tt;
    print(infoText.text); // returns Null, no error
    print(infoText.text.length); // null reference error

    And now I'm only getting an error when I access the string's length. Previously, I was also getting an error when I accessed the string itself. I'm not sure what I was doing to get the original error, but I didn't start looking at the string length until I started tracking down the error just trying to get the text.
     
    Last edited: Mar 19, 2018
  7. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    Another odd, intermittent problem I've run into after switching a project from Unity UI text to TMP text is with disappearing button text. The attached screen capture shows two buttons in a pop-up dialog panel, the top half shows the Scene view, the bottom half shows the game view. I'm not sure how this is even possible, how the text can be visible in the Scene view but not in the Game view.

    I haven't spent too much time trying to track this down yet. I thought it might have something to do with setting the text's alpha (when enabling/disabling the button) while the panel is inactive, but I don't think that's it. This doesn't happen every time the panel is shown, sometimes I have to open and close the panel MANY times to get it to happen, which is why it took me a while to discover the problem. But once the button text disappears, it happens every time the panel is shown after that, even if I stop and restart the game. Once the text disappears, I have to quit and restart Unity to make it come back. I never saw this before I switched the button text to TMP.

    I'm not sure how to figure this one out, as I have no idea what could cause the text to be invisible only in the Game view. I never do anything to the buttons, other than reducing the texts' alpha when they're disabled. The buttons/text are never made inactive, only their panel parent.

    I just noticed some more text disappearing. This is text that's in another panel. When I open a completely different panel, all the text in this panel disappears. Opening the one panel has nothing to do with the text in the other panel that disappears.
    Button-Problem.jpg
     
    Last edited: Mar 26, 2018
  8. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Are you changing the Alpha of the vertex color which is unique per text object or changing the Alpha of the FaceColor on the Material which is potentially shared by many text objects?

    Are you doing anything with scaling of the text objects or their parents? If so make sure the scale of the X, Y, Z of the text objects are uniform.

    Are you using a mixture of text objects in world space and some others in Overlay or Camera space?

    What version of Unity are you running?
     
  9. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    I got a chance to look into this, and I have no idea what's going on.

    I tracked down the cause of the disappearing text to instantiating one of 4 gameObjects, out of many. There's no difference code-wise between the objects that cause the problem and those that don't. No errors are generated, and everything is initialized properly. That is the one and only line that when commented out fixes the problem. The strange part is, once I instantiate one of those gameObjects and the button text disappears, all text seems to be broken after that, even after I Stop and Play again. When I hit Play after that, any time a panel is shown, it causes text in other visible panels to disappear. If I change something in the code, and then Play, it seems to reset things, but otherwise I have to quit and restart Unity to get back to the point where only the button text disappears. When I say "disappear," I mean only in the Game view, the text is still visible in the Scene view.

    To answer your questions:

    I only change the color. Below is the code I use to enable/disable buttons. It's the same code I used with Unity UI text, I just changed the component to TMP. I still see the problem even if I comment out all but the first line of that function.

    Code (JavaScript):
    1. function SetButtonInteractable(theButton: UnityEngine.UI.Button, isEnabled: boolean) {
    2.  
    3.     theButton.interactable = isEnabled;
    4.     if (theButton.GetComponentInChildren(TextMeshProUGUI)) {
    5.         var tColor = theButton.GetComponentInChildren(TextMeshProUGUI).color;
    6.         if (isEnabled)
    7.             tColor.a = 1.0;
    8.         else
    9.             tColor.a = 0.3;
    10.         theButton.GetComponentInChildren(TextMeshProUGUI).color = tColor;
    11.     }
    12. }
    If it is a color/alpha issue, wouldn't you see the same thing in the Game and Scene views?

    I'm not scaling any text objects. Other than changing alpha, I'm not doing anything to the text except changing the strings. I'm only changing the alpha on some button text, the other disappearing text never has its alpha changed.

    I'm using Unity 2017.3.1f1.
     
    Last edited: Mar 28, 2018
  10. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    First I would look for a way to cache a reference to those text components instead of using GetComponentInChildren<TMP_Text>(); which is not ideal from a performance standpoint.

    Second, I suspect the issue might be related to the use of GetComponentInChildren<TMP_Text>(); which only returns the component if it is active. I am only guessing here since I don't know your exact setup and how you end up calling this function.

    I would suggest stepping through that portion or your code to make sure it does in fact tries to set the color on the correct text component.
     
    arialblack14 likes this.
  11. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    I've spent a lot more time on this, and still have no idea what the cause of the problem is.

    It looks like it has nothing to do with changing the text's alpha. I've taken out every reference to text alpha, and still the disappearing text. I've taken out everything, all code that is executed from the button click that instantiates the object and opens the panel to the panel showing, with no effect. The only line I delete that fixes the invisible text is the line that instantiates the object.

    Code-wise, there's nothing different between instantiating objects that cause the problem and those that don't. Removing the initialization code does nothing. The only difference I can find is that the objects that cause the problem contain a TMP child object (shows the object's ID number), others don't. When those objects are initialized, the TMP object's strings get changed, but nothing else, no color change.

    I don't think there's an issue with GetComponentsInChildren. The text objects are never inactive, and it skips setting the alpha if nothing is returned (like for buttons that don't have a text child). This function is only called occasionally, to enable/disable buttons when a panel opens, so it's not a big performance issue.

    The last thing I've tried is switching the text back to Unity UI text just for one set of buttons. Problem solved. Since I don't really need any of TMP's special features, I was mainly trying to improve performance, I'm thinking I should cut my losses and switch back to Unity text. I didn't see a difference in batches/setPass calls switching to TMP, though the higher resolution is nice.
     
  12. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    The issue is likely a simple thing. Just submit a bug report with the project. Make sure you list the Case # here and I'll take a look today and tell you what the issue was.
     
  13. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    It's a pretty big project, and I doubt I could strip things out or reproduce it in a simple demo project. The time it will take me to switch the UI back to Unity text will be a lot less than the time I've already spent trying to track this problem down.

    One other thing I looked at was the Frame Debugger. I thought the TMP text might just not be updating every frame, which would explain why it's invisible in the Game but not the Scene view. But there's no difference when the text is visible or invisible. _mainTex for TMP text shows <none>. Is that correct? _MainTex for Unity text shows FontTexture. Both show as a draw call in the Frame Debugger, even when the TMP text is invisible.
     
    Last edited: Mar 30, 2018
  14. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    _MainTex should reference the font atlas texture even if the vertex color / alpha is zero. This might be indicative of the source of the issue.

    Something is going on in your code implementation that is causing this behavior. I have tried to reproduce this and it works as expect whether I change the vertex color, faceColor, etc.

    When submitting a bug report, you can include the whole project. As long as you give me the steps to reproduce the behavior, it would likely take me about 5 minutes to know exactly why this is happening.
     
    Last edited: Mar 30, 2018
  15. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    TMP _mainTex always shows <none> in the Frame Debugger, whether the text is currently visible or invisible. Unity text references the font atlas.

    I'm trying to submit a bug report. This project has LOTS of unused assets, and it's taking quite a while to pack and upload the report. I'm not sure if it's ever going to finish. After about 90 minutes with the progress bar not moving, I canceled and started over, and it's been uploading now for about 20 minutes. If it ever finishes, I'll post the bug report number.
     
    Last edited: Apr 6, 2018
    Stephan_B likes this.
  16. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    That took WAY too long to upload. Case number 1023353.

    I don't think this has anything to do with setting the text color, as I thought at first. It still disappears if I remove all code that changes color or alpha.
     
    Last edited: Apr 8, 2018
  17. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    Have you had a chance to take a look?
     
  18. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Looking at it now.

    Update
    Thank you for providing the project for me to look at. Upon review, I noticed that you are using a mixture of normal <TextMeshPro> and <TextMeshProUGUI> objects which happen to share the same material.

    This is what I suspected as per my initial reply.
    Since the Canvas system supports different Render Modes, the Canvas system manages and sets the ZTest value of materials for the different Canvas Render Modes. If several objects happen to share the same material using different Canvases and Render Modes, Unity internally creates instances of these materials for the different ZTest modes needed.

    When using a mixture of TextMeshPro and TextMeshProUGUI objects which share the same material, we can end up with a situation as these objects require different ZTest settings. Since the Canvas system doesn't know about non Canvas related objects which might happen to be using the same material which is also true for the non Canvas objects / components like TextMeshPro, they end up fighting over this ZTest on those shared materials.

    The easiest way to manage this is to create and use different Material Presets for your objects in world space and those in overlay space. World space objects can share the same material presets while overlay objects can also share their material preset as well.
     
    Last edited: Apr 11, 2018
  19. John-B

    John-B

    Joined:
    Nov 14, 2009
    Posts:
    1,259
    Thanks. I didn't realize that was an issue, as it did not happen when I was using Unity text for UI and 3D text. When you asked that question, I guess I thought you were referring to having multiple canvases.

    So the problem has nothing to do with changing color/alpha, the problem is caused by using the same material for TMP and TMPUGUI objects, correct? That would probably also explain why the two text objects that use a different font were not affected.
     
    Last edited: Apr 12, 2018
  20. Stephan_B

    Stephan_B

    Joined:
    Feb 26, 2017
    Posts:
    6,595
    Correct. The problem is simply due to two systems (the Canvas system and Mesh Renderer) sort of fighting over the ZTest value on the material and changing it which messes up the other.

    Easy solution is to have a separate set of Material Presets for World Space and for the Canvas.