【Unity】Building Split-Screen Local Multiplayer in Unity: Viewport Rect & Player Input

Created: 2026-07-12Last updated: 2026-07-13

Split one screen for two-player play — the foundation of local co-op and versus. Learn split-screen with multiple cameras' Viewport Rect, per-player input assignment with the New Input System's PlayerInputManager, and each player's own UI — the foundation of split-screen.

Sharing one PC or console with friends, splitting the screen and playing together — the fun of local multiplayer is special. Two-player racing, co-op action, four-player party games. This split-screen is actually built in Unity by combining just two mechanisms: divide the screen with multiple cameras' Viewport Rect, and control each with per-player input assignment. Those two pillars.

This article assembles the foundation of split-screen local multiplayer. From split-screen with Viewport Rect, to per-player input with the New Input System's PlayerInputManager, to each player's own UI. The first step of local versus and co-op games.

The idea of split-screen: one screen is divided top/bottom (or left/right), each showing player 1's and player 2's viewpoint. Each player controls their own character with a separate controller

What you'll learn

  • Splitting the screen with Viewport Rect (top/bottom, left/right)
  • Assigning per-player input with PlayerInputManager
  • Separating each player's UI
  • Practice: split-screen where two play with separate controllers

Tested on: Unity 2022.3 LTS / Unity 6 (Input System 1.x)

Sponsored

Split-screen is built from two mechanisms

Split-screen sounds hard, but broken down it's just "divide the screen" and "divide the input." Nail these two pillars and the rest is just adding more players.

