Change USS background property using C#?

Hi there

I want to change the background and color of some ui programmatically but I can figure out how. In the past I would grab the background color member of the camera component but with ui builder it doesnt work like that.

My goal is to lerp this color based on some condition.

Would anyone please share how to modify properties of the uss driven by ui builder?

Thanks

Hello, you can access the style properties in C# by using the VisualElement.style property - you’ll see the backgroundImage, backgroundColor, and color are there.

Just note that this is equivalent to inlining styles on the UXML, and using USS classes are the recommended way as performance is better that way - you can alternately then declare classes on your USS that set those properties for you, and then enable (and disable them) by calling VisualElement.EnableInClassList("className", true) (to enable, and with false as the second parameter to disable).

Hope this helps! :slight_smile:

Thanks @JuliaP_Unity
I am getting null when I Debug here:

if (_uiDocument = this.GetComponent<UIDocument>())
        {
            _visualElement = _uiDocument.rootVisualElement;
            Debug.Log(_visualElement.style.backgroundColor);
        }

When I debug _visualElement I get this:
TemplateContainer UIDocument-container (x:0.00, y:0.00, width:NaN, height:NaN) world rect: (x:0.00, y:0.00, width:NaN, height:NaN)

Any ideas?

1 Like

I see the same behaviour. The backgroundColor property is null on a button that has the background-color defined inline.

Are the styles set inlined in the UXML or on a USS class? Because the values are only there when they’re inlined.

If you want to check what values they were resolved to, you can check VisualElement.resolvedStyle - this is only set after the GeometryChangedEvent though, so if you look too early (before layout is done) you won’t find the values you want.

Is that what’s happening there? Because otherwise it would sound like a bug.

1 Like

The styles are inlined.
I still haven’t added or set a uss class.
@JuliaP_Unity

Great, so what you have to do is get the exact VisualElement where the inlined style is set, and then you’ll be able to see it through that code. Right now you’re looking at _uiDocument.rootVisualElement, which is the root of the clone of your UXML, so there’s no way the inline style is in there. If you name your VisualElement with the background color set inline (example: you name it “some-name”) and do _visualElement = _uiDocument.rootVisualElement.Q("some-name"), now from that VisualElement you can find the background color that was inlined by accessing _visualElement.style.backgroundColor.

Hope this helps!

@JuliaP_Unity
This is what I am trying to change and how my window looks like.

_visualElement = _uiDocument.rootVisualElement.Q("Background");
            Debug.Log(_uiDocument);
            Debug.Log(_visualElement);
            Debug.Log(_visualElement.style.backgroundColor);

That results in:
UIDocument (UnityEngine.UIElements.UIDocument)
UnityEngine.Debug:Log (object)

VisualElement Background (x:0.00, y:0.00, width:NaN, height:NaN) world rect: (x:0.00, y:0.00, width:NaN, height:NaN)
UnityEngine.Debug:Log (object)

Null
UnityEngine.Debug:Log (object)

So weird
Thanks @JuliaP_Unity

Hey @gegagome , I went looking for some information and found that I misunderstood some details.

So if you want to set values through code, the VisualElement.style property we talked about is the way to go indeed. However, you won’t find the values that are inlined through looking there.

If you want to check what was set in inline styles (and class styles for that matter), you should check VisualElement.resolvedStyle - but beware that you should look after the GeometryChangedEvent happens, as this is when the resolved styles get populated with the right values.

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UIElements;

public class UiDocumentManager : MonoBehaviour
{
    UIDocument _uiDocument;
    [SerializeField]
    string _visualElementName, _sliderIntName, _scrollViewName;
    VisualElement _visualElement;
    SliderInt _slider;
    ScrollView _scrollView;

    void Awake ()
    {
        if (_uiDocument = this.GetComponent<UIDocument>())
        {
            _visualElement = _uiDocument.rootVisualElement.Q(_visualElementName);
            _slider = _visualElement.parent.Q<SliderInt>(_sliderIntName);
            _scrollView = _uiDocument.rootVisualElement.Q<ScrollView>(_scrollViewName);
        }
    }

    public VisualElement GetBackground ()
    {
        return _visualElement;
    }

    public VisualElement GetScrollView ()
    {
        return _scrollView;
    }

    public SliderInt GetSliderInt ()
    {
        return _slider;
    }
}

7769196--979368--screenshot of hierarchy ui toolkit.png

@JuliaP_Unity Thanks for your help.

With your assistance I managed to achieve what I wanted. Ideally Unity would let you grab and drag components into the inspector as it is the current paradigm but somehow that isnt and will not be the case with uitoolkit.

I included my script where I expect to store all my UI elements instead of in multiple places. It’s very simple and hopefully others will find it useful. If you have any recommendations tips it’ll be appreciated.

Thanks again Julia

2 Likes

Note to add:
If you want to get the value, use

Debug.Log(_visualElement.style.backgroundColor.value);

Cheers

1 Like

I find it frustraiting that unity is breaking from their paradigms with many of the new packages. Its like working with an engine made by a bunch of sepearate teams that don’t have any unified leadership or direction. Every feature is starting to behave totally different. Its mindboggling.