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.
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).
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?
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.
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.
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:
Hello! The fact that the whole UIDocument gets recreated on disable/re-enable is as designed because of Live Reload (more info here: Feeback wanted : UI assets Live Reload )
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!
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.
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.
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.
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.
public int movesLabelValue=5;
public Label movesLabel;
private void OnEnable()
{
var rootVisualElement = GetComponent<UIDocument>().rootVisualElement;
movesLabel = rootVisualElement.Q<Label>("movesLabel");
movesLabel.text= movesLabelValue.ToString(); //makes Ui movesLabel 5, that's ok.
}
public void DecreaseMoveValue()
{
movesLabelValue= movesLabelValue-1;
print("moves value2: "+movesLabelValue); // movesLabelValue decreases, that's ok.
movesLabel.text=movesLabelValue.ToString(); //doesnt update the Ui with new movesLabelValue value!
}
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?
@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?
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!
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.
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.
@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
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.