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
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)
动手步骤
从 Scene 创建 Prefab
配置完成后 → 从 Hierarchy 拖到 Project 窗口的某个 Assets 文件夹。
在 Prefab Mode 中编辑
双击 .prefab 文件 → 进入隔离编辑空间。改动会传播到所有 Instance。
用 [SerializeField] 赋值
在 Inspector 中把 Project 里的 Prefab 资源拖到字段上,脚本才能 Instantiate。
把 Overrides 应用到 Prefab 资源
选中 Instance → Inspector → Overrides → Apply All。
交互模拟器
选择 Prefab 类型,按 Instantiate 生成副本。点击 Instance 选中并改 Override。按 Destroy 移除。
点击 "Instantiate()" 从 Prefab 生成 GameObject
Inspector
选择一个 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:预创建,用启用/禁用以代替创建/销毁