Prefab:源文件、副本,以及二者之间的修改
Unity 里的 prefab 是什么?
Prefab 是一个被存成文件、放在 Project 面板里的 GameObject;场景里的所有副本都跟随它,所以改这个文件会一次改掉每一个副本。若你去改某个副本,那处改动只是该副本上的一个 override——以粗体显示,并可在 Overrides 下拉里用 Apply All 和 Revert All 处理。
Prefab 就是一个存成文件的 GameObject。你拖进场景的那些副本并不是彼此复制 —— 它们全都跟着同一个文件走,所以改了文件,所有副本一起变。道理就这么简单,而 prefab 一切让人犯迷糊的地方,最后都归结为一个问题:我改的是文件,还是它的某个副本?
制作一个 prefab
- 1
在场景里把物体搭到你满意为止:mesh、material、collider、脚本、子物体,全部弄好。
- 2
把它从 Hierarchy 拖进 Project 面板里的一个文件夹。它在 Hierarchy 中的名字会变蓝:这个副本现在已经是磁盘上某个文件的 instance 了。
- 3
这个文件想拖回场景多少次都行。二十个敌人,一个文件。
编辑的是文件,不是某个副本
在 Project 面板里双击 prefab,Unity 会打开 Prefab Mode:台上只有这个物体,空空荡荡,没有任何东西挡路。你在这里改的就是文件本身,所以所有场景里的所有 instance 立刻跟着变。
反过来,如果你改的是场景里的 instance,就会产生一个 override:那一个副本上的那一个属性,从此不再理文件。Inspector 里它显示为粗体,边缘还有一条蓝线。
Inspector 顶部的 Overrides 下拉菜单会把它们全部列出来,并给出两个真正管用的按钮:Apply All 把改动写回文件,Revert All 把它们全部丢掉。
override 不是错误。巡逻点、速度、每个副本不一样的颜色 —— 它们就是为这些而生的 —— 但一个副本背着三十个 override,就只剩个 prefab 的名分了。
Variant —— 给几乎一模一样的敌人
Prefab Variant 是基于另一个 prefab 的 prefab:它全盘继承父级的东西,只在上面改几处。先做一个基础 Enemy,再做一个只改速度和颜色的 Fast Enemy variant —— 修好基础版的 bug,两个就都好了。
在项目面板中右键 prefab → ,然后打开这个 variant,只修改让它 与众不同的那几处。
prefab 也可以嵌在另一个 prefab 里面 —— 就像装在车里的轮子 —— 而且各自保留各自的链接。Unity 管这叫 nested prefab,它的行为和外面那个完全一样。
用代码生成实例
using UnityEngine;
public class Spawner : MonoBehaviour
{
public GameObject enemyPrefab; // drag the asset from the Project panel
void Start()
{
Instantiate(enemyPrefab, transform.position, Quaternion.identity);
}
}把文件从 Project 面板拖进那个槽位 —— 而不是站在 Hierarchy 里的那个副本。指向一个场景物体也 能跑,直到那个物体被删除或被禁用为止 —— 史上坏掉的一半 spawner,bug 就出在这里。 Instantiate 有自己的一篇指南。
值得认下来的两种状态
一个叫 Missing Prefab 的红色物体,说明它跟的那个文件在 Unity 之外被删掉或移走了。留在场景里的只是一具空壳:要么把文件放回去,要么把空壳删掉。
Prefab > Unpack 是故意切断链接:物体你留下了,但它们不再跟文件走。它只在一处有用 —— 一块你永远不会再用的布景;别的地方用了都后悔。
做出这个的那一课
方块预制体
这篇指南单独成篇,是一份可以直接照着做的配方。在课程里,同样的东西会作为贯穿全部五个章的那个项目的一部分来搭建 —— 基础,第 07 课。