πŸ‡UI System

Used to manipulate with UI screens

How to use

Add using Game.UI; to use UI System API in code.

Scene setup

  1. Add prefab UI;

  2. Find SceneSettuper object. If you don't see it -> create it. In SceneSettuper find SceneUI as child object;

  3. Replace all UIControllers (GameCanvas and etc) under SceneUI object;

You will end up with this:

Scene objects for UI
  1. Set in SceneUI object reference to active canvas by default;

Scene UI Controller in inspector

You can add more UIControllers under SceneUI object. SceneUIContainer will setup UICanvasContainer references. You can leave field null if you want manualy set active canvas on start.

How it works

UIManager.cs is main script that you will refer to get canvases and switch them. Each canvas must be inherited from UICanvasController.cs. All main prefab canvases are referenced in UICanvasContainer and UIManager requests their instances. Here is diagram:

UICanvasContainer.cs holds references to all UICanvasControllers in scene. By UIManager you can get target canvases. As soon as scene starts -> all canvases will automaticaly parented to UI object by SceneUIContainer. Each time you load new scene -> all old UI objects will be destroyed by SceneSetupper;

Basic look of UIManager in the inspector:

As you can see it has reference resolution that is used to compare user and reference resolutions in other scripts. EventSystem prefab will be created automaticaly if there is no active in scene.

UICanvasController

This is base of all canvases. You need to inherit it when implementing any type of canvas. It supports states and if you need it -> create UICanvasController that holds other UICanvasControllers as childs in scene hierarchy. It has built in fade in and out logic.

The above scheme is implemented in GameCanvas by default. It has Main/Win/Lose/Pause states. Here it's codea as example:

public class GameCanvas : UICanvasController {

    public MainState MainState; // UICanvasController 
    public WinState WinState;   // implementations
    public LoseState LoseState; // ..

    [SerializeField] private PauseState _pauseState; // Pause UICanvasController
    private UICanvasController _lastActiveState;     // private because used by PauseGame function only

    protected override void Awake() {
        base.Awake();
        _lastActiveState = _activeState;
    }

    public void PauseGame(bool active, float fadeDuration = 0.25f) {
        if (active) {
            SetState(_pauseState, fadeDuration);
        }
        else {
            SetState(_lastActiveState, fadeDuration);
        }
    }
}

And here is example how you can switch states of GameCanvas:

// get GameCanvas
var UI = UIManager.instance.GetCanvas<GameCanvas>();
// change state to Lose
UI.SetState(UI.LoseState);

API UIManager

/// <summary>
/// Manager for all ingame canvases except loaders
/// </summary>
[RequireComponent(typeof(UICanvasContainer))]
public class UIManager : MonoBehaviour {
    public static UIManager instance;
    
    /// <summary>
    /// Reference screen resolution, used to compare it with player's screen
    /// </summary>
    public Vector2 ReferenceResolution => _refResolution;
    /// <summary>
    /// Vector2 where x and y are refWidth/UserScreenWidth and refHeight/UserScreenHight
    /// </summary>
    public Vector2 RefAndUserWidthHightCoefs => _refAndUserWidthHightCoefs;
		
    public float ReferenceAspectRatio => _refResolution.x / _refResolution.y;
    public float UserAspectRatio => (float)Screen.width / Screen.height;
    public float UserAndRefAspectRatioCoef => UserAspectRatio / ReferenceAspectRatio;

    /// <summary>
    /// Visibility of UI by canvas group, returns true if it's visible.<br>
    /// If not visible then canvasGroup alpha = 0f</br>
    /// </summary>
    public bool IsVisibleUI;

    public UICanvasController ActiveCanvas => _activeCanvasController;

    /// <summary>
    /// Returns target non-custom canvas with casted type
    /// </summary>
    public T GetCanvas<T>() where T : UICanvasController;

    /// <summary>
    /// Smooth switch canvas to new instance <br>
    /// Note that child canvases you must switch in holder/parent canvas by SetState() </br>
    /// </summary>
    /// <param name="fadeOut">fade out time in seconds</param>
    /// <param name="fadeIn">fade in time in seconds</param>
    /// <returns>new canvas controller</returns>
    public void SwitchCanvasTo(UICanvasController canvas, float fadeOut = 0f, float fadeIn = 0f);

    /// <summary>
    /// Smooth switch canvas to new one by canvas type <br>
    /// Note that child canvases you must switch in holder/parent canvas by SetState() </br>
    /// </summary>
    /// <param name="fadeOut">fade out time in seconds</param>
    /// <param name="fadeIn">fade in time in seconds</param>
    /// <returns>new canvas controller</returns>
    public T SwitchCanvasTo<T>(float fadeOut = 0.25f, float fadeIn = 0.25f);

    public void DisableAllCanvases();

    public void DisableActiveCanvas();

    /// <param name="fadeOut">fade out duration in seconds</param>
    public void DisableActiveCanvas(float fadeOut);

API UICanvasController

public class UICanvasController : MonoBehaviour {
    public static UnityEvent<UICanvasController> OnCreated = new UnityEvent<UICanvasController>();

    /// <summary>
    /// Child-canvases keep belong to their parent canvases!
    /// </summary>
    public bool IsChildCanvas => _isChildCanvas;

    /// Set it to false - no input will be handled <br>
    /// Set it to true - buttons will work, input handled</br>
    public bool RaycasterEnabled;
    
    /// <summary>
    /// For canvas holder/parent it's visibility status <br>
    /// For child canvases - will they be activated on holder/parent and visibility status too </br>
    /// </summary>
    public bool IsActive => _isActive;
    
    /// Does this canvas will have transition animation on enable / disable?
    public bool HasTransitionComponent;

    [Tooltip("Leave it null if it's single canvas.\n" +
        "If it's state-driven -> chose active state by default!")]
    [SerializeField] protected UICanvasController _activeState;

    protected virtual void Awake();

    /// <summary>
    /// Enables/Disables controller, and also it's child if state-driven and activeState != null <br>
    /// Makes it instantly </br>
    /// </summary>
    /// <param name="active">true - enable, false - disable</param>
    public void EnableCanvas(bool active);

    /// <summary>
    /// Enables/Disables controller, and also it's child if state-driven and activeState != null <br>
    /// Makes it smoothly if <paramref name="fadeDuration"/> > 0 </br>
    /// </summary>
    /// <param name="active">true - enable, false - disable</param>
    /// <param name="fadeDuration">time to fade canvas in or out (alpha change)</param>
    public virtual void EnableCanvas(bool active, float fadeDuration);

    /// <summary>
    /// Set new state of UICanvasController that is child of canvas where it's called
    /// </summary>
    /// <param name="state">Child state (don't set child of child)</param>
    /// <param name="fadeDuration">Smooth fade state change with value > 0f, or instant</param>
    public void SetState(UICanvasController state, float fadeDuration = 0f);

    /// <summary>
    /// Override it to init references as soon as possible
    /// </summary>
    internal virtual void InitReferences();

More examples you can find in Assets/_Main/_Examples/UI System.

Last updated