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

Can't add a UI element programatically

Discussion in 'UI Toolkit' started by igamol, Jan 19, 2021.

  1. igamol

    igamol

    Joined:
    Dec 9, 2018
    Posts:
    8
    I'm using the UIBuilder / UIToolkit to create game UI, not Editor stuff)

    Going fine using the UIBuilder uxml, and c# to manipulate.

    When I try to add an element dynamically in code with

    Code (CSharp):
    1.  
    2. ..
    3. VisualElement rootVisualElement = GetComponent<UIDocument>().rootVisualElement;
    4. VisualElement ve = rootVisualEleemnt.Q<VisualElement>("MyPanel");
    5. ..
    6. Label label = new Label("Add this in");
    7. label.style.width = 500
    8. label.style.display = DisplayStyle.Flex
    9. ve.Add(label);
    10. ..
    11.  
    When I run the code, the label does not appear, even though it reports as being a child within MyPanel. Also, when i iterate through the children using Children(), I can't help but notice the reported value of all children VisualElement styles is 'null' except for my nice new label. For example, the width of the panels reports ss 'null'. They are in fact very much not null on screen.

    What am I missing?
     
  2. DukeGrimm

    DukeGrimm

    Joined:
    Sep 29, 2012
    Posts:
    61
    Totally new, and came here to find out if programmatically adding buttons/windows was possible. Based on your symptoms the first thing I'd look around is a method to refresh the UI.
     
  3. igamol

    igamol

    Joined:
    Dec 9, 2018
    Posts:
    8
    there is a MakeDirty equivalent - I think I did try that.

    Right now I need to see worked example to see how this should work.
     
  4. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
  5. igamol

    igamol

    Joined:
    Dec 9, 2018
    Posts:
    8
    Thanks!

    May I ask for some clarification?

    - "use the UIDocument component on a game object"
    - "and assign the UXML file to it"

    If I could know what this means with respect to code, I could find it in that demo project
     
  6. igamol

    igamol

    Joined:
    Dec 9, 2018
    Posts:
    8
    Actually, I think you are answering a different question - you are answering how to connect UXML to your game; add the UIDocument in the Unity hierarchy, and within the UIDocument, point to your root UXML.

    I'm asking a different thing. Alongside using VisualElements defined within UXML, can I additionally create a (e.g.) VisualElement programmatically and add that to an instantiated VisualElement as I do in my example?
     
  7. JuliaP_Unity

    JuliaP_Unity

    Unity Technologies

    Joined:
    Mar 26, 2020
    Posts:
    666
    You can definitely add as many VisualElements programmatically as you wish, and the way they'll show up in the Game View is by using the UIDocument component. And I just realized I misread your initial post, sorry about that!

    What you're trying to do is indeed supposed to work. You should add this code on your OnEnable (or some other method called from OnEnable). If you're not seeing anything on screen it probably means some style setting is wrong. When are you trying to iterate on the children? I suggest making sure the layout is done before you try to check on any values, like if you register a callback for the GeometryChangedEvent for example.
     
    Landa-100 likes this.
  8. igamol

    igamol

    Joined:
    Dec 9, 2018
    Posts:
    8
    ah, ok - thanks. And that GeometryChangedEvent looks like a strong tip too thank you
     
  9. uMathieu

    uMathieu

    Unity Technologies

    Joined:
    Jun 6, 2017
    Posts:
    384
    The VisualElement style contains only inlined style value, ie, values set from c# code. To get the effective values computed from stylesheets and inlined styles combined, you need to look at VisualElement.resolvedStyle.

    Be aware that the values are computed asynchronously. Right after adding an element, the width or height values will contain NaN. You will need to wait 1 frame or register to GeometryChangedEvent to get notified when values are computed.
     
  10. igamol

    igamol

    Joined:
    Dec 9, 2018
    Posts:
    8
    Perfect answer - and makes complete sense. Thank you.
     
  11. Landa-100

    Landa-100

    Joined:
    Sep 9, 2018
    Posts:
    13