Topic 8 of 15 12 min beginner

Canvas & UI

Anchors, scaling, and layout groups

Unity UI is the part most likely to look perfect on your monitor and broken on someone else's phone. Two settings prevent almost all of that: the Canvas Scaler, and anchors.

Canvas render modes

Render modeBehaves likeUse for
Screen Space - OverlayPainted on top of everythingHUD, menus. The default.
Screen Space - CameraDrawn by a cameraUI that needs post-processing or 3D elements.
World SpaceAn object in the sceneHealth bars over enemies, in-world screens.
A floating health bar above an enemy is a World Space canvas, not a screen-space element you reposition every frame. Let the engine do the projection.

Canvas Scaler: set this first

On a fresh canvas, UI Scale Mode is Constant Pixel Size, which means your UI keeps its pixel dimensions and therefore shrinks into a corner on a big display and overflows on a small one.

  1. 1
    Select the Canvas and find Canvas Scaler

    It sits below the Canvas component.

  2. 2
    Set UI Scale Mode to Scale With Screen Size

    This alone fixes most cross-resolution problems.

  3. 3
    Set a reference resolution

    Design at one size and let Unity scale from it. 1920 × 1080 for desktop, 1080 × 1920 for portrait mobile.

  4. 4
    Set Match to suit your game

    0 matches width, 1 matches height, 0.5 splits the difference. Landscape games usually want width; portrait usually wants height.

Anchors

A RectTransform positions itself relative to its anchors, not to the screen. Anchors are the single most misunderstood part of Unity UI, and getting them right is what makes a layout survive a different aspect ratio.

You want itAnchor toResult
Stuck to a cornerThat cornerStays put at any resolution.
CentredCentreStays centred.
A full-width barStretch horizontallyGrows with the screen.
Filling its parentStretch bothBackgrounds and overlays.
If a button is centred at your resolution but drifts off-screen at another, its anchor is almost certainly still at the default centre while the button sits far from it. Move the anchor to where the element belongs, not where the canvas happens to be.
Hold Shift + Alt when picking an anchor preset to set the anchor and snap the element's position to it in one action.

Layout groups

Rather than positioning every element by hand, let layout groups arrange children: Horizontal, Vertical, and Grid. Add a ContentSizeFitter when the container should grow to fit its contents — a tooltip that resizes around its text, for example.

Layout groups are not free. Nesting them several deep, especially with ContentSizeFitter, forces repeated layout passes and shows up in the profiler as Canvas.SendWillRenderCanvases.

The canvas rebuild problem

A canvas batches its elements into a mesh. Change any element and the entire canvas rebuilds. A single timer updating every frame therefore rebuilds your whole HUD every frame.

  • Split static and dynamic UI onto separate canvases. This is the big one.
  • Update text only when the value actually changes, not every frame.
  • Disable the Canvas component to hide a screen — cheaper than SetActive(false), which destroys and rebuilds the batch.
  • Turn off Raycast Target on any graphic that is not clickable.
C#
private int lastShown = -1;

private void Update()
{
    int seconds = Mathf.CeilToInt(timeRemaining);

    if (seconds != lastShown)
    {
        lastShown = seconds;
        timerText.text = seconds.ToString();   // once per second
    }
}

Safe areas on mobile

Notches and rounded corners cover part of the screen. Screen.safeArea gives you the usable rectangle; apply it to a container so nothing important hides behind the hardware.

SafeAreaFitter.cs
C#
private void ApplySafeArea()
{
    Rect safe = Screen.safeArea;

    Vector2 min = safe.position;
    Vector2 max = safe.position + safe.size;

    min.x /= Screen.width;  min.y /= Screen.height;
    max.x /= Screen.width;  max.y /= Screen.height;

    rectTransform.anchorMin = min;
    rectTransform.anchorMax = max;
}
The Mobile Safe Area Handler script does this properly, including re-applying on orientation change.

What to take away

  • Set Canvas Scaler to Scale With Screen Size before building any UI.
  • Anchor elements to the edge they belong to, not the centre.
  • Split changing UI onto its own canvas to limit rebuilds.
  • Only assign .text when the value has actually changed.
  • Switch off Raycast Target on non-interactive graphics.