Unity Term Book
核心与架构

Prefab

Prefab 是可复用的 Unity 模板资源——设计一次,便可生成无数份实例。修改 Prefab 资源后,仍继承该属性的所有实例会同步更新;每个实例还可做 Overrides。它是团队协作关卡与批量内容生产的核心,高频生成时常配合 Object Pooling 避免运行时卡顿与 GC 的内存尖峰。

想象一下...

Prefab 就像面包模具。你先设计好模具(Prefab 资源)和全部配方。然后往里倒面团(Instantiate()),几秒内就能做出几百个一模一样的面包。要换口味?改模具——之后每一批都会跟上变化。

概念详解

Prefab 是一个 .prefab 文件,保存完整的 GameObject 层级—— Component、设置和子物体。拖进 Scene 后,Unity 会创建一份 Prefab Instance,并链接回该资源。

Prefab Overrides:每个 Instance 可以覆盖 部分属性(颜色、HP…),其余仍从 Prefab 继承。当 Prefab 资源更新时, 没有 Override 的实例会自动拿到新值。

Nested Prefabs:一个 Prefab 可以包含其他 Prefab。 适合做 Level Prefab 里放 Room Prefab,每个 Room 再放 Enemy Prefab。

在紧密循环里频繁调用 Instantiate()/Destroy() 会造成卡顿 (Garbage Collection 尖峰)。高频生成(机枪子弹、特效…)请用 Object Pooling

示意图:Prefab → Instances

📦 Prefab Asset

Enemy_Goblin.prefab

⚙ Rigidbody · ⚙ Collider · ⚙ EnemyAI

HP: 100 · Speed: 3

↓ Instantiate()

Instance #1

pos: (2, 0, 5)

HP: 100(来自 Prefab)

Instance #2 — Override

pos: (-3, 0, 7)

HP: 150 ← Override!

Instance #3

pos: (0, 0, 10)

HP: 100(来自 Prefab)

动手步骤

1

从 Scene 创建 Prefab

配置完成后 → 从 Hierarchy 拖到 Project 窗口的某个 Assets 文件夹。

2

在 Prefab Mode 中编辑

双击 .prefab 文件 → 进入隔离编辑空间。改动会传播到所有 Instance。

3

用 [SerializeField] 赋值

在 Inspector 中把 Project 里的 Prefab 资源拖到字段上,脚本才能 Instantiate。

4

把 Overrides 应用到 Prefab 资源

选中 Instance → Inspector → Overrides → Apply All

交互模拟器

选择 Prefab 类型,按 Instantiate 生成副本。点击 Instance 选中并改 Override。按 Destroy 移除。

Instances: 0

点击 "Instantiate()" 从 Prefab 生成 GameObject

Inspector

选择一个 Instance

Prefab: Enemy_Goblin|Selected: None|提示:点击 Instance 查看属性

代码示例

基础
using UnityEngine;

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

  void Start()
  {
      // Spawn a copy at the spawnPoint pose
      GameObject clone = Instantiate(
          enemyPrefab, spawnPoint.position, spawnPoint.rotation
      );

      // Configure the clone immediately
      EnemyAI ai = clone.GetComponent<EnemyAI>();
      if (ai != null)
      {
          ai.patrolSpeed    = 3f;
          ai.detectionRange = 8f;
      }

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

代码示例

进阶
using System.Collections;
using UnityEngine;

public class WaveSpawner : MonoBehaviour
{
  [SerializeField] private GameObject[] enemyPrefabs;  // multiple enemy types
  [SerializeField] private Transform[] spawnPoints;   // multiple spawn points
  [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++)
          {
              // Pick a Prefab and SpawnPoint at random
              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);
      }
  }
}

📌 快速记忆

  • Prefab = 可复用模板——设计一次,一直用
  • Instance 可以 Override 个别属性
  • 改 Prefab 资源 → 所有已链接 Instance 更新
  • 高频生成 → 用 Object Pooling,别靠 Instantiate/Destroy

⚠️ 常见错误

  • ❌ Instantiate 后不保存引用

    生成了却无法再控制那份 clone

    ✅ var clone = Instantiate(prefab);

  • ❌ 在热循环里每帧 Instantiate/Destroy

    GC 尖峰与卡顿——尤其机枪子弹

    ✅ Object Pool:预创建,用启用/禁用以代替创建/销毁