Screens, panels and the GameManager
Assets/
Scenes/
Arena.unity
Scripts/
Audio/
you already havethis lesson adds
Every game has one object that is not part of the world: it decides what you are looking at and what is coming out of the speakers. Before you write it, though, two words have to stop being interchangeable — because in Unity they are two completely different things.
Screen and panel are not the same word
✓ Screen
SceneManager.LoadScene("Arena")
.unity file. Loading one destroys everything in the scene you were in and builds the new one from disk. You use it when a clean slate is exactly what you want.✓ Panel
pausePanel.SetActive(true)
Different place, different world → screen. The intro is not the arena, so it gets a scene file of its own.
Same place, something on top → panel. Pausing happens in the arena, so it is a GameObject in the arena.
If you find yourself needing DontDestroyOnLoad to keep something alive across a switch, you almost certainly wanted a panel.
Two screens, each a scene file. Two panels, both living inside the second one. The arena underneath never moves.
Step 1 — the intro screen, a scene of its own
This is the one place in the whole course where a second scene earns its keep. The intro has no floor, no characters and no physics: it loads in a blink, and the moment you leave it there is nothing worth keeping.
- 1
→ Basic (URP), then → Assets/Scenes/Intro.unity.
- 2
Add , a Text with the game title, and a labelled PLAY.
- 3
Create an empty object called Intro, attach IntroScreen.cs, and point the button's On Click () at LoadArena.
using UnityEngine;
using UnityEngine.SceneManagement;
public class IntroScreen : MonoBehaviour
{
public void LoadArena()
{
SceneManager.LoadScene("Arena");
}
}Step 2 — one manager the whole arena can reach
Back in Arena.unity. A button needs to tell the manager to pause. A script on the Knight needs to play a hit sound. Neither of them owns the manager, and hunting for it with FindObjectOfType on every call is both slow and easy to get wrong. One static field settles it.
using UnityEngine;
using UnityEngine.SceneManagement;
// Panels, not screens: both of these live inside Arena.unity.
public enum GamePanel { Hud, Pause }
public class GameManager : MonoBehaviour
{
// The whole arena reaches the manager through this one field.
public static GameManager I;
void Awake()
{
I = this;
}
}Step 3 — two panels inside the arena
- 1
. Unity adds an EventSystem next to it — leave that alone, it is what makes buttons clickable.
- 2
Inside the Canvas create two empty objects: HudPanel and PausePanel. Each one is just a container.
- 3
HudPanel gets whatever you want visible while playing — a Text reading 0 will do. PausePanel gets a full-screen dark Image, the word PAUSED, a RESUME button and a MENU button.
[Header("Panels")]
public GameObject hudPanel;
public GameObject pausePanel;
public GamePanel current { get; private set; }
void Start()
{
ShowPanel(GamePanel.Hud); // the arena starts playable
}
public void ShowPanel(GamePanel next)
{
current = next;
hudPanel.SetActive(next == GamePanel.Hud);
pausePanel.SetActive(next == GamePanel.Pause);
// A pause panel that does not stop time is just a picture.
Time.timeScale = next == GamePanel.Pause ? 0f : 1f;
}
void Update()
{
if (Input.GetKeyDown(KeyCode.Escape))
ShowPanel(current == GamePanel.Pause ? GamePanel.Hud : GamePanel.Pause);
}
// Leaving the arena is a screen change, so it goes through SceneManager.
public void BackToIntro()
{
Time.timeScale = 1f;
SceneManager.LoadScene("Intro");
}One line per panel, and the comparison decides it. Add a third panel later and you add one line, not a new if-chain.
SetActive(false) stops that panel's Update too, so a hidden panel costs nothing per frame.
Point the RESUME button at
ShowPaneland the MENU button atBackToIntro. One is a panel switch, the other is a screen load — same menu, two different kinds of jump.
Step 4 — music that loops, clicks that do not
Two AudioSources on the same GameManager object. One has Loop ticked and holds the music. The other holds nothing at all and fires one-shots on demand.
[Header("Sound")]
public AudioSource musicSource; // tick Loop on this one
public AudioSource sfxSource;
public AudioClip arenaMusic;
public AudioClip clickClip;
public void PlayMusic(AudioClip track)
{
// Asking for the track that is already playing must not restart it.
if (musicSource.clip == track && musicSource.isPlaying) return;
musicSource.clip = track;
musicSource.Play();
}
public void PlaySfx(AudioClip clip)
{
if (clip != null) sfxSource.PlayOneShot(clip);
}Where the sound actually comes out
An AudioListener is the ear, and a scene should have exactly one. Unity put it on the Main Camera in lesson 06 — leave it there, and remember Intro.unity has its own.
Music does not survive a screen change: load Intro and the arena's AudioSource is destroyed with the rest of the scene. That is the price of a screen, and it is why you do not make one lightly.
Clips live in Assets/Audio — the folder you made in lesson 05. .ogg for music, .wav for short effects.
Untick Play On Awake on both sources. The manager decides when sound starts, not the Inspector.
Step 5 — wire it up
- 1
Select GameManager and add two components. Tick Loop on the first, untick Play On Awake on both.
- 2
In the Inspector drag HudPanel and PausePanel into their slots, the two Audio Sources into Music Source and Sfx Source, and your clips into Arena Music and Click Clip.
- 3
Add
PlayMusic(arenaMusic);to Start(), right after ShowPanel, so the arena comes up with the track already running. - 4
Open Intro.unity and press Play from there, not from the arena. That is the order a player meets them in, and it is the only way to catch a broken Build Settings list.
- ✓Play from Intro.unity and PLAY takes you to the arena, with music.
- ✓Escape brings up PausePanel and the Knight stops moving; Escape again and it carries on.
- ✓The floor, the blocks and the three characters never move while a panel is switched.
- ✓MENU returns to the intro, and the intro is not frozen when it gets there.