第2章
游 戏 对 象
游戏对象是Unity游戏项目的基本组件。场景中存在的每个物体都是或者都基于游戏对象。在本章中,你将学习Unity中的游戏对象。不过,在开始使用Unity中的对象之前,必须先学习2D和3D坐标系统。学习完这些系统之后,将开始使用Unity内置的Unity游戏对象,最后将学习各种游戏对象变换。本章中学习的知识是本书的基础,一定要花时间学好它。
2.1 维度和坐标系
那些华丽而富有魅力的视频游戏其实都是建立在数学基础上的。所有的属性、运动和交互都可以归结为数字运算。幸运的是,很多基础都已经打好。数学家辛苦工作了几个世纪,发现、创建和简化了各种过程。正是数学家的杰出工作,我们才可以利用现代软件轻松地创建游戏。你可能认为游戏中的对象只是随意地摆放在空间中,但是实际上每种游戏空间都具有维度,并且每个对象都置身于一种坐标系(或网格)中。
2.1.1 3D中的D
如前所述,每一款游戏都会使用某种级别的维度。可能你最熟悉的维度系统是2D和3D,它们分别是二维(two-dimensional)和三维(three-dimensional)的缩写。2D系统是一个平面系统。在2D系统中,只处理垂直和水平元素(换句话说就是上、下、左、右)。像Tetris、Pong和Pac Man这样的游戏就是2D游戏。3D 系统跟2D系统类似,但它多一个维度。在 3D 系统中,不仅具有垂直和水平方向(上、下、左、右),还具有深度(里和外)。图2-1完美阐述了2D正方形和3D正方形,也就是立方体(cube)。注意在3D立方体中有Z轴,它看上去就像是凸出来了一样。
注意:学习2D和3D
Unity是一个3D引擎。因此,利用它创建的所有项目一般都使用三维系统。所以,用Unity无法制作纯粹的2D游戏。现代软件表现每个物体的时候都是按照3D来渲染的。2D游戏同样拥有Z轴,只不过不用罢了。你可能想知道为什么我们还要不胜其烦地介绍 2D 系统。事实是:即便在3D项目中,仍然有许多2D元素。纹理、屏幕元素和绘图技术都使用2D系统。Unity有一套强大的工具用于制作2D游戏,2D系统也不会很快消失。
2.1.2 使用坐标系
维度系统在数学上等价于坐标系。坐标系由一系列称为轴向的直线(axis)和称为点(point)的位置组成,轴直接对应于其模拟的维度。比如,2D坐标系中包含X轴和Y轴,它们分别代表水平和垂直方向。如果对象沿着水平方向移动,我们称之为“沿着X轴”移动。同样,3D坐标系使用X轴、Y轴和Z轴,分别用于水平、垂直和深度移动或定位。
注意:常用的坐标系
在谈到对象的位置时,一般都会列出它参照的坐标系。描述对象位置的时候,说它在X轴上是2,在Y轴上是4可能有点麻烦。幸运的是,我们有一种简单的方式描述坐标。在 2D 系统中,采用(X, Y)这样的形式记录坐标。在 3D 系统中,则写成(X, Y, Z)的形式。因此,刚才的示例可以记作(2, 4)。如果对象在Z轴的坐标是10,则写作(2, 4, 10)。
每种坐标系都有一个所有的轴相交的点,这个点称为原点(origin),原点的坐标在 2D坐标系中是(0, 0),在3D坐标系中则是(0, 0, 0)。原点非常重要,因为它是计算其他点的基础。其他任何点的坐标都只是那个点沿着每个轴到原点的距离。当移动某个点使之远离原点时,点的坐标将变大。例如,右移一个点时,X轴的值将变大;左移时,X轴的值将变小,直到它经过原点为止。此时,点X坐标的绝对值将再次开始变大,但会变成负数。如图2-2所示,在2D坐标系中定义了3个点。点(2, 2)在X方向和Y方向上都距离原点2个单位(unit)。点(–3, 3)在左边和上方都距离原点3个单位。点(2,–2)在右边和下方都距离原点2个单位。
2.1.3 世界坐标系和本地坐标系
现在你已经学习了游戏世界的维度以及组成它们的坐标系。前面我们使用的坐标系称作世界(world)坐标系。在任何给定的时间,在任何世界坐标系中都只有一个X轴、一个Y轴和一个Z轴。同样,所有的对象都共享唯一一个原点。有一点你可能不知道,还有一种称为本地(local)坐标系的坐标系。每个对象都有属于自己的本地坐标系,与其他对象完全分隔开。本地坐标系具有它自己的轴和原点,其他对象不会使用它们。图2-3展示了同一个正方形在不同坐标系下的坐标表示,阐释了世界坐标系与本地坐标系之间的区别。
你可能想问:如果世界坐标系用于记录对象的位置,那么本地坐标系是用于什么的呢?本章后面将探讨变换游戏对象以及设置游戏对象的父对象,它们都需要使用本地坐标系。
2.2 游戏对象
Unity 游戏中的所有形状、模型、灯光、摄像机和粒子系统等都具有一个共同点:它们都是游戏对象。游戏对象是每个场景的基本单元。虽然游戏对象比较简单,但是却非常强大。归根结底,游戏对象只不过是一种变换(将在本章后面详细讨论)和一个容器。游戏对象作为容器用于保存各种使对象更生动、更有意义的组件。至于向游戏对象中添加什么,取决于你自己。Unity有众多组件,它们为Unity带来了多样性。在本书的课程中,你将学习使用很多组件。
注意:内置的对象
并不是每个你使用的游戏对象一开始都是空对象。Unity 有多个内置的游戏对象可以拿来就用。单击 Unity 编辑器顶部的 GameObject菜单项,就可以看到大量可用的内置对象。学习使用Unity的很大一部分内容就是学习使用内置的游戏对象和自定义的游戏对象。
创建一些游戏对象
现在我们花一些时间熟悉游戏对象。你将创建几个基本的对象,并且检查它们的各种组件。
- 创建一个新项目,或者在已经存在的项目中创建一个新场景。
- 单击GameObject 菜单项并选择Create Empty 命令,添加一个空游戏对象(也可以通过按下Ctrl+Shift+N组合键(PC用户)或者Command+Shift+N组合键(Mac用户)来创建空游戏对象)。
- 查看Inspector视图,将会发现你刚才创建的游戏对象除了有一个变换组件之外,没有任何其他组件。(所有的游戏对象都有一个变换组件。)在 Inspector 视图中单击 Add Component按钮,查看所有可以添加到对象的组件。
- 单击 GameObject 菜单项,把光标放在3D Object命令上,然后从列表中选择 Cube命令,这样就可以在项目中添加一个立方体。
- 注意立方体具有空游戏对象所不具有的各种组件。网格(mesh)组件让立方体可见,碰撞器(collider)组件让它能够在物理层面与其他对象交互。
- 最后,在Hierarchy 视图中单击Create 下拉菜单,并从列表中选择Light > Point Light 命令,在项目中添加一个点光源(point light)。
- 可以看到点光源仅仅与立方体共享了变换组件,它的主要功能是发光。你可能还会注意到,点光源发出的光由已经添加到场景中的直接光决定。
2.3 变换
现在,你已经学习、探索了不同的坐标系,并且尝试创建了一些游戏对象。现在应该把它们二者融合起来。在使用3D对象时,经常会听到变换(transform)这个术语。根据上下文,变换既可能是一个名词,也可能是一个动词。3D空间内的所有对象都有位置、旋转和缩放比例这三个属性。如果把它们结合起来,就会得到对象的变换(名词)。此外,如果变换指的是更改对象的位置、旋转或缩放比例,那它就是一个动词。Unity把它的两种含义用变换组件(transform component)统一起来。
我们回想下之前的内容,就会发现变换组件是每个游戏对象都必须具有的唯一组件。每个空游戏对象都具有变换。使用这个组件,可以查看对象当前的变换参数,也可以改变对象的变换参数。这现在听起来可能令人糊涂,但它相当简单,过不了多久你就会了解。由于变换由位置、旋转和缩放比例组成,执行变换就有三种独立的方式,分别为平移、旋转和缩放。这些变换可以使用Inspector或变换工具实现。图2-4和图2-5显示了哪些Inspector组件和工具与哪些变换相关联。
提示:Rect的使用
术语Rect(rectangle的缩写)常用于描述2D游戏对象之间的关系。比如说,像精灵这样的2D对象与3D对象有着类似的变换类型。你可以使用简单化的Rect工具控制它们的位置、旋转和缩放(Rect工具的位置见图2-5)。此外,Unity中的用户界面(UI)对象具有不同的变换,称为Rect变换。在第14章中,我们会详细介绍它。现在,你只需要了解它与应用在UI上的transform一样即可。
2.3.1 平移
在 3D 系统中改变对象的坐标位置称为平移(translation),这是最简单的变换。当你平移一个对象时,它将会沿着轴移动。图2-6演示了一个沿着X轴平移的正方形。
当你选择Translate工具的时候(快捷键:W),会注意到所选的任何对象在Scene视图中将稍微有所改变。更确切地讲,你会看到3个箭头出现,它们沿着3个轴从对象的中心指向外面。它们是平移小工具,它们可以帮助你在屏幕上移动对象。单击并按住其中任何一个轴的箭头将使其变成黄色。然后,移动鼠标,对象将沿着那个轴移动。图2-7展示了平移小工具的样子。注意,这个工具只会出现在Scene视图中。
提示:Transform组件和Transform工具
Unity提供了两种方式来管理对象的变换。知道何时使用哪种方式很重要。当你利用Transform工具在Scene视图中执行对象的变换时,会发现Inspector视图中对应的变换数据也会发生改变。使用Inspector视图通常更容易对对象执行较大的变换,因为只需要更改它们的值。不过,变换工具对于快速、较小的改变更有用。结合使用这两种方式将极大地改进工作流程。
2.3.2 旋转
旋转对象不会在空间中移动,而是改变对象与空间的关系。更简单地说,旋转能够使你重新定义X轴、Y轴和Z轴对于特定的对象指向的是哪个方向。当对象绕着一个轴旋转的时候,就是说那个轴不动。图2-8展示了一个围绕Z轴旋转的正方形。
提示:如何确定旋转的轴向
如果不确定需要围绕哪个轴旋转对象才能获得想要的效果,可以使用一种简单的方法。一次围绕一个轴旋转,假装对象是通过与那个轴平行的针固定在某个位置上。对象只能围绕固定它的针旋转。现在,确定围绕哪根针旋转就是允许对象以哪种方式旋转,它就是旋转对象所需要的轴。
就像Translate工具一样,选择Rotate工具(快捷键:E)会让旋转小工具出现在对象周围。这些小工具是圆形的,代表对象围绕轴的旋转路径。单击并拖动其中任何一个圆形都会使其变成黄色,然后围绕那个轴旋转对象。图2-9显示了旋转小工具的样子。
2.3.3 缩放
缩放将导致对象在3D空间内扩大或者缩小。这种变换相当直观且易于使用。在任何一个轴上缩放对象都会导致对象在这个轴上放大或者缩小。图2-10展示了在X轴和Y轴上缩放正方形。图2-11展示了当你选择了Scaling工具的时候缩放小工具的样子。
2.3.4 变换的风险
本章前面介绍的变换都是在本地坐标系中进行的。所以,我们所做的更改可能会影响未来的变换操作。例如,图2-12展示了如果两种变换的顺序不同,可能产生不同的效果。
正如你所见,如果不注意变换的顺序,可能会导致不可预知的后果。幸好,只要提前安排好变换,就能得到正确的效果。
- 平移:平移是一种惰性相当强的变换,这意味着在它之后应用的任何改变一般不会受其影响。
- 旋转:旋转将改变本地坐标系中轴的方向。在旋转之后应用的平移将导致对象沿着新的轴移动。例如,如果要围绕Z轴把对象旋转180°,然后在正Y方向上移动,对象实际的表现是在向下(而不是向上)移动。
- 缩放:缩放实际上会影响本地坐标系网格(grid)的大小。一般来说,当把对象放大时,实际上是把它在本地坐标系中放大,所以看上去对象似乎变大了。这种改变具有乘法效应。例如,如果一个对象的缩放值是1(默认值),沿着X轴平移5个单位,对象看上去好像右移了5个单位。不过,如果把同一个对象缩放到2,然后在X轴上平移5个单位,这将导致对象看上去好像右移了10个单位。这是因为本地坐标系的大小现在加倍了,所以是5×2=10个单位。相反,如果把对象缩放到0.5然后移动,它好像只移动了2.5个单位(0.5×5=2.5)。
一旦理解了这些规则,就很容易确定一组变换将如何改变对象的表现。到底当前的变换是什么效果,取决于你选择的是Local还是Global,说了这么多,大家最后动手试一试效果。
提示:所有功能集于一体的工具
工具栏上的最后一个场景工具是Composite工具(快捷键是Y)。这个工具集成了针对3D对象的平移、旋转和缩放功能。
2.3.5 小工具的位置
对于不了解小工具功能的新手来说,小工具的摆放选项会特别令人迷惑。这些选项控制了场景视图中变换小工具的位置和对齐规则。观察图2-13就会发现,在Local和Global这两个不同的坐标系下,平移小工具的对齐规则不同。
此外,图2-14展示了当你选中多个对象的时候小工具的位置变化。当选中Pivot选项的时候,小工具在第一个对象的中间;当选中Center选项的时候,小工具在所有选中的对象中间。
一般来说,这两个选项应该分别设置为Pivot和Local,这样可以让你在Unity的日常开发中得心应手。
2.3.6 变换和嵌套的对象
在第1章中,我们学习了如何在Hierarchy视图中创建嵌套的游戏对象(将一个游戏对象拖曳到另一个游戏对象上)。回忆一下,当一个对象嵌套在另一个对象中的时候,我们将上层的对象称为父对象,其他对象称为子对象。应用于父对象的变换会像我们想象中那样正常进行。对象可以平移、缩放和旋转。特殊的是子对象的行为方式。一旦发生嵌套,子对象的变换就是相对于父对象进行的。因此,子对象的位置不是基于它与原点的距离,而是它与父对象的距离。如果旋转了父对象,子对象将随之移动。不过,如果查看子对象的旋转属性,你会发现它根本没有记录自己旋转过。对于缩放也是如此。如果缩放父对象,子对象也会改变大小。子对象的缩放将保持不变。你可能感到迷惑为什么会这样。记住,当应用变换时,不是把它应用于对象,而是应用于对象的坐标系。旋转的不是对象,而是它的坐标系,其效果就相当于对象旋转了。当子对象的坐标系基于父对象的本地坐标系时,对父对象所做的任何改变都将直接改变子对象(而子对象并不需要了解这一点)。
2.4 本章小结
在本章中,学习了Unity的游戏对象。首先学习了2D与3D之间的区别,然后研究了坐标系,它立马摧毁了你对“世界”这个概念的理解。之后开始学习游戏对象,包括一些内置的游戏对象。最后,学习了有关变换的知识以及3种变换方式。你应尝试了一些变换,意识到其中蕴含的一些风险,以及它们如何影响嵌套的对象。
2.5 问答
问:既学习2D概念又学习3D概念有用吗?
答:有用,即使整个游戏都是3D游戏,在技术上我们还是会使用一些2D概念。
问:应该立即学会所有内置游戏对象的使用吗?
答:并不需要。内置游戏对象那么多,一次性学完有点强人所难。随着时间的推移,跟着本书的步伐慢慢学即可。
问:熟悉变换的最佳方式是什么?
答:练习。多加练习,练得越多,熟悉得越快。
2.6 测验
花些时间完成下面的练习,确保掌握了本章的内容。
问题
- 2D和3D中的D代表什么意思?
- 有多少种变换方式?
- 判断题:Unity没有内置对象,你必须自己创建。
- 如果一开始对象在(0, 0, 0)的位置,沿着X轴将游戏对象移动一个单位,然后再将它绕Z轴旋转90度,那么现在的坐标是多少?如果先旋转后移动呢?
答案
- 维度。
- 3种。
- 错,Unity包含众多内置对象。
- 如果一开始对象在(0, 0, 0)的位置,沿着X轴将游戏对象移动一个单位,然后再将它绕Z轴旋转90度,那么现在的坐标是(1, 0, 0)。如果先旋转90度,后移动一个单位,那么坐标是(0, 1, 0)。
2.7 练习
花点时间在包含父子对象的场景中尝试各种变换,这样可以更好地理解坐标系改变对象坐标的定位方式。
- 创建一个新的场景或项目。
- 在项目中添加一个立方体,然后把它放在(0, 2, –5)处。记住坐标的简写表示法。立方体应该具有以下坐标值:X=0、Y=2、Z=–5。你可以在Inspector视图的变换组件里轻松设置这些值。
- 在场景中添加一个球体,注意球体的X、Y和Z值。
- 在Hierarchy视图中把球体拖到立方体上,从而把球体嵌套在立方体下。注意位置值是如何改变的。球体现在是相对于立方体定位的。
- 把球体放在(0, 1, 0)处。注意它不会出现在原点的正上方,而是位于立方体的正上方。
- 体验各种变换方式。一定要在立方体以及球体上都做一些变换操作,查看不同的变换操作对父对象和子对象的影响有何不同。