Chapter 2 15 min

Scenes & Level Structure

From UE Levels to Unity Scenes

Scenes Are Like Lightweight Levels

In Unreal, a Level is a complete world with its own streaming setup. In Unity, a Scene is more lightweight — it's a container for GameObjects that can be loaded and unloaded independently.

Unity scenes are cheap to create. Use them liberally — one for the menu, one for the game world, one for persistent managers, one for UI overlays.

Scene Loading

Unreal uses World Partition and Level Streaming. Unity uses SceneManager with two modes: Single (replaces current scene) and Additive (loads alongside current scene).

cpp
// Unreal: Load a level
#include "Kismet/GameplayStatics.h"

// Hard transition
UGameplayStatics::OpenLevel(this, TEXT("MapName"));

// Level streaming
ULevelStreamingDynamic::LoadLevel(
    this, TEXT("SubLevelName"),
    FVector::ZeroVector, FRotator::ZeroRotator);

Persistent Objects

In Unreal, the GameInstance persists across level loads. In Unity, you use DontDestroyOnLoad to keep a GameObject alive across scene transitions.

cpp
// Unreal: GameInstance persists across levels
UCLASS()
class UMyGameInstance : public UGameInstance
{
    GENERATED_BODY()
public:
    UPROPERTY()
    int32 PlayerScore = 0;

    UPROPERTY()
    FString PlayerName;
};
Be careful with DontDestroyOnLoad — it's easy to accidentally create duplicates. Always check for existing instances in Awake() as shown above.

Multi-Scene Workflow

Unity's additive scene loading enables a powerful pattern: keep your managers in a persistent scene and load content scenes on top. This is similar to Unreal's level streaming but more explicit.

Scene Management

Unreal EngineUnityNote
Level StreamingAdditive Scene LoadingLoad scenes alongside current
World PartitionAddressables (for large worlds)Unity uses Addressables package for streaming
Persistent LevelDontDestroyOnLoad sceneA scene that persists across loads
Sub-LevelsAdditive ScenesModular world building
Deep Dive: Async Scene Loading with Progress

For loading screens, you can track scene loading progress:

C#
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class SceneLoader : MonoBehaviour
{
    public Slider progressBar;

    public void LoadScene(string sceneName)
    {
        StartCoroutine(LoadAsync(sceneName));
    }

    IEnumerator LoadAsync(string sceneName)
    {
        AsyncOperation op = SceneManager.LoadSceneAsync(sceneName);
        op.allowSceneActivation = false;

        while (op.progress < 0.9f)
        {
            progressBar.value = op.progress;
            yield return null;
        }

        progressBar.value = 1f;
        yield return new WaitForSeconds(0.5f);
        op.allowSceneActivation = true;
    }
}