The two pillars of split-screen: on the left "divide the screen" (multiple cameras' Viewport Rect split the display area top/bottom or left/right), on the right "divide the input" (PlayerInputManager assigns each controller to each player). Local multiplayer works from combining the two
MechanismRole
Divide the screen (Viewport Rect)Prepare a camera per player and assign each camera's display area to part of the screen
Divide the input (PlayerInputManager)Link each controller (device) to each player so they don't cross

These two are independent. "How to split the screen" is the camera's job, "who controls which character" is the input's job. Each is set separately, and combined they complete local multiplayer where "on your screen, with your controller, you move your character." Let's start with split-screen.

Divide the screen with Viewport Rect

The crux of split-screen is the camera's Viewport Rect. This is a setting that specifies "which area of the screen a camera renders to" as a 0–1 ratio.

Divide the screen with Viewport Rect: a camera's Viewport Rect is specified by X/Y/W/H, with the bottom-left of the screen as origin (0,0) and top-right (1,1). For a top/bottom split, set the P1 camera to (0, 0.5, 1, 0.5) = top half and the P2 camera to (0, 0, 1, 0.5) = bottom half

Viewport Rect specifies a ratio with the four values X, Y, W, H, with the bottom-left of the screen as origin (0, 0) and top-right (1, 1).

  • Full screen: (X=0, Y=0, W=1, H=1) — a normal camera
  • Top/bottom split (2P): player 1's camera at (0, 0.5, 1, 0.5) (top half), player 2's at (0, 0, 1, 0.5) (bottom half)
  • Left/right split (2P): player 1 at (0, 0, 0.5, 1) (left half), player 2 at (0.5, 0, 0.5, 1) (right half)
  • 4-way split: four cameras at (0,0.5,0.5,0.5), (0.5,0.5,0.5,0.5), (0,0,0.5,0.5), (0.5,0,0.5,0.5)

Prepare a camera per player and just set each Viewport Rect, and the screen splits cleanly. Make each camera follow its player (Cinemachine is handy) and each viewpoint shows separately. No special shader or rendering technique needed — it's achieved with a single camera setting.

Mind the camera Depth: when using multiple cameras, each camera's Depth value determines the render order. Split displays don't overlap, so it's usually fine, but if you layer a UI camera, control front/back with Depth.

Assign input with PlayerInputManager

Even with the screen split, it's meaningless if both characters move on the same input. Assigning each player "their own controller" is the New Input System's PlayerInputManager.

PlayerInputManager: it detects each connected controller (gamepad 1, gamepad 2) and generates a player object with a PlayerInput for each. Each player receives input only from its own device

PlayerInputManager is a mechanism that auto-generates a player when a controller joins and delivers only that device's input.

  1. Prepare a Player Prefab: make a Prefab of the player character with a PlayerInput component (define input actions in an Input Actions asset)
  2. Place a PlayerInputManager: place a PlayerInputManager in the scene and assign step 1 to Player Prefab
  3. Set the join method: choose a Join scheme like "join by pressing a button." Pressing a gamepad button generates a player dedicated to that device

Now the player who joined with gamepad 1 receives only pad 1's input, and the pad 2 player only pad 2's. The biggest benefit is no input crossing. You can also split one keyboard into "P1 on WASD" and "P2 on arrow keys" via Control Schemes. Assign the previous section's Viewport Rect to each generated player's camera, and screen and input connect.

Sponsored

Separate each player's UI

Health bars and scores also want to show on each player's own screen. Place each UI in its divided area.

Separate each player's UI: on a top/bottom split, P1's top half shows their own health bar and P2's bottom half shows their own, each within its area. Match each player's Canvas to the corresponding camera's Viewport area

To separate each player's UI, prepare a Canvas per player. There are mainly two ways.

  • Link via Screen Space - Camera: set each player's Canvas to Screen Space - Camera and set Render Camera to that player's camera. The UI fits within the camera's Viewport area
  • Follow the character in World Space: place a health bar above the character's head with a World Space Canvas. Each player's camera renders it, so it naturally shows on their own screen

Now P1's health bar shows in P1's screen area and P2's in P2's. Knowing the basics of Canvas and RectTransform makes positioning within the split areas smooth. Player-specific info like scores and lives can all show on each screen this way.

Practice: two-player split-screen

Combining the above, let's complete local multiplayer where two play a top/bottom split screen with separate controllers. Co-op action, versus racing, party games — all start from this foundation.

The finished practice: a top/bottom split with player 1 on top and player 2 on bottom. Each moves their character with a separate gamepad, and each screen corner shows their own health bar — a completed split-screen

For this build we commit to a maximum of two players (turn on Enable Max Player Count on the PlayerInputManager and set Max Player Count to 2 — mash the Join button all you like, a third player will never spawn). The overall assembly:

  1. Make a Player Prefab (PlayerInput + character + follow camera + own Canvas)
  2. Place a PlayerInputManager in the scene, assign the Player Prefab and the player cap
  3. Every time someone joins or leaves, redistribute the screens by player count (one player gets fullscreen, two get top/bottom)
  4. Join with each controller → each character, screen, and input connect
using UnityEngine;
using UnityEngine.InputSystem;

// Redistribute every player's Viewport Rect whenever someone joins or leaves
public class SplitScreenManager : MonoBehaviour
{
    // Wire BOTH "On Player Joined" and "On Player Left" on the PlayerInputManager to these
    public void OnPlayerJoined(PlayerInput input) => Relayout();
    public void OnPlayerLeft(PlayerInput input) => Relayout();

    private void Relayout()
    {
        var players = PlayerInput.all;  // All currently joined players

        for (int i = 0; i < players.Count; i++)
        {
            var cam = players[i].GetComponentInChildren<Camera>();
            if (cam == null) continue;

            cam.rect = players.Count <= 1
                ? new Rect(0f, 0f, 1f, 1f)                     // One player -> back to fullscreen
                : new Rect(0f, i == 0 ? 0.5f : 0f, 1f, 0.5f);  // Two players -> top/bottom split
        }
    }
}

Two points: "camera and input are a set per player" (one player has "their camera + their PlayerInput + their UI" as one set; bundling them in the Player Prefab makes generation easy) and "re-lay out on every change, not just on join" (handle only OnPlayerJoined, and when player two drops out, player one is left stranded in half a screen. Call the same Relayout from both Join and Left, and the moment you're back to one player, the screen glides back to fullscreen — that touch of care is what makes local multiplayer feel finished).

Break It on Purpose, Then Fix It

  1. Forget the camera in the Player Prefab: a second player joins and the screen never splits. It's the sign that the "one player = character + input + camera + UI" bundle has come apart
  2. Both players' UI subscribes to the same character's health: P2 takes a hit and P1's bar drains too. Keep UI references self-contained inside the prefab and this crosstalk can't happen by construction (it's the instance-event idea, applied here)
  3. One fullscreen pause menu: now "whose gamepad drives it?" The standard answer: switch only the pausing player's PlayerInput to the UI Action Map and freeze everyone else's input — decide who "owns" the pause

With this foundation, racing, fighting, or co-op action — just layer on the game logic.

Good to know first

  • Requires the Input System package: PlayerInputManager is a New Input System feature. Install Input System in the Package Manager and nail the basics of New Input System (Input Actions) first.
  • Audio is shared: the screen splits, but there's one speaker. BGM and SFX are usually treated as one for the whole game, not split per player. Note that 3D audio changes how it sounds based on "which player is nearby."
  • A divider makes it readable: drawing a single thin line (a divider UI) at the split boundary makes the screen far more readable. Adding one full-screen UI camera and drawing only the divider is a classic approach.
  • Different from online: this article is local multiplayer that "splits one screen." Online multiplayer over a network needs a separate mechanism like Netcode for GameObjects and a completely different design.

Summary

  • Split-screen is the two pillars of "divide the screen" + "divide the input"
  • Split-screen is each camera's Viewport Rect (X/Y/W/H ratio). Top/bottom is (0,0.5,1,0.5) and (0,0,1,0.5)
  • Input is PlayerInputManager. It generates a player per controller and prevents crossing
  • UI prepares a Canvas per player, matched to the corresponding camera's area
  • Practice: bundle each player as one prefab (camera + input + UI), and redistribute Viewport Rects on every join and leave (back to fullscreen when one remains)

Start by placing two cameras and splitting them top/bottom with Viewport Rect. The moment one screen splits into two, the door to local multiplayer opens. What game will you split the screen for with friends?

Further reading