Background

If you want to change a property via code that is defined in a UGUI component but controlled through a Better UI component that derives from it, it might not be enough to simply set the property of the ugui component. The logic in the better ui part may replace that value a bit later again.


Example:

You have a Better Image and want to change the sprite.


Before Better UI 2.5 you would need to write the following code:



myBetterImage.sprite = mySprite;

myBetterImage.CurrentSpriteSettings.Sprite = mySprite;



Since Better UI 2.5 only this line is enough (as long as "myBetterImage" is of type "BetterImage")



myBetterImage.sprite = mySprite;



The second line is still applied but now it is done inside the sprite-property of the Better Image.


Digging Deeper

So, the Image class of UGUI has a property called "sprite" and the BetterImage that derives from Image also have a property called "sprite".

This is achieved by using the "new" keyword. That allows to replace a property in a derived class so that the base implementation is hidden.

Inside the new property the hidden property is also called however, so that the base value is for sure kept up to date.


Note that the new property is only called if you reference a BetterImage (or other Better component), not an Image.

So, this works:



using UnityEngine;

using TheraBytes.BetterUi;


public class MyComponent : MonoBehaviour

{

    [SerializeField] BetterImage myBetterImage;

    [SerializeField] Sprite mySprite;


    void Start()

    {

        myBetterImage.sprite = mySprite;

    }

}



But this doesn't (even if a BetterImage is assigned to myImage):



using UnityEngine;

using UnityEngine.UI;


public class MyComponent : MonoBehaviour

{

    [SerializeField] Image myImage;

    [SerializeField] Sprite mySprite;


    void Start()

    {

        myImage.sprite = mySprite; // <- this only calls the property in Image, not in BetterImage

    }

}



If you want to set the sprite (or another property of another component) and don't know in the code if it is a better version, you can help yourself with a helper method:



    public static void SetSprite(Image image, Sprite sprite)

    {

        if(image is BetterImage betterImage)

        {

            betterImage.sprite = sprite;

        }

        else

        {

            image.sprite = sprite;

        }

    }



Note

Some properties are not using the new keyword because they are virtual. Those properties are simply overridden. This means that the property of the better ui component is called even if the ugui base component is referenced.

Here is a list of overridden properties:

    • (Better) Image.color
    • (Better) RawImage.color

Restrictions

The new properties setting the hidden base property as well as the current screen configuration only. Changing the values in other configs is currently not supported (but usually not needed as you normally don't have another config if the value should be the same).


Turning it Off

You can turn off the new behavior introduced with Better UI 2.5. To globally prevent changing the current settings in the creen configuration call:



TheraBytes.BetterUi.Config.ApplyAssignmentsToCurrentSettings = false;