Search Unity

  1. Welcome to the Unity Forums! Please take the time to read our Code of Conduct to familiarize yourself with the forum rules and how to post constructively.
  2. Dismiss Notice

Question Label text does not change when text parameter is modified by a script

Discussion in 'UI Toolkit' started by Roshinator, Oct 9, 2020.

  1. Roshinator

    Roshinator

    Joined:
    Feb 2, 2019
    Posts:
    13
    I have a pause menu with a title label that displays who paused the game. There is some placeholder text that my script replaces like so where "playerNameText" is the title label and the "canvas" is the UIDocument. component.

    playerNameText.text = playerName + " Paused";
    canvas.enabled = true;


    I used a debugger to step through and what I found is that after the text is changed, the text property of the label remains on what I set it to, but the actual visible label does not update in game. I have other UI that uses labels that have their text changed this way and it works fine. None of my buttons in this UI trigger any code either despite having clicked actions bound in the start function (lines are executed as confirmed by the debugger).
     
  2. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    515
    Hi,

    If you use the UIToolkit debugger (window-> UiToolkit -> debugger) and that you select the element (You cannont "pick" runtime element for now, you will need to select the PanelSetting name in the top left dropdown and explore your hierarchy manually), do you see the updated text or the placeholder? Normally both should be in sync and if they don't, please let me know because it would be a bug.

    I think it may be a question of timing and you may explore the following to get a workaround:
    • Can you change "playerNameText.text" at the same time you change the other labels that are working?
    • Can you change the other labels text at the place where you change the playerNameText?
    • Can you enable the canvas before you change the text and see if there is a difference?

    Let me know once you have any results.
     
  3. Roshinator

    Roshinator

    Joined:
    Feb 2, 2019
    Posts:
    13
    I checked the debugger and the text was not being changed. I have tried before and after enabling the canvas and the result is the same. I will continue to investigate the timing thing, but this seems to happen specifically when enabling the ui document at the same time as changing the text. If I enable/disable the whole gameobject and leave the UI document component enabled it seems to work fine, as that is how my main menu works. The same thing seems to be true with the buttons where disabling the UI document component seems to mess with the button actions, they work fine when the whole gameobject starts disabled and is enabled though.
     
  4. Roshinator

    Roshinator

    Joined:
    Feb 2, 2019
    Posts:
    13
    I did a bit more investigation with other UI I have, and I found that if the UI Document component itself gets disabled at any point during runtime, even if its through the gameobject (gameObject.SetActive), it malfunctions and stops registering any changes I make in code when reenabled. I have Mirror for networking and when an object I had went through a network switch (disables and reenables the gameobject in the same or next frame), the UI on that gameobject stopped registering changes (not shown in the UI toolkit debugger either), though print statements & vscode debugger show the statements are going through in code.
     
  5. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    515
    Thanks for the investigation.

    It really looks like there is a problem if disabling-enabling the game object changes break the internal cache.

    Can you file a bug for this? Having clear reproduction step or an example project will help the team fix it quickly.
     
  6. Roshinator

    Roshinator

    Joined:
    Feb 2, 2019
    Posts:
    13
    Am I supposed to submit it through Help -> report a bug in editor?
     
  7. broots

    broots

    Joined:
    Dec 20, 2019
    Posts:
    54
    I encountered the same issue (for renaming an object field) and found a cheaty workaround that might work in your case as well where you set the object as null and then reassign it:

    Code (CSharp):
    1.            
    2. charSelector.value = null;
    3. charSelector.value = currentCharacter;
    4.  
     
  8. SimonDufour

    SimonDufour

    Unity Technologies

    Joined:
    Jun 30, 2020
    Posts:
    515
    Yes :) Let me know if you need help with this.
     
  9. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    Hello! The fact that the whole UIDocument gets recreated on disable/re-enable is as designed because of Live Reload (more info here: https://forum.unity.com/threads/feeback-wanted-ui-assets-live-reload.963129/)
    Doesn't mean it has to stay that way, but it's not exactly a bug as it is right now.
    The recommended flow is that you set your values with a companion MonoBehaviour to your UIDocument, and use its OnEnable method to do so. You can access the root element from the UIDocument there.
    Can you try this and let us know if this works for you? Or what is the alternative flow you wish to use?
    Thanks!
     
  10. Roshinator

    Roshinator

    Joined:
    Feb 2, 2019
    Posts:
    13
    I have a companion script on the same gameobject as a ui document which serves as a sort of UI controller. I want to be able to turn the UI on and off without disabling the gameobject because I need the script to remain active. If this is not a bug, then recreating the UI document should at least delete the old objects and throw a nullreference when I try to operate on them, because right now no errors are thrown. As for workflow, I think it should be made more clear that you need to rebuild your c# references every time you reenable the UI Document. Ideally we should be able to turn the UIDocument on and off without having problems like UGUI and the canvas component. I have found a workaround for now which is setting the root visual element's visibility to false to give the same effect.
     
    Snoozed and Plaximo like this.
  11. martymayfly

    martymayfly

    Joined:
    Mar 4, 2021
    Posts:
    8
    Hello, I need help about new ui.
    I cant change ui element's label.text from another function, value is changing but ui is not changing. Do you know a solution for that?
    It gets the first value from onEnable, but after that my function cant change that ui text value.
     
  12. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    I'd recommend you open a new topic for visibility, but even if you decide to continue in this thread, can you share the contents of your UXML and code? From what you're describing it's hard for us to suggest anything.
     
  13. martymayfly

    martymayfly

    Joined:
    Mar 4, 2021
    Posts:
    8
    Hello @JuliaP_Unity

    I call DecreaseMoveValue() function and line 14 prints the right value but line15 doesnt update ui and gives NullReferenceException: Object reference not set to an instance of an object exception.
    I am newbie, sorry if I am mistaken, thanks for your help.

    Code (CSharp):
    1. public int movesLabelValue=5;
    2. public Label movesLabel;
    3.  
    4. private void OnEnable()
    5.     {
    6.         var rootVisualElement = GetComponent<UIDocument>().rootVisualElement;
    7.         movesLabel = rootVisualElement.Q<Label>("movesLabel");
    8.         movesLabel.text= movesLabelValue.ToString(); //makes Ui movesLabel 5, that's ok.
    9. }
    10.  
    11. public void DecreaseMoveValue()
    12. {
    13.             movesLabelValue= movesLabelValue-1;
    14.             print("moves value2: "+movesLabelValue); // movesLabelValue decreases, that's ok.
    15.             movesLabel.text=movesLabelValue.ToString(); //doesnt update the Ui with new movesLabelValue value!
    16.  
    17.     }
    18.  
     
  14. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    Where is
    DecreaseMoveValue
    called?
     
  15. martymayfly

    martymayfly

    Joined:
    Mar 4, 2021
    Posts:
    8
    DecreaseMoveValue() is called from another class inside a function which is triggered when I swipe on screen, in that case, like I said before, line14 is working and swipe is detected (isnt it the proof for function call?), I am curious and want to know why line15 is not working and returning exception?
     
  16. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    @martymayfly from the information you're giving us here it does look like it should work, unless you're not using the same instance of the component that exists in the Scene and is placed with the UIDocument. How are you referencing that component in the other class?
     
  17. martymayfly

    martymayfly

    Joined:
    Mar 4, 2021
    Posts:
    8
    I'm referencing,
    MyClassName myClassName = new MyClassName();
    and then using as
    myClassName.DecreaseMoveValue();

    I am able to call DecreaseMoveValue() function with this reference. Is it weird?
     
  18. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    When you do this, you're creating a new instance, one that will probably not be able to find the UIDocument unless everything is under the same game object. I'm also surprised that line would even work because if I'm not mistaken MonoBehaviour classes cannot be instantiated like that. For reference, the way to add a new instance of a component would be to use the AddComponent call.

    However this is not what you want here, since you already have your MyClassName instance set up with the UIDocument, as you mentioned on the first comment with code that in line 8 it "makes Ui movesLabel 5, that's ok."

    It's not weird because after all it's all C# code so you'll be able to call the method. It's just not calling it in the instance you wanted it to be called, and you can see that because
    movesLabel
    is null (it gives gives "NullReferenceException: Object reference not set to an instance of an object").

    Now, how to fix it... there's a few options!
    1. If you need to keep the game objects separate (one that has UIDocument + MyClassName, a second one that has the code to call
      DecreaseMoveValue
      ), then find that game object somehow (through FindObjectsOfType you can find one with the component you're interested directly, or Find by name and you can then GetComponent from it). Once you have that instance of the MyClassName component, call
      DecreaseMoveValue
      from it.
    2. Store a reference to MyClassName in the component where you're trying to use it, and assign the reference in the scene. This is assuming the class where you call
      DecreaseMoveValue
      from is also a component (i.e. it extends MonoBehaviour).
    If this is not clear than I would suggest looking at some basic Unity tutorials because components/MonoBehaviours are the building blocks of Unity and you'll probably need to know your way around them to be able to progress with your code.

    Hope this helps!
     
  19. martymayfly

    martymayfly

    Joined:
    Mar 4, 2021
    Posts:
    8
    @JuliaP_Unity Referencing my script by using GetComponent solved this problem. I am also studying on tutorials but I was confused when I see method is working partially and tried wrong way :)

    Thank you very much for your help!
     
    JuliaP_Unity likes this.
  20. Noa3

    Noa3

    Joined:
    May 29, 2012
    Posts:
    84
    I want to say that the problem is still peristing, if you Turn the gameobject off and then activate it again, the values for the elements cant be reflected on the gamescreen.