UI Inverse Mask

Is it currently possible to create an inverse mask with Unity’s UI mask component? That is hide everything that is under or overlapping the mask.

1 Like

Poking through the UI source code, I don’t think this is possible. Mask.cs is an IMask, and MaskableGraphic.cs appears to uses the IMask interface to alter itself. Unfortunately, I can’t find the path where the graphic from Mask is passed as the color mask graphic.

This is a total guess (and hopefully somebody can find more information), but you’d have to make a new “InvertibleMask.cs”. It would have an additional public boolean for “Inverted” (which triggers a NotifyMaskStateChanged). The “graphic” property could check the “Inverted” variable and return either an inverted graphic (harder) or an alternate graphic (easier).

Not officially, no. However, you might be interested in this post of mine, as well as the post below it (though I have no experience with the latter asset): Using mask to cut a hole in an image? - Unity Engine - Unity Discussions

I don’t know of a way to do this. The next best thing is to parent sprites to the UI camera, where you can use the Mask Interaction property on sprites, but that leaves you unable to interact with other true UI elements

Very simple and straight forward implementation is to switch stencil operation on the masked object.

Here is a simple script which must be places instead of Image (beneath the mask object)

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

public class InvertedMaskImage : Image {
    public override Material materialForRendering
    {
        get
        {
            Material result = base.materialForRendering;
            result.SetInt("_StencilComp", (int)CompareFunction.NotEqual);
            return result;
        }
    }
}

No any shader code or new materials.

You can check full details and screenshots here http://answers.unity.com/answers/1492803/view.html

10 Likes

Thanks a lot @nicloay . Now all my regular UI Images are broken. Do not add this script.

5 Likes

LOL its true! all my uI images was broken after that!

Images are broken

My tests showed that if you create new material based on the base, the problem of breaking Images disappears.

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

public class InvertedMaskImage : Image
{
    public override Material materialForRendering
    {
        get
        {
             Material result = new Material(base.materialForRendering);
             result.SetInt("_StencilComp", (int)CompareFunction.NotEqual);
             return result;

        }
    }
}

@GladStudio_1 but your code not work for me :smile:
And code of @nicloay is broken all :smile:

Decided to give this a go. And… @nicloay code broke it all :hushed:

Maybe you’re using it not correct way? Please show me how you use this component

Dont use this code without prior saving, it destroyed everything and I could not recover!

For my scenario, which was sufficient is the following: I wanted to create a “highlight” on certain areas of the screen for a tutorial, making everything else a bit darker. So I created a 512x512 50% transparency black image into which I cut a 64x64 hole. Now I scale this image to make everything darker but the center. Won’t work for many scenarios but may be helpful for some :slight_smile:

3 Likes

Wish I would’ve scrolled this far before trying it.
Guess there’s gotta be a first time for everything.

urgh

If anyone can’t fix their UI after closing and reopening, try a right click in Assets → reimport all assets, it did it for me.

Make sure to delete the faulty script.

2 Likes

If you use the code above and the game is broken, use the code below to restore it.
Just run it once in the game using the code below.

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

public class InvertedMaskImage : Image {
    public override Material materialForRendering
    {
        get
        {
            Material result = base.materialForRendering;
            result.SetInt("_StencilComp", (int)CompareFunction.Always);
            return result;
        }
    }
}
3 Likes

This code should work:

using UnityEngine;
using UnityEngine.Rendering;
using UnityEngine.UI;

public class InvertedMaskImage : Image {
    public override Material materialForRendering
    {
        get
        {
            Material result = Instantiate(base.materialForRendering);
            result.SetInt("_StencilComp", (int) CompareFunction.NotEqual);
            return result;
        }
    }
}

Original answer:
http://answers.unity.com/answers/1492803/view.html

5 Likes

Hello everyone
I found this on Youtube. I tested it in 2019.4.17, 2020.1.2 and 2020.2.1, and it works,with UI totally fine

14 Likes

@JavoCL 's video recommendation works for me. Looks like the proper way of doing inverse UI masks :slight_smile:

1 Like

Is there a way to create an Inverse MASK instead of inverting the image masked itself?

2 Likes