1. 什么是预制体 #

在进行一些功能开发的时候, 我们常常将一些能够复用的对象制作成.prefab的预制体,然后将预制体存放到 Resources 目录之下, 使用时再动态加载到场景中并进行实例化. 例如 : 子弹、特效甚至音频等, 都能制作成预制体.

预制体英文名称即 Prefab 是一种资源类型 —— 存储在项目视图中的一种可重复使用的游戏对象.

2. 预制体的优点 #

预制体可以多次放入到多个场景中;
当你添加一个预制体到场景中, 就创建了它的一个实例;
所有的预制体实例链接到原始预制, 基本上等于就是它的克隆;
不管你的项目存在多少实例, 当你对预制体进行任何更改, 你将看到这些更改将应用于所有的实例上;

3. 使用预制体注意的几点 #

3.1 创建预制体 ##

为了创建一个预制, 必须使用菜单构造一个新的空白预制, 这个空预制不包含游戏对象, 还不能创建它的一个实例. 想象一个新的预制为一个空的容器, 等着用游戏对象数据来填充. 一个新的、空的预置不能实例化直到你用一个游戏对象来填充它.

unity 编辑器下实例化预制体 unity 创建预制体_unity 编辑器下实例化预制体

要填充预制, 需要使用一个场景中已经创建的游戏对象.

  • 从菜单选择 Assets->Create->Prefab 并为新预制命名;
  • 在层次视图 Hierarchy View 中, 选择你想使之成为预制的游戏对象;
  • 在层次视图中拖动该对象到项目视图中的新预置上;

当完成这些步骤之后, 游戏对象和其所有子对象就已经复制到了预置的数据中. 该预置现在可以在多个实例中重复使用, 层次视图中的原始游戏对象已经成为了该预置的一个实例.

3.2 预制体实例 ##

可以在程序运行时来执行实例化操作, 创建预制物体, 在脚本中引用预制物体. 相对而言脚本中代码也比较简洁, 需要修改也比较简单只要对预制物体进行修改就可以了, 不需要添加其他修改代码, 与普通脚本相比预制创建的实例化物体, 全部都是预制物体的克隆, 可以提高程序运行效率和节省内存空间.

要在当前的场景中创建预制体的一个实例, 就从项目视图拖动预制到场景中或层次视图中即可. 此实例是链接到该预制的, 如下图在层次视图中使用蓝色文字显示.

unity 编辑器下实例化预制体 unity 创建预制体_.net_02

如果选择了一个预制的实例, 并希望做些改变以影响到所有实例, 可以在检视视图中单击 Select 按钮选择预制源.

** - 继承 Inheritance **

继承是指当预制源发生变化, 这些变化将应用于所有已链接的游戏对象.

例如, 如果添加一个新的脚本到预制, 所有已链接的游戏对象都将立刻包含该脚本. 但是它有可能改变一个单独实例的属性, 同时保持链接. 改变任何一个预制实例的属性, 可以看到变量名称变为粗体, 现在该变量可以被重写, 所有的重写属性不会影响预制源的变化.

这使你可以修改预制实例使它们变得独一无二, 而不破坏它们与预置源之间的链接.

unity 编辑器下实例化预制体 unity 创建预制体_unity 编辑器下实例化预制体_03

** - 破坏和恢复预制链接 Breaking and Restoring Prefab Links **

有些行为将破坏单个实例及其预制源之间的链接, 但链接总是可以恢复的.

下面的行为将破坏链接 :

  • Adding or removing a Component 添加或删除一个组件;
  • Adding or removing a child GameObject 添加或删除一个子对象;

这些行为将引起一个破坏链接的警告/确认消息, 确认该行为将破坏链接. 这样, 更改预制源将不再影响已破坏了链接的实例.
要恢复该链接, 你可以在实例的检视视图中单击 Reconnect 或 Apply 按钮.

  • Reconnect 将丢弃与预置源的所有差别;
  • Apply 将复制所有差别到预置源中(包括所有其它预置实例);

** - 导入预制 Imported Prefabs **

当你放置一个网格资源到你的资源文件夹中, Unity 自动导入文件并生成一些类似于一个预制的网格. 这实际上并不是一个预制, 它只是这个资源文件本身. 在进行正常预制工作时, 资源的实例化名没有某些限制.

资源是作为一个游戏对象存在于场景中的实例, 链接到源资源代替一个正常的预置.

作为正常的游戏对象, 组件可以被添加和删除. 但是, 你不能应用任何变动到这个资源本身, 因为这样将给资源文件本身添加数据. 如果你创建一些你想要重复使用的东西, 你应该将资源实例制成一个预制.

4. 加载预制体并实例化的代码 #

将预制体放到 Resource 文件夹下

GameObject.Instantiate(Resource.Load("预制体的名字")); 或者
GameObject instance = Instantiate(Resources.Load<GameObject>("预制体的名字"));

End.