Unity Term Book
Core & Architecture

Scene

Scene là không gian chứa mọi GameObject, ánh sáng và camera — mỗi file .unity là một Scene: một màn chơi, menu hoặc trạng thái game riêng biệt bạn tải vào.

Hãy tưởng tượng...

Scene giống như một tập phim riêng lẻ. Mỗi tập có bối cảnh, nhân vật và câu chuyện riêng. Khi chuyển tập (chuyển Scene), toàn bộ bối cảnh cũ biến mất. Một số nhân vật xuất hiện xuyên tập bằng DontDestroyOnLoad() — giống nhân vật chính không biến mất khi chuyển màn.

Khái niệm chi tiết

Một game điển hình có nhiều Scene: MainMenu, Level_01, Level_02, GameOver, Loading… Tổ chức nhiều Scene giúp quản lý bộ nhớ — chỉ tải những gì cần thiết.

Để chuyển Scene, dùng lớp SceneManager. Hàm LoadScene() là đồng bộ (blocking — game đóng băng), còn LoadSceneAsync() tải nền cho phép hiển thị Loading Screen.

Additive Loading: tải nhiều Scene cùng lúc, chồng lên nhau. Thường dùng để streaming world hoặc tách Scene UI với Scene gameplay.

GameObject cần tồn tại qua nhiều Scene dùng DontDestroyOnLoad(gameObject). Luôn dùng Singleton pattern để tránh tạo bản sao khi Scene tải lại.

Luồng chuyển Scene

🎬

MainMenu

index: 0

Loading

index: 1

🎮

Level_01

index: 2

💀

GameOver

index: 3

Single Mode

Tải Scene mới → xóa Scene cũ

Additive Mode

Tải thêm → giữ nguyên Scene cũ

Hướng dẫn thực hành

1

Tạo Scene mới

Menu File → New Scene để tạo Scene.

2

Thêm vào Build Settings

File → Build Settings → kéo file .unity vào danh sách. Index quyết định số trong LoadScene(index).

3

Chuyển Scene bằng Script

Thêm using UnityEngine.SceneManagement; rồi gọi SceneManager.LoadScene().

4

Loading Screen với Async

Dùng Coroutine + LoadSceneAsync(), đọc AsyncOperation.progress (0.0 → 0.9) để cập nhật thanh tiến trình.

Trình mô phỏng tương tác

Click Load Scene để mô phỏng chuyển cảnh với Loading Screen. Theo dõi GameManager tồn tại xuyên suốt mọi Scene.

Build Settings

🔒 GameManager

DontDestroyOnLoad

Active Scene: MainMenu ·  Build Index: 0

Ví dụ Code

Cơ bản
using UnityEngine;
using UnityEngine.SceneManagement;

public class SceneBasics : MonoBehaviour
{
  void Awake()
  {
      // Giữ object này qua tất cả Scene (Singleton GameManager)
      DontDestroyOnLoad(gameObject);
  }

  public void LoadLevel1()
      => SceneManager.LoadScene("Level_01");      // theo tên

  public void RestartCurrentScene()
  {
      int idx = SceneManager.GetActiveScene().buildIndex;
      SceneManager.LoadScene(idx);                   // theo index
  }

  public void LoadNextScene()
  {
      int next = SceneManager.GetActiveScene().buildIndex + 1;
      SceneManager.LoadScene(next);
  }
}

Ví dụ Code

Nâng cao
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.UI;

public class SceneLoader : MonoBehaviour
{
  public static SceneLoader Instance { get; private set; }
  [SerializeField] private Slider progressBar;

  void Awake()
  {
      // Singleton: chỉ tồn tại 1 instance duy nhất
      if (Instance != null) { Destroy(gameObject); return; }
      Instance = this;
      DontDestroyOnLoad(gameObject);
  }

  public void LoadScene(string sceneName)
      => StartCoroutine(LoadAsync(sceneName));

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

      while (op.progress < 0.9f)
      {
          float progress = Mathf.Clamp01(op.progress / 0.9f);
          if (progressBar) progressBar.value = progress;
          yield return null;
      }

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

📌 Ghi nhớ nhanh

  • Phải thêm Scene vào Build Settings trước khi LoadScene
  • DontDestroyOnLoad để giữ object qua transitions
  • Dùng Async + Coroutine để tạo Loading Screen
  • Additive mode cho Streaming World và tách UI

⚠️ Lỗi thường gặp

  • ❌ Quên thêm Scene vào Build Settings

    Lỗi "Scene not found in Build Settings"

    ✅ File → Build Settings → Add Open Scenes

  • ❌ DontDestroyOnLoad không có Singleton guard

    Reload Scene tạo bản sao thứ 2 của GameManager

    ✅ if (Instance != null) Destroy(this);