Appearance
预制件

“预制件”和“预制体”基本是在说同一个东西:Unity 的 Prefab。
更常见的说法是:
Prefab = 预制体 / 预制件
Prefab Asset = Project 面板里的模板
Prefab Instance = Hierarchy 场景里的实例一句话理解
预制体就是“保存好的 GameObject 模板”。
比如你做了一个敌人:
c
Enemy
├─ Transform
├─ SpriteRenderer
├─ Rigidbody2D
├─ Collider2D
└─ EnemyController.cs你不想每一关都重新搭一遍敌人,就把它拖到 Project 面板里,生成:
c
Enemy.prefab以后你可以把 Enemy.prefab 拖进任何场景。
Prefab Asset 和 Prefab Instance
Project 面板里的:
c
Enemy.prefab叫 Prefab 资源,也就是模板。
Hierarchy 场景里的:
c
Enemy
Enemy
Enemy叫 Prefab 实例。
关系是:
c
Enemy.prefab 模板
-> 场景里的 Enemy #1
-> 场景里的 Enemy #2
-> 场景里的 Enemy #3模板改了,实例通常也会跟着变。
Override 覆盖
如果你只改场景里某一个敌人,比如:
c
Enemy #1 血量 = 100
Enemy #2 血量 = 200
Enemy #3 血量 = 300这些单独修改就叫 Override,也就是“实例覆盖”。
你会在 Inspector 里看到:
c
Overrides
Apply
Revert意思是:
Apply:把这个实例的改动写回 Prefab 模板
Revert:撤销这个实例的改动,恢复成模板状态新手要小心 Apply,因为它会影响所有使用这个 Prefab 的实例。
什么时候用 Prefab
凡是“会重复出现”的东西,都适合做成 Prefab:
c
玩家 Player
敌人 Enemy
子弹 Bullet
金币 Coin
血条 HealthBar
伤害数字 DamageText
按钮 Button
弹窗 Panel
特效 Explosion
道具 Item比如发射子弹时,不可能提前在场景里摆好一百颗子弹,而是运行时生成:
c
using UnityEngine;
public class Shooter : MonoBehaviour
{
public GameObject bulletPrefab;
public Transform firePoint;
public void Fire()
{
Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
}
}这里的:
c
bulletPrefab就是你在 Inspector 里拖进去的 Bullet.prefab。
销毁生成出来的 Prefab
Destroy(gameObject);比如子弹飞出屏幕后销毁自己:
c
using UnityEngine;
public class Bullet : MonoBehaviour
{
private void Start()
{
Destroy(gameObject, 3f);
}
}意思是:3 秒后销毁这颗子弹。
Prefab Variant 变体
Prefab Variant 是“基于某个 Prefab 的变种”。
比如:
c
Enemy.prefab
-> FastEnemy.prefab
-> TankEnemy.prefab
-> BossEnemy.prefab它们都继承 Enemy 的基础结构,但可以改不同属性:
c
FastEnemy:速度快,血少
TankEnemy:速度慢,血厚
BossEnemy:血很多,有特殊技能这比复制一堆完全独立的 Prefab 更好维护。
Nested Prefab 嵌套预制体
Prefab 里面还可以放 Prefab。
比如:
c
Car.prefab
├─ Body
├─ Wheel.prefab
├─ Wheel.prefab
├─ Wheel.prefab
└─ Wheel.prefab这叫嵌套 Prefab。
好处是:如果你改了 Wheel.prefab,所有车上的轮子都可以更新。
Unpack 是什么
当你右键一个 Prefab 实例,可能看到:
c
Unpack Prefab
Unpack Prefab Completely意思是断开它和模板的关系。
断开后,它就变成普通 GameObject,不再跟随 Prefab 更新。
新手建议:别随手 Unpack。除非你明确知道这个物体以后不需要跟模板保持关系。
你现在最该记住的口诀
c
Project 里的是模板。
Hierarchy 里的是实例。
改实例叫 Override。
Apply 会写回模板。
Revert 会撤销实例修改。
重复出现的东西,就做成 Prefab。把场景和 Prefab 放在一起理解:
c
Scene:装一堆对象的舞台
GameObject:舞台上的演员/道具
Component:演员身上的能力
Prefab:可以反复摆放的演员模板这就是 Unity 项目能做大的关键机制之一。
使用Prefab的好处
1. 避免重复劳动
比如你有一个敌人:
c
Enemy
├─ SpriteRenderer
├─ Animator
├─ Rigidbody2D
├─ Collider2D
└─ EnemyController.cs如果不用 Prefab,每一关都要重新创建、挂组件、调参数,很麻烦。
做成:
c
Enemy.prefab以后直接拖进场景就行。
2. 统一修改
这是 Prefab 最大的价值。
假设你在 10 个场景里都放了敌人。后来发现敌人的碰撞盒太大。
不用 Prefab:
c
你要去 10 个场景里一个个改用 Prefab:
c
改 Enemy.prefab
所有关联实例都可以同步更新项目越大,这个好处越明显。
3. 方便运行时生成对象
很多对象不是提前摆在场景里的,而是游戏运行时生成的:
c
子弹
敌人
金币
爆炸特效
伤害数字
掉落物
弹窗例如生成子弹:
c
using UnityEngine;
public class Shooter : MonoBehaviour
{
public GameObject bulletPrefab;
public Transform firePoint;
public void Fire()
{
Instantiate(bulletPrefab, firePoint.position, firePoint.rotation);
}
}这里的 bulletPrefab 就是一个 Prefab。
4. 保持项目结构清晰
Prefab 可以让你的资源更有条理:
c
Assets/
├─ Prefabs/
│ ├─ Player.prefab
│ ├─ Enemy.prefab
│ ├─ Bullet.prefab
│ ├─ Coin.prefab
│ └─ UI/
│ ├─ HealthBar.prefab
│ └─ Dialog.prefab以后你想找玩家、敌人、UI、特效,都不会乱。
5. 支持变体
比如基础敌人是:
c
Enemy.prefab你可以做出:
c
FastEnemy.prefab
TankEnemy.prefab
BossEnemy.prefab它们共享基础结构,但有不同参数。
c
FastEnemy:速度快,血少
TankEnemy:速度慢,血厚
BossEnemy:血多,伤害高这叫 Prefab Variant,很适合做同类对象的不同版本。
一句话记忆
c
重复出现的对象,用 Prefab。
需要统一修改的对象,用 Prefab。
运行时要生成的对象,用 Prefab。
同类对象有不同版本,用 Prefab Variant。最典型的 Prefab:Player、Enemy、Bullet、Coin、Explosion、HealthBar、Popup。