【Unity】3.2 利用预设(Prefab)制作可复用的组件

分类:Unity、C#、VS2015

创建日期:2016-04-02

一、简介

预制体(Prefab,也叫预设)是“存储在工程视图(Project View)中”的一种特殊的资源,是一种可重复使用的游戏对象(GameObject)的容器。

如果在Project中有多个预制体(Prefab),为了容易查找,可将这些预制体全部保存到Project视图中Assets文件夹的Prefabs子文件夹下。

Prefabs子文件夹下的的所有预制体都可以放入到多个场景中,而且即使在同一个场景中仍然可以多次使用。

向场景中添加一个预制体就是创建该预制体的一个实例。另外,由于场景(Scene)中所有预制体的实例都会自动链接到Project中的原始预制体(Prefab),因此这些实例本质上就是原始预制体的克隆。或者说,不论场景中有多少个预制体实例,只要仅仅对Project中某个Prefab作出任何更改,你就会看到这些更改马上就能应用于场景中该Prefab的所有实例。

1、在工程视图(Project)中创建预制体(Prefab)

要在Project中创建一个预制体(Prefab),只需将你在场景(Scene)中创建的一个游戏对象 (GameObject)拖放到工程视图(Project View)中的某个Prefab中。

如果层级视图(Hierarchy)中的游戏对象(GameObject)的名称变成蓝色,表示Hierarchy中的该对象是一个已经制作好的预制体的实例。此时,你可以根据需要,决定是保留层级视图 (Hierarchy)中的这个实例还是删除这个实例,不论你是否保留,都不会影响Project中制作好的原始预制体。

2、在层次视图(Hierarchy)中创建预制体的实例

要在“当前场景中”创建一个“预制体的实例”,直接从工程视图(Project View)中将某个预制体拖放到场景(Scene)或层级视图(Hierarchy)中。

Hierarchy视图中的“蓝色”字体表示该对象是某个预制体的实例。

一旦你创建了预制体的实例,该实例就会自动链接到Project中的源预制体,并在层级视图(Hierarchy)中以“蓝色”文字显示。

image

在这个截图中,有3个游戏对象是蓝色,表示这都是预制体的实例。

3、在检视器(Inspector)中操作预制体

(1)粗体的含义

有时候你可能希望仅更改单个预制体实例的属性,同时还能保持与源预制体的链接完整,此时可看到该实例对应的变量名称变成了粗体,表示这个变量已被重写。注意,所有重写的属性都不会受到源预制体更改的影响。

(2)Select

如果你选择了某个预制体实例,并希望将所做的更改影响到所有实例,此时可直接在检视器(Inspector)中单击【Select】按钮来选择更改的原始预制体。

(3)Apply

如果希望用重写的值更新源预制体及其所有实例,可单击检视器(Inspector)中的【Apply】 按钮。注意,这种“应用”不会对“根位置”和“旋转”起作用,因为这会影响实例的绝对位置并导致所有实例放在同一个位置。但是,Apply会对根的任何子元素或祖先元素的位置和旋转起作用,因为它们是相对于根的变换来计算的。

(4)Revert

如果想放弃对特定实例的所有重写,可单击【(Revert)】按钮。

4、导入预制体

将网格资源放入Assets文件夹下时,Unity会自动导入文件,并生成一些类似于网格之外的看起来像预制体的东西。但是,这实际上不是预制体(Prefab),它只是资源文件本身使用的东西。

注意,资源(asset)图标与预设 (Prefab) 图标略有不同。

资源是作为一个游戏对象(GameObject)存在于场景中的实例,它链接到源资源而不是链接到预制体(Prefab)。你可以向该游戏对象(GameObject) 正常添加、删除组件,。但是你无法对资源本身作任何更改,因为这样会向资源文件本身添加数据!如果你希望创建一些可重复使用的东西,那你就应当把它制作成一个预制体。

选择一个资源实例时,检视器 (Inspector) 中的【Apply】按钮将被替换成【Edit】按钮。单击此按钮将为资源启动编辑应用程序(如 Maya 或 Max)。

二、Prefabs基本用法示例

经过上面的介绍,你应当已经从基本层面上了解了Prefabs的概念:Prefabs本质上是GameObjects(预定义的游戏对象)和Components(组件)组成的集合体,是可在游戏中重复使用的容器对象。

使用Prefabs可以方便地在运行时实例化复杂的GameObjects(游戏对象)。

1、创建游戏对象的方式

在Unity中,有两种创建对象(Game Object)的方式:

(1)方式1:全部用C#代码实现。这种方式使用C#代码从头开始创建并初始化游戏对象(GameObjects)。

(2)方式2:利用Prefabs实现。即:先制作预制体,运行时再通过代码实例化预制体。

与方式1相比,方式2(用Prefabs实现)有多个优势:

l 可以使用一行代码实例化Prefab,并具有完整功能。而使用代码创建等效游戏对象 (GameObjects),平均需要五行代码,还有可能需要更多。

l 可在场景 (Scene) 和检视器 (Inspector) 中快速设置、测试和修改预制体。

l 可以更改已实例化的预制体,而无需更改实例化预制体的代码。例如,可将一个简单的火箭更改成超级火箭,但无需更改代码。

2、示例—创建一堵墙

为了说明Prefabs的强大,让我们来看看可用得上Prefabs的一些基本情况:

(1)在不同位置,多次使用单块“砖”预制体来创建一堵墙。

(2)发射时,火箭发射器实例化一个飞行的火箭预制体。该预制体是一个包含一个网格(Mesh)、刚体 (Rigidbody)、碰撞器 (Collider) 和带有自己的拖尾粒子系统 (Particle System) 的子游戏对象 (GameObject)。

