【摘要】:Unity是一个非常流行和强大的游戏引擎,它支持众多的平台和设备。图7-75Game视图效果注意:对于Unity 2D游戏,Unity编辑器会自动处于2D模式。图7-77将playership精灵图片拖入场景视图在结构视图中,单击Unity为你创建的playership游戏对象,在检视器中查看它的属性。通过Unity的2D精灵表单编辑器,能够轻易管理这些精灵表单。
Unity是一个非常流行和强大的游戏引擎,它支持众多的平台和设备。尽管3D游戏最近火热,大部分手机游戏、控制台和桌面游戏仍然是以2D方式呈现的,因此学习用Unity编写2D游戏仍然非常重要,需要学会以下几点:如何使用精灵和相机。如何使用物理2D组件处理碰撞和玩法。如何创建2D动画和状态。如何使用图层和精灵的order。
首先从https://blog.csdn.net/kmyhy/article/details/75105514下载开始项目,解压缩,用Unity打开LowGravityLander-Start项目。在项目窗口中,打开Scenes文件夹下的Lander-Start场景。Game视图效果如图7-75所示。
开始项目已经能够运行,但你还需要解决几个问题才能真正完成它。
图7-75 Game视图效果
注意:对于Unity 2D游戏,Unity编辑器会自动处于2D模式。当你创建新项目时,可以选择2D或3D模式:在开始项目中已经设置好这个选项了。如图7-76所示。
图7-76 2D或3D模式
①精灵通过Unity强大的2D引擎和内置编辑器,我们很容易使用精灵。
要向游戏中添加精灵,从项目文件夹中将它拖到你的场景视图即可。这真的很简单,打开场景视图,然后从Sprites文件夹中,将playership精灵图片拖到你的场景视图如图7-77所示。
图7-77 将playership精灵图片拖入场景视图
在结构视图中,单击Unity为你创建的playership游戏对象,在检视器中查看它的属性。注意Unity会自动添加一个Sprite Renderer组件到游戏对象中,这个组件包含了你的playership图片,如图7-78所示。
OK!Sprite Renderer允许你将图片用作2D/3D场景中的精灵。
图7-78 Sprite Renderer组件包含了playership图片
图7-79 在Assets/Sprites文件夹中选中一个精灵图片
从结构视图中删除playership游戏对象。
②Sprite Modes,在Assets/Sprites文件夹中选中一个精灵图片。在检视器中,你可以有三种不同的模式来使用这个精灵,如图7-79所示。
Single:只有一张图片的精灵。
Multiple:使用多张图片的精灵,比如动画或精灵表单(spritesheet,同一个角色图片由多个图片组成)。
Polygon:自定义精灵的多边形形状,你可以用各种原始形状来创建,比如:三角形、方块、五边形、六边形等等。
图7-80 精灵表单包含的单张图片
一个精灵表单是一张包含多个更小图片的单张图片,如图7-80所示。
使用精灵表单的原因是游戏中用到的每一张图片都会占用一次绘制动作。当精灵图片非常多时,这会产生非常大的负担,而且你的游戏会变得复杂臃肿,导致潜在的问题。
通过精灵表单,你可以在一次绘制中绘制多个精灵图,提升游戏性能。当然,在精灵表单中如何组织这些精灵图是一个学问,那就是另一篇教程的事情了。
③精灵编辑将多张图片放到一张图片是很有用的,这样就可以用于动画或者允许对象拥有多个动作。通过Unity的2D精灵表单编辑器,能够轻易管理这些精灵表单。
在这个游戏中你将用到两个精灵表单:一个用于登陆舱的推进器动画,一个用于爆炸效果。这两个动画都由多个播放帧组成,你可以用精灵编辑器编辑和分割它们。
explosion-spritesheet.png是用于爆炸效果的,它已经切分好了,但thruster-spritesheet.png图片仍然需要处理,这是你接下来的工作。
在项目窗口的Sprites文件夹中单击thruster-spritesheet.png。在检视器中,它的Sprite Mode已经是Multiple了(如果不是,请修改为Multiple并单击Apply)。
然后,单击Sprite Editor,如图7-81所示。
弹出一个窗口,显示了自动切分成多个帧的精灵表单(图7-82中的数字是方便演示而添加的,不是截图中的内容):
单击窗口左上角的Slice,你会看到默认的切分动作是Automatic,如图7-83所示。
图7-81 单击Sprite Editor
图7-82 自动切分成多个帧的精灵表单
图7-83 单击窗口左上角的Slice的视图
图7-84 单击Slice菜单下面的Grid by Cell Size
Automatic表示Unity会自动搜索并切分你的精灵表单,以它自己的方式。但你也可以以cell size和cell count方式来切分你的精灵表单。
选择cell size将允许你以像素单位的方式来指定每一帧的大小。
在精灵编辑器中,单击Slice菜单下面的Grid by Cell Size,如图7-84所示。
在Pixel Size,将X设为9,Y设为32。将Pivot设为Center,其他值保持为0,然后单击Slice,如图7-85所示。
图7-85 Pixel Size设置
单击精灵编辑器窗口的Apply,将修改应用到精灵表单,如图7-86所示。
图7-86 单击精灵编辑器窗口的Apply
这就完成了——你可以关闭精灵编辑器了。推进器的精灵表单已经就绪。
④将精灵赋给登陆舱
现在,还不能在游戏中看到登陆舱。因为它还没有被添加上任何Sprite Renderer组件。不会有任何壮观的着陆场景——或者坠毁效果!——如果登陆舱甚至不能在屏幕上看到的话。
要解决这个问题,单击结构视图中的Lander游戏对象。在检视器中,单击Add Component,在搜索栏中输入Sprite Renderer。然后,选中Sprite Renderer组件,在组件属性中单击Sprite右边的圆圈,选择playership精灵图片,如图7-87所示。
图7-87 选择playership精灵图片
将Order in Layer设置为1。
接下来的工作是设置起落架的精灵图。在Lander游戏对象下方,选择LanderFeet游戏对象,然后单击Sprite Renderer组件中Sprite选择器右边的小圆圈。然后从Select Sprite窗口中选择lander-feet图片,如图7-88所示。
图7-88 选择lander-feet图片
单击Play,即可以在游戏视图中查看你的登陆舱了。通过WASD或者箭头键在屏幕上移动,如图7-89所示。
图7-89 单击Play后的效果
图7-90 Lander项目中的默认的相机设置
⑤2D镜头和单位像素
Unity 2D项目默认带有一个正交视图相机。
在2D游戏中,通常你会用这种相机而不是透视视图相机。接下来你会了解正交视图和透视视图的区别。
图7-90显示的是Lander项目中的默认的相机设置。
注意,Projection(投影)属性现在是Orthographic(正交)。
在项目窗口中,选择playership精灵图,然后在检视器中查看它的Import Settings。在Pixels Per Unit(单位像素)属性中,当前默认为100,如图7-91所示。
图7-91 Pixels Per Unit(单位像素)属性
这里的100是什么意思呢?
⑥术语:单位像素
在Unity中“单位”一词不一定和屏幕像素对应。相反,你的对象的大小只是相对于其它对象的,它可以是任意大小,比如:1个单位=1米。对于精灵图片,Unity用“单位像素”来定义它们以“单位”计算的大小。
假设有一张精灵图,是一张500像素宽度的图片。图7-92显示了当绘制这个精灵时,在不同的缩放系数以及不同单位像素时,它的x轴上的宽度的变化:
图7-92 x轴上的宽度的变化
还是没看懂?下面会对这个计算过程进行说明:
假设有一个游戏,使用了静态相机来全屏显示背景,就好像电脑桌面上的墙纸。
backdrop.png的高是2048,默认单位像素是100。如果你稍微心算一下,就会知道在结构视图中的游戏对象backdrop的高度是20.48个单位。
当然,正交相机的Size属性会将屏幕高度折半,因backdrop游戏对象的真实高度应当也经过直角转换,即10.24,如图7-93所示。
图7-93 正交相机的Size属性变化
当然,你不需要修改项目中的相机,因为当前的Size为5,对于这个游戏中的移动相机来说刚刚好。
⑦星系
在精灵的Import设置中有一个MaxSize属性,允许你指定精灵的最大尺寸,单位为像素。你可以根据目标平台来修改这个设置。
放大一下背景是淡蓝色星系的场景视图。注意它有一点模糊;当你导入一张精灵图片时,Max Size属性默认是2048。Unity会将图片缩小以适应默认的纹理尺寸,这会导致图片质量下降。
要解决这个问题,在项目窗口中选中这张backdrop图片,勾选Override for PC、Mac&Linux Standalone,然后将Max Size修改为4096。单击Apply,然后Unity会花几秒钟重新导入这张图片到场景视图中。你会发现背景突然变得清晰明锐了,如图7-94所示。将Max Size设为4096将告诉Unity用4096×4096大小的纹理贴图,这样你就可以看出原图的细节显示。但是,这确实会付出一些代价。查看下图中的检视器的预览区域;背景贴图的大小现在是4 M,而原来是1 M,如图7-95所示。
图7-94 勾选Override for PC、Mac&Linux Standalone
图7-95 检视器的预览
纹理贴图的大小增加后,会使它的内存暴增4倍。
值得注意的是,根据Unity所支持的平台的不同,可能会有针对其它平台的Override设置。如果你准备将游戏编译到这些平台时,你可以使用这些Override设置,从而在不同的平台上使用不同的大小和格式。
注意:4096×4096是十分大的图片文件了,尽可能避免使用这么大的文件,尤其是对于手机游戏来说。这个项目中只是为了演示才使用这么大的图片。
⑧贴图
你还可以修改贴图的格式,如图7-96所示。
图7-96 贴图的格式设置
你可能想修改某些贴图的格式,以提升图像质量,或者压缩它们的大小,但这要么会增加图片在内存中的占用,要么会降低图片的保真度。最好是理解每个参数的作用,尝试修改它们并比较贴图最终的尺寸和质量。
将Use Crunch Compression设置为50%的压缩时间会长一点,但文件尺寸会变得最小,当然你后面仍然可以调整它。
将backdrop的Import设置改回之前的内容,然后再修改Format和Crunch Compression设置,然后单击Apply,如图7-97所示。
图7-97 backdrop的Import设置,修改Format和Crunch Compression设置
在开发你自己的游戏时,你可以尝试不同的压缩率以在最小大小和质量之间找到一个结合点。
⑨2D碰撞和物理
Unity中你可以像在3D游戏中一样修改2D物理引擎的重力。对于新项目Unity默认将重力设置为地球重力,也就是9.806 65 m/s2。但如果你将飞船降落在月球上,而不是地球上,则重力就应当是地球重力的16.6%,也就是1.625 19 m/s2。
注意:在开始项目中,重力被设置为-1,以便你更容易起飞和测试游戏。
要修改游戏的重力,单击Edit/Project Settings/Physics 2D然后用Physics2DSettings检视器面板将重力的Y值从-1修改为-1.625 19,如图7-98所示。
单击Play,运行游戏,四处飞一下,看重力对飞船的移动有什么影响。
图7-98 游戏的重力修改
⑩碰撞
如果你曾经试过引导登陆舱,那么你也可能碰到过一两块岩石了。这是因为Unity的2D碰撞系统生效了。
每个会受重力和其它物体影响到的对象,都需要拥有一个2D碰撞体组件和一个2D刚体组件。
如图99所示,在结构视图中选中Lander这个游戏对象,你会看到它带有一个2D刚体和一个2D多边形碰撞体组件。在一个精灵上添加一个2D刚体组件将让它接受Unity 2D物理系统的管理。
图7-99 在结构视图中选中Lander游戏对象
⑪物理组件的简单介绍
一个2D刚体组件表示重力将对这个精灵产生作用,你可以在脚本中通过力来控制这张图片。如果你想让这个精灵受其它对象影响并和其它对象发生碰撞,你还需要添加一个2D碰撞体。添加碰撞体组件将使精灵能够响应和其它精灵发生的碰撞。
多边形2D碰撞体相对于其它简单的碰撞体,比如盒子碰撞体或圆形碰撞体来说,要耗费更多的性能,但它能和其它物体发生更精确的碰撞。尽可能地使用最简单的碰撞体能够确保你达到最佳性能。(www.chuimin.cn)
⑫碰撞多边形
在你的飞船上尝试一下碰撞体,从结构视图中选择Lander游戏对象,在Polygon 2D Collider中单击Edit Collider,如图7-100所示。
在场景视图中,将鼠标置于碰撞体的边沿;当手柄出现,你可以移动碰撞体的端点;也可以添加或删除端点,从而改变碰撞体的形状,如图7-101所示。
现在,将Lander的碰撞体恢复原样。
图7-100 在Polygon 2D Collider中单击Edit Collider
图7-101 设置变更后场景效果
注意:在Lander游戏对象附属的Lander.cs脚本中,我们用OnCollisionEnter2D去处理和其它对象的碰撞。如果碰撞力超过某个设定值,登陆舱就会坠毁。
你的降落坐垫也需要一个碰撞体;不然的话在着陆的时候你的飞船会直接落下。
在结构视图中,双击LanderObjective游戏对象,让降落坐垫居中显示。在检视器中,单击Add Component,选择Box Collider 2D组件,如图7-102所示。
图7-102 选择Box Collider 2D组件
图7-103 盒子2D碰撞体组件
Unity会为LanderObjective游戏对象添加一个盒子2D碰撞体组件,并自动将碰撞体的大小设为和精灵图的大小一样,如图7-103所示。对于刚体和2D碰撞体组件,有几点需要注意:如果你想在移动物体时应用变形组件,而不是只有重力能够作用它,可以将刚体的body type设为Kinematic。要保持让它们受Unity重力控制,使用Dynamic。如果要让它们根本不可移动,设为Static。
还可以修改刚体组件的质量,线性阻力、角阻力和其它物理属性。
碰撞体可以用于Trigger模式;在这种模式下,它们不会和其它物体发生物理碰撞,而是允许你用代码在所有MonoBehaviour脚本中都有效的OnTriggerEnter2D()方法来响应事件。
要在你的脚本代码中处理碰撞事件,可以用OnCollisionEnter2D()方法。这个方法在所有MonoBehaviour脚本中都是可用的。
可以为碰撞体分配一个可选的Physics2D材质,以控制反弹属性或摩擦属性。
注意:当游戏中只有几个对象的时候,你可能没有注意到,如果屏幕上有数以百计的对象时都参与物理作用时,用更简单的碰撞体形状将大大提升游戏性能。
如果有大量对象发生碰撞时,你可能不得不重新审视一下使用多边形碰撞体组件的策略。
⑬登陆舱动画
你的登录器还不算完,因为还缺少一个看得见的推进器向上助推的效果。现在推进器已经有了,但看不出它喷火的效果。
⑭ Unity动画101
要为游戏对象增加动画效果,需要为这个对象添加一个包含所需动画的Animator组件。这个组件需要引用一个Animation Controller,这个Controller定义了将要使用的动画剪辑,以及这些剪辑的控制方式,以及其它“发烧级”特效,比如混合和动画的过渡。
⑮推进器的动画控制器
在结构视图中,展开Lander游戏对象,显示出4个下级对象。选择ThrusterMain游戏对象,你会看到已经有一个Animator组件在上面了,但它还没有对应的动画控制器,如图7-104所示。
图7-104 展开Lander游戏对象
图7-105 单击Window菜单,选择Animation
仍然在ThrusterMain游戏对象,单击Animation编辑器标签。如果在编辑器主窗口中看不见这个标签,请单击Window菜单,然后选择Animation,如图7-105所示。
单击Create按钮,创建一个动画剪辑,如图7-106所示。
图7-106 单击Create按钮,创建一个动画剪辑
名字输入ThrusterAnim,位置选择Assets/Animations文件夹。
你会在项目窗口的Animations文件夹看到2个新的动画资源。ThrusterAnim这个动画剪辑中保存了推进器的动画,ThrusterMain则是控制这个动画的动画控制器,如图7-107所示。
图7-107 Animations文件夹
在动画窗口,你会看到一个时间轴;在时间轴上,你可以对每个推进器的图片帧进行排序或添加。
单击AddProperty,属性类型选择Sprite Renderer/Sprite,如图7-108所示。
你的编辑器现在看起来的效果如图7-109所示。
在项目窗口,单击Sprites文件夹,展开truster-spritesheet.png图片。选中4个切片图,然后拖到动画编辑器的ThrusterMain:Sprite时间线。
动画帧在时间线中重叠在一起,你可以根据需要重新安排。首先从最右边的图片开始;单击这张图片,将它向右拖,置于0:05秒处,如图7-110所示。
图7-108 选择Sprite Renderer/Sprite
图7-109 编辑器视图
图7-110 动画帧时间线设置
选中最后一帧,用Delete键删除它,如图7-111所示。
单击动画窗口的Record按钮一次,关闭这个剪辑的记录模式,防止意外修改到这个动画,如图7-112所示。
接下来配置动画控制器。
图7-111 选中最后一帧,用Delete键删除
图7-112 关闭剪辑的记录模式
Lander.cs脚本当前的Animation参数设置为true或false,表明玩家是否点火了推进器。动画控制器应该负责计算这些参数并允许某些状态被修改。
在项目窗口,单击Animations子文件夹,双击ThrusterMain.controller。这会打开动画编辑器,当你在ThrusterMain游戏对象上创建动画剪辑时,Unity会自动添加这个控制器。
现在推进器动画正在持续运行。
正确地说,推进器动画只应当在玩家当前已经点火了推进器才播放。
右击动画编辑器中的网格区域,然后选择Create State/Empty,如图7-113所示。
图7-113 选择Create State/Empty
在检视器中,将新状态命名为NoThrust。这是动画在玩家没有任何输入时的默认状态:
从Entry处,Animator会走到NoThrust并停下来,直到布尔值变成true。为了改变动画状态,你必须添加一个transition连接。
在Entry状态上右击,选择MakeTransition。再单击NoThrust状态,这会从Entry添加一个箭头指向NoThrust。右键单击NoThrust,选择Set As Layer Default State。NoThrust会变成橙色。橙色表明这个状态将会是播放时的第一个状态。
在Animator编辑器中,单击Parameters标签中的+按钮,创建一个新的Bool型参数,命名为ApplyingThrust。
右击NoThrust,单击Make Transition,然后单击ThrusterAnim。这会创建一个转换,允许在两个状态之间改变。执行同样步骤,创建一个从TrhusterAnim到NoThrust的转换,如图7-114所示。
单击从NoThrust到ThrusterAnim之间的转换线条,在检视器中单击+,添加一个条件。这个选项只对条件ApplyingThrust有效。
从下拉框中选择true。也就是说只有ApplyingThrust为true时,动画才会变成TrusterAnim状态,如图7-115所示。
图7-114 创建一个从TrhusterAnim到NoThrust的转换
图7-115 选择ApplyingThrust为true
现在编辑从ThrusterAnim到NoThrust之间的转换,同样适用ApplyingThrust条件,但这次将条件设为false:
完成后的动画控制器状态如图7-116所示。
图7-116 动画控制器状态
在Animator编辑器中,你可以调整动画回放速度为一个合适的值。单击ThrusterAnim状态,在检视器中,修改Speed属性为1.5,如图7-117所示。
图7-117 修改Speed属性
推进器动画应该对用户按下扳机进行即时响应。单击两条转换箭头(NoThrust和ThrusterAnim之间的两条),在检视器中,将转换有关的设置修改为0。反选Has Exit Time和Fixed Duration,如图7-118所示。
最后,你需要将相同的动画和控制器应用到左右推进器。在结构视图中,选择ThrusterLeft和ThrusterRight,将ThrusterMain.controller从项目窗口的Animations文件夹拖到Animator组件的Controller属性上,如图7-119所示。
图7-118 修改转换有关的设置
图7-119 将ThrusterMain.controller拖至Animator组件的Controller属性
单击Play,运行游戏;用WASD或箭头键试一下你的推进器吧!
⑯精灵的排序和图层
如果精灵不进行排序的话,2D引擎的事情不能算完。Unity允许你使用图层系统和图层顺序来进行精灵的排序。
单击Play,再次运行游戏;拿出你吃奶的力气去碰撞旁边的大石头吧!观察编辑器中的场景视图,当Restart按钮显示时,有一些石头会消失在幕布图片之后。
这是因为渲染引擎无法得知精灵的摆放顺序。所有精灵,除了飞船之外,都用的是默认的图层顺序0。
要解决这个问题,需要使用图层和图层排序系统来分隔精灵。Unity会按照指定的图层顺序来将精灵们绘制在图层上。对于每个图层,Unity会按照精灵在图层中的序号依序绘制。
单击Edit菜单,然后单击ProjectSettings,选择Tags&Layers。展开Sorting Layers一节。
单击+,添加3个新的图层:
Background;Rocks;Player。
单击并拖动每个图层旁边的句柄,将他们的顺序设置为如下所示。你的图层顺序决定了Unity的绘制这些图层中的精灵的顺序,如图7-120所示。
图7-120 图层的顺序
从结构视图中单击Backdrop;在Sprite Render组件中单击Sorting Layer下拉框,然后选择列表中的Background,如图7-121所示。
图7-121 选择列表中的Background
图7-122 设置对象的Sorting Layer为Rocks
展开Rocks游戏对象,选中所有下级的rock游戏对象。在检视器中,将这些对象的Sorting Layer统统设置为Rocks,如图7-122所示。
由于场景中的岩石是前后交叠的,很方便用它们来演示同一图层中的精灵的Order in Layer属性的用法。
如果你不为Rocks图层中的每个岩石分配一个排序值,你会发现在游戏中,岩石会随机地从其它岩石上“弹出”。这是因为Unity无法以同一的顺序绘制岩石,因为它们在图层中的顺序都是0。
找到交叠在一起的岩石,将位于较前面的岩石指定一个更大的Order in Layer值,如图7-123所示。
图7-123 指定一个更大的Order in Layer值
修改Lander及其子对象,以及Pickups下面的所有Fuel游戏对象的Sprite Renderer Sorting Layer属性为Player。这将确保它们绘制在所有东西之前。
但有一个问题。对于推进器动画该怎么办(而且,登陆舱的脚架正常情况下应当隐藏在登陆舱下面)?如果我们不指定它们的Order in Layer数值,我们会看到一些奇怪的现象。
将Lander的Order in Layer属性修改为2。选中Thruster的所有子对象和LanderFeet对象,设置它们的Order in Layer为1。
当登陆舱碰到登录平台时,平台会微微下沉,表示你已经着陆。登录平台和岩石精灵是彼此交叠的,为了使结果看起来正确,你必须将登录平台排在岩石的后面。
将LanderObjective精灵设置为Rocks图层,然后指定它的Order in Layer为0。
设置LanderObjective下方的岩石的Order in Layer值设置为1,如图7-124所示。
图7-124 设置LanderObjective下方的岩石的Order in Layer值设置为1
图7-125 设置Explosion预制件的Sorting Layer为Player
最后,选中Prefabs文件夹中的Explosion预制件,将它的Sorting Layer设置为Player,如图7-125所示。
单击Player,试一下你的飞行技巧,点火推进器,落到着陆平台上——注意不要在一个反向上推得过猛,以便撞到岩石上!
相关推荐