Unity Term Book
Core & Architecture

Prefab

Prefab là mẫu thiết kế sẵn (template asset) trong Unity — tạo một lần, nhân bản vô số lần. Sửa Prefab gốc sẽ cập nhật mọi instance còn kế thừa thuộc tính đó.

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

Prefab giống như khuôn đúc bánh mì. Bạn thiết kế khuôn (Prefab gốc) một lần với đầy đủ nhân liệu. Sau đó, đổ bột vào khuôn (Instantiate()) để cho ra hàng trăm chiếc bánh giống hệt nhau trong tích tắc. Nếu cần thay đổi hương vị — chỉnh khuôn gốc — tất cả mẻ bánh tiếp theo đều có hương vị mới.

Khái niệm chi tiết

Prefab là file .prefab lưu trữ toàn bộ cấu trúc một GameObject — tất cả Components, thiết lập và Child objects. Khi kéo Prefab vào Scene, Unity tạo ra một Prefab Instance kết nối với Prefab gốc.

Prefab Overrides: mỗi Instance có thể ghi đè (override) một số thuộc tính riêng (màu sắc, HP…) trong khi vẫn kế thừa phần còn lại từ Prefab gốc. Khi Prefab gốc cập nhật, Instance không có override tự động nhận bản mới.

Nested Prefabs: Prefab có thể chứa Prefab khác bên trong. Rất hữu ích cho Level Prefab chứa Room Prefabs, mỗi Room chứa Enemy Prefabs.

Gọi Instantiate()/Destroy() liên tục gây lag (Garbage Collection spikes). Với tốc độ cao (đạn súng máy, hiệu ứng…) hãy dùng Object Pooling.

Sơ đồ: Prefab → Instances

📦 Prefab Asset

Enemy_Goblin.prefab

⚙ Rigidbody · ⚙ Collider · ⚙ EnemyAI

HP: 100 · Speed: 3

↓ Instantiate()

Instance #1

pos: (2, 0, 5)

HP: 100 (gốc)

Instance #2 — Override

pos: (-3, 0, 7)

HP: 150 ← Override!

Instance #3

pos: (0, 0, 10)

HP: 100 (gốc)

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

1

Tạo Prefab từ Scene

Thiết kế xong → kéo từ Hierarchy vào thư mục Assets trong Project window.

2

Chỉnh sửa trong Prefab Mode

Double-click file .prefab → môi trường chỉnh sửa cô lập. Thay đổi lan ra tất cả Instances.

3

Kéo vào [SerializeField]

Trong Inspector, kéo file Prefab từ Project vào biến để script dùng Instantiate.

4

Apply Override lên Prefab gốc

Chọn Instance → Inspector → Overrides → Apply All.

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

Chọn loại Prefab, nhấn Instantiate để tạo bản sao. Click vào một Instance để chọn và thay đổi Override. Nhấn Destroy để xóa nó.

Instances: 0

Nhấn "Instantiate()" để tạo GameObject từ Prefab

Inspector

Chọn một Instance

Prefab: Enemy_Goblin|Selected: None|Tip: Click instance để xem Properties

Ví dụ Code

Cơ bản
using UnityEngine;

public class PrefabSpawner : MonoBehaviour
{
  [SerializeField] private GameObject enemyPrefab;
  [SerializeField] private Transform  spawnPoint;

  void Start()
  {
      // Tạo bản sao tại vị trí và góc của spawnPoint
      GameObject clone = Instantiate(
          enemyPrefab, spawnPoint.position, spawnPoint.rotation
      );

      // Lấy component từ bản sao và cấu hình ngay
      EnemyAI ai = clone.GetComponent<EnemyAI>();
      if (ai != null)
      {
          ai.patrolSpeed    = 3f;
          ai.detectionRange = 8f;
      }

      clone.name = $"Enemy_{Random.Range(100, 999)}";
  }
}

Ví dụ Code

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

public class WaveSpawner : MonoBehaviour
{
  [SerializeField] private GameObject[] enemyPrefabs;  // nhiều loại kẻ thù
  [SerializeField] private Transform[] spawnPoints;   // nhiều điểm sinh
  [SerializeField] private int    enemiesPerWave = 5;
  [SerializeField] private float  spawnInterval  = 0.5f;
  [SerializeField] private float  waveCooldown   = 5f;

  private int _waveCount = 0;

  void Start() => StartCoroutine(SpawnLoop());

  private IEnumerator SpawnLoop()
  {
      while (true)
      {
          _waveCount++;
          for (int i = 0; i < enemiesPerWave; i++)
          {
              // Chọn Prefab và SpawnPoint ngẫu nhiên
              var prefab = enemyPrefabs[Random.Range(0, enemyPrefabs.Length)];
              var point  = spawnPoints[Random.Range(0, spawnPoints.Length)];
              Instantiate(prefab, point.position, point.rotation);
              yield return new WaitForSeconds(spawnInterval);
          }
          yield return new WaitForSeconds(waveCooldown);
      }
  }
}

📌 Ghi nhớ nhanh

  • Prefab = mẫu thiết kế, tạo một lần dùng mãi mãi
  • Instance có thể Override thuộc tính riêng
  • Chỉnh Prefab gốc → tất cả Instance tự cập nhật
  • Spawn liên tục → dùng Object Pooling thay Instantiate/Destroy

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

  • ❌ Instantiate không lưu tham chiếu

    Tạo xong không biết bản sao đó ở đâu để điều khiển

    ✅ var clone = Instantiate(prefab);

  • ❌ Gọi Instantiate/Destroy liên tục trong game loop

    GC spikes, memory lag, đặc biệt khi spawn đạn súng máy

    ✅ Object Pool: tạo sẵn, bật/tắt thay vì tạo/xóa