(3)机器人爆炸成许多碎片。此时完整的操作机器人已毁坏,替换成一个残破的机器人预制体。该预制体包含分成多个部分的机器人,所有部分均设有自己的刚体 (Rigidbodies) 和粒子系统 (Particle Systems)。有了预制体,你仅用一行代码就可以将一个对象替换成指定的预制体,从而让机器人炸成许多碎片。

该示例仅仅是为了说明“使用Prefab创建对象”与“使用代码创建对象”相比,前者(使用Prefab创建对象)的优势。

(1)实现方式1

首先演示“使用代码创建对象”的实现方式,因为只有比较,你才能理解这种方式有什么缺点。

先在ch03Demos工程的Project视图的Assets下创建一个名为Scripts的子文件夹,然后在该子文件夹添加一个名为Demo1的C#脚本:

image

双击Demo1脚本,Unity就会自动启动VS2015并自动在VS2015中打开Demo1.cs文件,而且解决方案资源管理器中Assets下的文件夹结构和Unity中的文件夹结构相同:

image

将Demo1.cs文件改为下面的内容:

using UnityEngine;
using System.Collections;

public class Demo1 : MonoBehaviour
{
    void Start ()
    {
        for (int y = 0; y < 5; y++)
        {
            for (int x = 0; x < 5; x++)
            {
                GameObject cube = GameObject.CreatePrimitive(PrimitiveType.Cube);
                cube.AddComponent<Rigidbody>();
                cube.transform.position = new Vector3(x, y, 0);
            }
        }
    }
}

保存该文件。

切换到Unity,选择主菜单的【GameObject】->【Create Empty】创建一个空游戏对象,再将Scripts文件夹下的Demo1脚本拖放到刚添加的空游戏对象中。

切换到Game视图,单击【播放】按钮观察执行效果。此时将看到完全用代码创建的立方体墙(由于默认使用了重力,墙会自动倒塌):

image

当然,由于没有添加纹理,所以此时看到的仅仅是一堵白色的墙(倒塌后还是一个一个的立方体)。若想执行附加操作,例如更改砖块纹理、摩擦力或刚体的质量,还需要再添加其他的代码,可见用这种方式实现起来有多么麻烦。

删除层次视图中刚创建的空游戏对象。

(2)实现方式2

第2种中实现方式是先创建一个“墙”预制体,然后再用“创建预制体实例”的办法来创建多堵墙。

步骤如下:

选择主菜单的【GameObject】->【3D Object】->【Cube】创建一个立方体:

image

此时,刚创建的Cube在层次视图中处于选中状态。

将Texture文件夹下的brick_D拖放到层次视图中的这个立方体上。

在Project视图的Assets文件夹下,添加一个Prefabs子文件夹:

image

鼠标右击Prefabs子文件夹,选择【Create】->【Prefab】:

image

将新添加的Prefab的名称更改为“Brick”。

将在层级视图中创建的立方体拖放到Project视图中刚创建的“Brick”上。

image

这样就创建好了一个名为“Brick”的预制体(或预设)。

创建预设 (Prefab) 后,在层次视图中添加的立方体(Cube)已经用不到了,可以从层级视图 (Hierarchy) 选中它,然后按Delete键删除。

重新添加一个空游戏对象 (GameObject)。

在VS2015解决方案资源管理器项目中的Scripts子文件夹下,添加一个文件名为Demo2.cs的C#脚本(Demo2.cs),然后将其改为下面的内容:

using UnityEngine;
using System.Collections;

public class Demo2 : MonoBehaviour
{
    public Transform Brick;

    void Start ()
    {
        for (int y = 0; y < 5; y++)
        {
            for (int x = 0; x < 5; x++)
            {
                Instantiate(Brick, new Vector3(x, y, 0), Quaternion.identity);
            }
        }
    }
}

按<F5>键将其附加到Unity,然后按<Shift>+<F5>键结束。

切换到Unity,将工程视图下的该脚本拖放到刚才添加的Cube上,这就为该对象添加了一个Demo2组件:

image

另外,此时检视器 (Inspector) 中将出现一个名为“Brick”的新变量,这个Transform类型的变量可以接受任何游戏对象 (GameObject) 或预制体。

从工程视图 (Project View) 中,将预制体“Brick”拖放到检视器 (Inspector)视图中的Brick变量的值上(作用是:创建预制体的实例作为Brick变量的值):

image

按下“播放 (Play)”,就会看到同时使用预制体和C#脚本创建的墙:

image

可见,这种方式实现的脚本代码不仅非常干净,而且可重复使用这个Brick预制体。

刚开始学习时,你可能想知道为什么要这样做,用第1种方式创建立方体不是更灵活和方便吗?为什么还要再搞一个Prefab呢?

这是因为使用Prefab,您可以在数秒之内就能完成对它的调整:

  • 想要添加或更改所有实例的质量?只需在预制体中添加一个刚体,并一次性调整刚体 (Rigidbody)的重力即可。
  • 想为所有实例使用不同的材质 (Material)?只需将材质 (Material) 拖放到预制体上一次。
  • 想要更改摩擦力?在预制体碰撞器中使用不同的物理材质 (Physic Material)就行了。
  • 想为所有立方体添加一个粒子系统 (Particle System)?向预制体中添加一次子对象即可。

当然,如果仅仅是为了学习操作步骤,找不到brick_D.jpg文件时,随便找一副其他的.jpg图片代替也行,反正目标就是给这堵用立方体构造的墙贴满图,理解其含义就行了。

posted @ 2016-04-02 11:13  rainmj  阅读(5356)  评论(0编辑  收藏  举报