Screen Fade In and Out

Greetings,

What is the recommended way to do screen fade ins and out? I tried to do it using pseudo classes but I could not find a pseudo class that corresponded to when the screen is made active or inactive.

I was going to use it doing c#, but I am trying to figure out how to access the background color of the screen - a visual element - in code, how to change it, and if that method is performant.

Any help would be greatly appreciated.

Thank you.

I’ve had good success doing this with css/uss transitions.

Have an element non visible through alpha set to 0 in uss.

Then have a uss class with alpha set to 1, the right transisions set, and then just:

element.AddToClassList(“fade-in”);

What psuedo class would you use for the fade in? I tried enabled but that doesn’t work.

I am trying to change visibility of the screen’s root visual element to fade in the screen and fade it out.

Thanks also for your reply. I think your strategy might work if I can find the right pseudo class.

If doing it through C#, is the “element” in your example on the visual element?

Here’s one way I’m guessing it could be done via script to transition the screen from on layout to another. Assume your top level VisualElement in the layout is called “Container” on both the layouts.

using System.Collections;
using System.Threading.Tasks;
using UnityEngine;
using UnityEngine.UIElements;

public class Layout_Transition : MonoBehaviour
{
    public VisualTreeAsset layout2;
    public bool doFade;
    UIDocument doc;
    VisualElement root;
    VisualElement container;

    void OnEnable()
    {
        doc = GetComponent<UIDocument>();
        root = doc.rootVisualElement;
        container = root.Q("Container");
    }

    void Update()
    {
        if (doFade)
        {
            doFade = false;
            container.style.opacity = 1;
            FadeOut();
        }
    }

    async void FadeOut()
    {
        while (container.style.opacity.value > 0)
        {
            float opacity = container.style.opacity.value - 0.05f;
            Mathf.Clamp(opacity, 0, 1);
            container.style.opacity = opacity;
            await Task.Delay(100);
        }
        FadeIn();
    }

    async void FadeIn()
    {
        doc.visualTreeAsset = layout2;
        root = doc.rootVisualElement;
        container = root.Q("Container");

        while (container.style.opacity.value < 1)
        {
            float opacity = container.style.opacity.value + 0.05f;
            Mathf.Clamp(opacity, 0, 1);
            container.style.opacity = opacity;
            await Task.Delay(100);
        }
    }
}

But, let me know what you come up with.
FYI - I’m just learning this UI Toolkit now. There is a great course on Udemy from David Makowski that covers all the basics. I highly recommend it! You can find a link to it with a discount from his youtube channel called MadCat tutorials.

Thanks. Your approach definitely seems like it would work. Also thanks for the reference to the Udemy course. My only question is that one of the Unity Devs said that doing it through USS and UXML is more performant and the recommended way to do it. Nonetheless, I will definitely keep this method in mind. I will also report back on any solution I find.

Have an element with the uss class .container. The code just adds a class OnEnable. This is what I meant earlier. And it should be what you’re referring to in regards to using UXML/USS.

USS

opacity: 0;
}
.fade-in {
opacity: 1;
transition-duration: 0.5s;
transition-property: opacity;
}

Pseudo code:

{
void OnEnable() {
// Need to wait for creation before animating stuff
doc.rootVisualElement.RegisterCallback<GeometryChangedEvent>(_ => doc.rootVisualElement.Q("container").AddToClassList("fade-in"));
}
}

Okay, I diddn’t know about transitions. That works pretty well. So if I want to toggle fade out and fade in, (and I’m not doing anything to change the layout) I’m doing this:

    void FadeIn()
    {
        container.AddToClassList("fade-in");
        container.RemoveFromClassList("fade-out");
    }

    void FadeOut()
    {
        container.AddToClassList("fade-out");
        container.RemoveFromClassList("fade-in");
    }

Where the uss is like this:

.container {
    opacity: 1;
}

.fade-in {
    opacity: 1;
    transition-property: opacity;
    transition-duration: 0.5s;
    transition-timing-function: linear;
}

.fade-out {
    opacity: 0;
    transition-property: opacity;
    transition-duration: 0.5s;
    transition-timing-function: linear;
}

This works very smoothly. I’m just wondering if the RemoveFromClassList() causes any problems if the class has not been added? It doesn’t seem to.

Weird, I did everything @JasonsFreeTime1 said,

USS code

.fade-in {
    opacity: 1;
    transition-property: opacity;
    transition-duration: 1s;
    transition-timing-function:ease;
}

.fade-out {
    opacity: 0;
    transition-property: opacity;
    transition-duration: 1s;
    transition-timing-function:ease;
}

made helper static methods for ease of use:

        public static void FadeIn(this VisualElement v) {
            v.AddToClassList("fade-in");
            v.RemoveFromClassList("fade-out");
        }
        public static void FadeOut(this VisualElement v)
        {
            v.AddToClassList("fade-out");
            v.RemoveFromClassList("fade-in");
        }

In use:

            public void ShowAlert(string m, float dur)
            {
                alertLabel.text = m;
                alert.FadeIn();
            }

        public void HideAlert()
            {
                alert.FadeOut();
            }

But no fading happens.

But, if I setup in code, the element can fade.

                alert.style.opacity = 0;
                alert.style.transitionProperty = new List<StylePropertyName> { "opacity" };
                alert.style.transitionDuration = new List<TimeValue> { new TimeValue(1f, TimeUnit.Second) };
                alert.style.transitionTimingFunction = new List<EasingFunction> { EasingMode.Ease };

Then each time I want to fade in: alert.style.opacity = 1;
fade out: alert.style.opacity = 0;
and the transition will auto run.

Make sure you don’t have inline styles set on the fading element, those will override classes.

That was going to be my advice as well. I wonder if having that code amounts to being inline property applied and overriding the classes? Maybe make sure to comment out that code.
I just happened to be reviewing selector precedence in that Udemy course and these are my notes:

Selector Precedence

  • The Type selector has lowest precedence because there will likely be many elements with the same type (such as all VisualElements or all Labels or all Buttons, ect.)

  • The Class selector has a higher precedence than the Type selector because you can of course have multiple elements with the same class.

  • The Id selector has a higher precedence than the Class selector because its unlikely that you will name many elements with the same name. (Recommended to avoid naming multiple elements with the same name)

  • Style properties applied to the element itself are called Inline style properties and will override all other properties, so it has the highest precedence.

I only write the code to setup styles after I used AddToClassList and RemoveFromClassList with no result though. So that’s what I’m currently use, kinda happy with it. Since the use case code is simpler: just set opacity. But this of course does not account to more complex styles.