思考并回答以下问题:
本章涵盖:
本章将构建一个卷轴动作游戏,图1是该游戏的一个截图。此游戏很大程度上依赖于Unity的2D图形和物理功能,另外还大量使用了UI系统。
图1:最终的游戏效果
游戏设计
游戏玩法很简单。玩家控制一个地精,用一根绳索将其坠到一个井中,井底有宝藏。井壁上有一些陷阱,地精碰到陷阱后就会死亡。
首先创建一个非常粗糙的草图,展示游戏将会是什么样子。使用纸和笔就可以,这里的目标是尽快形成一个大概的想法,知道如何把游戏的各个部分组织起来。图2显示了草图。
图2:游戏的简略概念图
确定了游戏的最终效果后,还需要确定总体架构。首先确定哪些对象是可见的,以及它们之间的关系是什么。同时,我们思考“不可见的”组件如何工作:如何收集输入信息,游戏的内部管理器如何彼此通信。
最后,还要考虑游戏的视觉效果。我们找到了一个艺术家朋友,请他绘制一幅地精下到井中、遭遇陷阱威胁的图片。这让我们意识到主要角色可能是什么样子,并设定了游戏的总体基调:轻松的、卡通风格的、稍微有点暴力的游戏,主角是贪婪的地精。最终概念图如图3所示。
图3:地精角色的概念图
如果不认识艺术家,就自己绘图!也许你觉得自己画得不好,但是只要能表达游戏看起来是什么样子,任何想法都比没有想法要好。
完成了初步设计后,就能够开始确定一些需要实现的东西:地精在游戏中如何移动,如何设置界面,以及游戏对象如何联系起来。
为使地精能够下到井中,可给玩家提供3个按钮:一个增加绳索的长度,一个缩短绳索的长度,还有一个显示游戏的菜单。按下增加绳索长度的按钮,地精将在井中下降。为了在下降过程中避开陷阱,玩家需要左右倾斜设备,使地精左右移动。
游戏玩法主要是2D物理模拟的结果。地精是一个“布娃娃”(ragdoll),即通过关节连接的部位集合,每个部位是一个独立模拟的刚体。这意味着当通过Rope(绳索)对象连接到井的顶部时,地精将正确摆动。
绳索是通过类似的方式创建的:绳索是刚体的集合,各个刚体通过关节彼此连接。刚体链中的第一段连接到井口,并通过一个旋转的关节连接到第二段。第二段连接到第三段,第三段连接到第四段,以此类推,直到最后一段连接到地精的脚踝。要延长绳索,就在绳索顶部添加更多绳段;要缩短绳索,就移除绳段。
游戏玩法的剩余部分通过非常直观的碰撞检测来处理。
- 如果地精的任何部位触碰到陷阱对象,地精将死亡,然后创建一个新的地精。另外,创建一个鬼魂精灵,沿着井向上移动。
- 如果触碰到宝藏,就更新地精的精灵,显示它抱着宝藏。
- 如果触碰到井口(不可见对象),并且地精抱着宝藏,那么玩家获胜。
除了地精、陷阱和宝藏,游戏摄像机的脚本也在运行,使摄像机的位置关联到地精的纵向位置,但也会阻止摄像机显示高于井口或者低于井底的任何东西。
我们构建这个游戏的方式如下。
- (1) 首先,暂时使用简单的火柴人来创建地精。我们将设置布娃娃,并连接精灵。
- (2) 接下来,设置绳索。这里涉及第一段大块代码,因为绳索是在运行时生成的,并且需要支持绳索的延长和缩短。
- (3) 设置好绳索后,将创建输入系统。输入系统将接收关于设备如何倾斜的信息,并将此信息提供给游戏的其他部分(特别是地精)使用。同时,我们将构建游戏的用户界面,并创建延长和缩短绳索的按钮。
- (4) 创建好绳索、地精和输入系统后,就可以开始实际创建游戏了。我们将实现陷阱和宝藏,并开始玩游戏。
- (5) 剩下的就是锦上添花了:将地精的精灵替换为更加复杂的精灵,添加粒子效果,以及添加整体音效。
图4:第一个粗糙版本完成后的游戏效果
在完成这个项目的过程中,我们将向游戏对象添加大量组件,并调整属性值。除了我们告诉你需要修改的组件之外,还有大量组件可以调整,因此你可以自由修改任何东西的设置来查看效果,否则就保留默认设置。
创建项目并导入资源
(1) 创建一个新2D项目,命名为GnomesWell。
(2) 创建项目中的文件夹。
- Scripts
- Scenes
- Sounds
- Sprites
- 此文件夹将包含所有精灵图像。
- Gnome
- 此文件夹将包含地精角色需要的预设,以及其他相关的对象,例如绳索、粒子效果和鬼魂。
- Level
- 此文件夹将包含关卡自身的预设,包括背景、井壁、装饰用的对象和陷阱。
- App Resources
- 此文件夹将包含应用作为一个整体需要的资源:应用图标及其闪屏。
完成创建文件夹的工作后,Assets文件夹应该如图5所示。
图5:创建文件夹之后的Assets文件夹
(3) 导入原型地精资源。原型地精是地精的粗糙版本。我们首先构建这个版本,后面将把它替换为更加美观的精灵。
在下载的资源中,找到Prototype Gnome文件夹,将其拖放到Unity的Sprites文件夹中,如图6所示。
图6:地精的原型精灵
(4)将场景保存为Main.scene。
现在就可以开始构造地精了。
创建地精
因为地精将由多个独立移动的对象组成,所以我们需要先创建一个对象,作为每个身体部位的容器。还需要给此对象添加Player标签,因为用来检测地精何时触碰到陷阱、宝藏或者关卡出口的碰撞检测系统需要知道该对象是否为特殊的Player对象。构建地精的步骤如下。
(1) 创建Prototype Gnome对象。打开GameObject菜单并选择Create Empty,创建一个新的空游戏对象。将新对象命名为Prototype Gnome,然后从Inspector顶部的Tag下拉列表中选择Player,将该对象的标签设为Player。重置其Transform。
(2) 添加精灵。找到前面添加的Prototype Gnome文件夹,将每个精灵拖放到场景中,但是不要拖放Prototype Arm Holding with Gold,这个精灵以后才会用到。
你需要单独拖放每个精灵。如果选择所有精灵,试图把它们一次全部拖放到场景中,那么 Unity会认为你在试图拖放一系列图像,从而创建一个动画。
完成拖放操作后,场景中将有6个新精灵:Prototype Arm Holding、Prototype Arm Loose、Prototype Body、Prototype Head、Prototype Leg Dangle和Prototype Leg Rope。
(3) 将精灵设置为Prototype Gnome对象的子对象。在Hierarchy窗格中,选择刚才添加的全部精灵,把它们拖放到空的Prototype Gnome对象上。完成之后,Hierarchy应该如图7所示。
图6:在 Hierarchy 中,地精精灵已被附加为Prototype Gnome对象的子对象
(4) 设置精灵的位置。添加精灵后,需要正确设置它们的位置,把胳膊、腿和头连接到躯干上。在场景视图中,单击工具栏中的Move工具或者按下T键,选择Move工具。
使用Move工具重新排列精灵,使其如图8所示。
图8:原型地精的精灵
另外,让全部精灵使用Player标签,就像其父对象一样。最后,确保每个对象的z位置为0。在每个对象的Transform组件(位于Inspector顶部)的Position字段中,可看到其z位置。
(5) 向躯干部位添加Rigidbody 2D组件。选中全部身体部位精灵,然后在Inspector中单击Add Component 按钮。在搜索框中输入Rigidbody,添加一个Rigidbody 2D组件(如图9所示)。
一定要添加“Rigidbody 2D”组件,而不是“Rigidbody”。Rigidbody组件在3D空间中完成模拟,这并不适合现在这个游戏。
另外,确保仅在精灵上添加Rigidbody 2D。不要在父对象Prototype Gnome上添加刚体。
图 4-10:在精灵上添加 Rigidbody 2D 组件
(6) 在身体部位上添加碰撞器。碰撞器定义了对象的物理形状。因为身体部位在视觉上有不同的形状,所以不同的身体部位需要不同形状的碰撞器。
a. 选择手臂和腿部精灵,添加一个Box Collider 2D组件。
b. 选择头部精灵,添加一个Circle Collider 2D组件。保留其半径不变。
c. 选择Body精灵,添加一个Circle Collider 2D组件。然后,进入该碰撞器的Inspector,将其半径(radius)减小大约一半,以适应Body精灵。
现在就可以把地精及其身体部位链接起来了。身体部位之间的链接将通过Hinge Joint 2D关节完成,该关节允许对象相对于另一对象围绕中心点旋转。腿部、手臂和头部都将链接到躯干。关节的配置步骤如下所示。
(1) 选择除躯干之外的所有精灵。躯干自身不需要任何关节,其他身体部位将通过各自的关节链接到躯干。
(2) 给所有选中的精灵添加Hinge Joint 2D组件。通过单击Inspector底部的Add Component按钮,然后选择Physics 2D → Hinge Joint 2D完成。
(3) 配置关节。在仍然选中精灵的状态下,我们将设置一个所有身体部位都具备的属性:这些部位都将连接到Body精灵。
将Prototype Body从Hierarchy窗格拖放到Connected Rigid Body框中,从而把对象链接到躯干。完成之后,铰链关节的设置应该如图10所示。
图 4-11:铰链关节的初始设置
(4) 对关节添加限制。我们不希望对象能够旋转整圈,而想限制它们的旋转程度。这可以避免一些看上去不符合实际的行为,例如腿部从身体中穿过。
选择手臂和头部,然后选中Use Limits。将Lower Angle设为-15,Upper Angle设为15。
接下来,选择腿部,同样选中Use Limits。将Lower Angle设为-45,Upper Angle设为0。
(5) 更新关节的轴点。我们想让手臂绕肩膀旋转,让腿部绕臀部旋转。但默认情况下,关节将绕对象的中心旋转(如图 4-12 所示),这样看起来会很奇怪。
图 4-12:铰链关节的锚点的起始位置不正确
为了纠正这个问题,需要更新关节的 Anchor(锚点)以及 Connected Anchor(连接处锚点)的位置。拥有关节的身体部位将绕Anchor旋转,而关节连接到的身体部位则绕着Connected Anchor旋转。对于地精的关节,我们想让 Connected Anchor 和 Anchor 在同一个位置。
当选择一个有铰链关节的对象时,Anchor 和 Connected Anchor 都会显示在场景视图中:
Connected Anchor 显示为一个蓝点,Anchor 显示为一个蓝色的圆圈。
选择有铰链关节的每个身体部位,将 Anchor 和 Connected Anchor移动到正确的轴点。
例如,选择右臂,将蓝点拖动到肩膀位置,这就移动了Connected Anchor。
移动Anchor要稍微困难一点,因为默认情况下Anchor位于对象的中心,但是拖动对象的中心会导致 Unity 移动整个对象。要移动Anchor,首先需要手动调整Anchor的位置:修改Inspector中的数字,可改变 Anchor 在场景视图中的位置。当Anchor不在对象的中心位置后,就可以将其拖动到正确的位置,就像拖动Connected Anchor一样(如图 4-13 所示)。
对双臂(连接到肩膀位置)、双腿(连接到臀部位置)和头部(连接到脖子底部)重复这个过程。
图 4-13:左臂的锚点在正确的位置;注意,点的周围有一个环,这说明 Connected Anchor 和 Anchor在同一个位置接下来添加连接到 Rope 对象的关节。这是一个连接到地精右腿的 Spring Joint 2D,允许绕着关节的锚点自由旋转,并限制身体离开绳索一端的距离(下一节将创建绳索)。弹簧关节的工作方式类似于现实世界中的弹簧:有弹性,可被适度拉伸。
在 Unity 中,弹簧关节主要由两个属性控制:距离和频率。距离指的是弹簧的“首选”长度,即压缩或拉伸之后,弹簧应当恢复到的长度。频率指的是弹簧的“刚度”,较低的值意味着弹簧更松。
为设置 Rope 中使用的弹簧关节,执行下面的步骤。
(1) 添加绳索关节。选择 Prototype Leg Rope。这是右上腿部精灵。
(2) 向其添加弹簧关节。添加一个 Spring Joint 2D。将其Anchor(蓝色圆圈)移动到靠近腿的一端。不要移动 Connected Anchor(即移动蓝色圆圈,不移动蓝点)。图 4-14 显示了地精的锚点位置。
图 4-14:添加精灵关节,以将腿部连接到绳索;关节的Anchor靠近脚趾
(3) 配置关节。关闭Auto Configure Distance,将关节的Distance设为0.01,将Frequency 设为5。
(4) 运行游戏。地精将在屏幕中部悬荡。
最后一步是缩小地精,使其以合适的大小显示在其他关卡对象旁边。
(5) 缩放地精。选择父Gnome对象,将其Scale值的x和y值改为0.5。这将使地精缩小一半。
现在就准备好了地精,可以添加绳索了。
绳索
绳索是游戏中第一个需要用到代码的地方,其原理如下。绳索是游戏对象的一个集合,每个游戏对象都具有刚体和弹簧关节。每个弹簧关节链接到下一个Rope对象,该对象又链接到下一个Rope对象,一直链接到绳索顶端。最上面的Rope对象链接到一个位置固定的刚体,从而保持自己固定在一个位置。绳索另一端连接到地精的一个组件:Rope Leg对象。
为创建绳索,首先需要创建一个对象,作为绳索每一段的模板。然后,创建另外一个对象,它将使用此绳段对象和一些代码来生成整条绳索。执行下面的步骤来准备Rope Segment。
- (1) 创建Rope Segment对象。创建一个新的空游戏对象,命名为Rope Segment。
- (2) 向该对象添加刚体。添加一个Rigidbody 2D,将其Mass设为0.5,这样绳索将有一些重量感。
- (3) 添加关节。添加一个Spring Joint 2D组件,将其Damping Ratio设为1,Frequency设为30。
可以自由尝试其他值。我们发现,上面设置的这些值能够让绳索比较有真实感。游戏设计的关键就在于不断调整数字。
- (4) 创建一个使用此对象的预设。打开Assets窗格中的Gnome文件夹,将Rope Segment对象从Hierarchy窗格拖放到Assets窗格。这将在Assets文件夹中创建一个新的预设文件。
- (5) 删除原来的Rope Prefab对象。现在已经不需要原来的对象了:我们马上编写代码来创建Rope Segment的多个实例,并把它们连接成整条绳索。
现在来创建Rope对象。
- (1) 创建一个新的空游戏对象,命名为Rope。
- (2) 改变Rope的图标。因为游戏没有运行时,场景视图中是看不到绳索的,所以我们需要为绳索设置一个图标。选择新创建的Rope对象,然后单击Inspector左上角的立方体图标(如图 15所示)。
图15:为Rope对象选择一个图标
选择红色的圆角矩形,Rope对象将在场景中显示为一个红色的药片形状的对象(如图16所示)。
- (3) 添加刚体。单击Add Components按钮,向对象添加一个Rigidbody 2D组件。添加此刚体后,在 Inspector 中将Body Type改为Kinematic。这将把对象固定在该位置,从而不会下落——这正是我们想要的效果。
- (4) 添加一个线渲染器。再次单击Add Component按钮,添加一个LineRenderer。将新线渲染器的Width设为0.075,使其具有好看的、细细的绳索外观。保留线渲染器其余设置的默认值不变。
图16:选择图标后,Rope对象将出现在场景中
现在就设置好了绳索的组件,可以编写脚本来控制它们了。
编写控制Rope的代码
此处看过了,不需要内容
Rope.cs
1 | using UnityEngine; |
创建地精的代码
BodyPart.cs
1 | using UnityEngine; |
Gnome.cs
1 | using UnityEngine; |
设置GameManager
1 | using UnityEngine; |
背景
(1)更新摄像机的大小。选择Main Camera对象,将摄像机的Ortho Size设为7,这将给玩家足够觉的视野,以便看到整个关卡。
(2)更新摄像机的限高。我们已经修改了摄像机能够看到的范围,还需要调整摄像机的限商。将摄像机的Top Limit改为11.5
我们还需要调整Bottom Limit,但是这里选择的值取决于井有多深。
确定这个值最好的方法是把地精下降到最低的地方。如果在到达井底之前,摄像机就停止移动,则减小Bottom Limit,如果摄像机超出了井底(显示了蓝色的背景),则增大
Bottom Limit. 在停止游戏之前,要记下这个值,因为游戏结束后会重设为原始值。停止游戏后,把刚才记下的数字输入Bottom Limit字段中。
用户界面
现在是时候改进游戏的UI了。前面在设置界面时,使用了Unity提供的标准按钮。虽然它们能够提供必要的功能,但是不太符合这个游戏的观感,因此需要用更好的东西来替换按钮图片。
另外,当地精到达井口时,需要显示一个Game Over画面;当玩家暂停游戏时,显示另外一个画面。
在继续设置之前,确保导入了本节需要用到的精灵。导入精灵的Interface文件夹,将其添加到Sprites文件夹中。
这些精灵被设计成高分辨率的图片,以便用在各种不同的场景中。为了使其在游戏中能用作按钮,将其添加到Canvas中时,Unity需要知道它们应该是什么尺寸。这可以通过调整这些精灵的Pixels Per Unit值做到,当把精灵添加到UI组件或者精灵渲染器时,该值控制着它们的比例。
选择Interface文件夹中的全部图片(但不要选择You-Win)以配置精灵。将Pixels Per Unit值改为2500。
首先处理当前位于窗口右下角的Up和Down按钮,将其更新为更美观的图片。为此,需要移除按钮上的标签,并调整每个按钮的大小和位置,以适应它们的新图片。需要执行的步骤如下所示:
(1)移除Down按钮的标签。找到Down Button对象,移除其Text子对象。
(2)更新精灵。选择Down Button对象,将Source Image属性改为Down精灵(位于Interface文件夹中)。
单击Set Native size按钮,按钮会调整自己的大小。
最后,调整按钮的位置,使其仍然位于画面的右不角。
(3)更新Up按钮。为Up按钮重复相同的过程。移除Text子对象,并将Source Image改为Up精灵。接下来,单击Set Native Size按钮,并更新其位置,使其位于Down按钮的上方。
(4)测试游戏。按钮仍然能够工作,看起来效果也更好了(如图18所示)。
图18:更新后的Up和Down按钮
现在把这些按钮分组到一个容器中。这么做有两个原因:首先,让UI整洁有序是个好主意;其次,把按钮分组到一个对象中,能够同时启用和禁用它们。后面章节中实现Pause菜单时,这会很有用。执行以下步骤来进行设置。
(1)创建按钮的父对象。创建一个新的空游戏对象,命名为Gameplay Menu,设为Canvas的子对象。 (2)设置对象,使其填充整个画面。将Gameplay Menu的锚点设为水平和垂直拉伸。单击左上角附近的Anchors,然后单击弹出菜单右下角的选项(如图7-19所示)。然后,将Left,Top,Right和Bottom设为0,这将使整个对象填充其整个父对象(即Canvas,这样整个对象就将填充整个Canvas)。
图7-19:将对象的锚点设为水平和垂直拉伸
(3)将按钮移动到Gameplay Menu对象中。将Up按钮和Down按钮在Hierarchy中的条目拖放到Gameplay Menu对象中。 接下来将创建You Win画面。该画面向玩家显示一个图片,以及一个让玩家再次玩游戏的按钮。为了准备此画面,执行下面的步骤。
(1)为Game Over画面创建容器对象。创建一个新的空游戏对象,命名为Game Over,设为Canvas的子对象。 按照设置Gameplay Menu对象的步骤,使其水平和垂直拉伸。 (2)添加Game Over图片。通过打开GameObject菜单,选择UI-Image,创建一个新的Image游戏对象,设为刚才创建的Game Over对象的子对象。 将新的Image对象的锚点设为水平和垂直拉伸。将Left和Right边距设为30,将Bottom边距设为60,这将在图片周边添加一些填充,并确保它不会遮盖我们将要添加 的New Game按钮。 Image 的Source Image属性设为You Win精灵,并打开Preserve Aspect选项以防止其被拉伸
无敌模式
电子游戏中出现作弊码,其实源于一个非常实际的需求。构建游戏时,必须击败游戏中包含的各种陷阱和谜题来到达想要测试的特定部分,这个过程可能变得非常枯燥。为了加快开发进度,常见的做法是添加工具来修改游戏的玩法:射击游戏常常包含一些作弊码,让敌人不攻击玩家;策略游戏则可以添加作弊码来禁用战争迷雾。
我们的游戏也不例外:在构建游戏时,不应该每次运行游戏都必须应对每个障碍。为此,我们将添加一个工具来使地精变得无敌。
此功能将实现为一个复选框(有时叫作开关,toggle),显示在画面的左上角。开启该选项后,地精不会死亡。它仍然会受到伤害,显示下一章将添加的粒子效果,这对于测试很有用。
为了保持整洁有序,我们将把此复选框包含在一个容器对象中,就像其他UI组件一样。首先创建这个容器。
(1)创建Debug Menu容器。创建一个新的空游戏对象,命名为Debug Menu,设为Canvas的子对象。将其锚点设为水平和垂直拉伸,并将Left、Right、Top和Bottom边距设为0,使其填满画面。
(2)添加Invincible(无敌模式)开关。打开GameObject菜单并选择UI->Toggle,创建一个新的Toggle对象,命名为Invincible。
将新对象的锚点设为Top Left,并将其移动到画面的左上角。
(3)配置开关。选择Lable对象,这是刚才添加的开关的子对象,并将其Text组件的颜色设为白色。将标签的文本设为Invincible。
将Toggle对象的Is On属性设为关闭。
完成之后,开关应该如图23所示。
图23:显示在画面左上角的Invincible复选框
(4)将开关连接到Game Manager。通过单击+按钮,在Invincible开关的Value Changed事件中添加一个新条目。将Game Manager拖放到显示的框中,并将函数修改为GameManager.gnomeInvincible。现在,当开关的值改变时,gnomeInvincible属性也会改变。
(5)测试游戏。玩游戏,并开启Invincible。现在,即使地精触碰到陷阱也不会死亡。
主菜单
现在,游戏的核心部分已经完成并优化。接下来将构建一些所有游戏都需要的功能,而不是Gnome’s Well特有的功能。也就是说,我们需要一个标题画面,以及从标题画面进入游戏的方法。
这部分将作为一个单独的场景实现,以保持游戏的独立性。因为菜单是比完整的游戏更简单的场景,所以菜单的加载会比整个游戏更快,让玩家能够更快地看到一些东西。另外,菜单将在后台开始加载游戏。当玩家触摸New Game按钮时,游戏将完成加载并切换场景。二者结合起来产生的效果是,游戏看起来启动更快。设置步骤如下。
(1)创建一个新场景。将新场景命名为Menu。
(2)添加背景图片。打开GameObject菜单,选择UI->Image。将图片的Source Image设为Main Menu Background精灵。将图片的锚点设为垂直拉伸,并水平居中。将x位置设为0,Top边距设为0,Bottom边距设为0,宽度设为800。
打开图片的Preserve Aspect,以防止其拉伸。
Inspector现在看起来应该如图9所示,背景图片应该如图10所示。
图9:主菜单背景图片的Inspector
图10:背景图片
(3)添加New Game按钮。打开GameObject菜单,选择UI->Button。将此对象命名为New Game。将按钮的锚点设为bottom-center。接下来,将x位置设为0,y位置设为40,宽度设为160,高度设为30。将按钮Lable的文本设为New Game。完成之后,按钮应该如图11所示。
图11:添加按钮后的菜单
加载场景
当玩家触摸New Game按钮时,我们想显示一个叠加画面,告诉玩家游戏正在加载。执行下面的步骤进行设置。
(1)创建叠加画面对象。创建一个新的空游戏对象,命名为Loading Overlay,设为Canvas对象的子对象。
使叠加画面的锚点垂直和水平拉伸,并将Top、Bottom、Left和Right边距设为0。这将使其填充整个屏幕。
(2)添加一个Image组件。在仍然选中Loading Overlay对象的情况下,单击Add Component按钮,为其添加一个Image组件。画面将填充为白色。
将Color属性改为黑色,并设置透明度为50%。现在叠加画面将成为半透明的黑色画面。
(3)添加一个标签。添加一个Text对象,设为Loading Overlay的子对象。将标签的锚点设为水平和垂直居中。将Left、Top、Right和Bottom位置设为0。
接下来,增加Text组件的字号,并使文字垂直和水平居中。将颜色设为白色,将文字设为“Loading…”。
设置好叠加画面后,接下来添加代码。这些代码负责实际加载整个游戏,以及在玩家触模New Game按钮时切换场景。为方便起见,我们将把这段代码添加到Main Camera中,不过如果你愿意,也可以添加到一个新的空游戏对象上。设置步骤如下。
在Main Camera中添加MainMenu代码。选择Main Menu,添加一个新的C#脚本,命名为MainMenu。
在MainMenu.cs中添加下面的代码:
1 | using UnityEngine; |
Main Menu的脚本负责两个工作:在后台加载游戏场景,以及响应玩家触摸New Game按钮的操作。在Start方法中,让SceneManager在后台开始加载场景。结果作为一个Asyncoperation对象(即sceneLoadingOperation)返回,我们可以使用此对象控制如何加载。这里我们告诉sceneLoadingOperation,加载完成时不要激活新场景。这么做意味着,当加载完成时,加载操作将会等待,直到用户准备好进入下一个菜单。
切换到下一个菜单的操作是在LoadScene方法中完成的,当用户触摸New Game按钮时就会调用此方法。首先,将会显示刚才设置的loading(加载)叠加画面。然后,告诉场景加载操作,在加载完成后可以激活场景。这么做意味着,如果场景已经完成加载,它会立即显示;如果场景还没有完成加载,它会在加载完成后立即显示。
以这种方式设置主菜单,意味着整个游戏看起来加载得更快。因为主菜单需要加载的资源比主体游戏更少,所以会更快显示出来。当主菜单显示时,用户还要花些时间来点击New Game按钮。游戏将在此时加载新场景。不过,因为用户不必盯着一个“请等待”画面,所以相比直接启动游戏而言,这种方式感觉加载得更快。
执行以下步骤。
(1)配置Main Menu组件。将Scene to Load变量设为Main(即游戏主场景的名称)。将Loading Overlay变量设为刚才创建的Loading Overlay。
(2)使按钮加载场景。选择New Game按钮,使其运行Main Camera的MainMenu.LoadScene函数。
最后,需要建立构建的场景列表。Application.LoadLevel及其相关的函数只能加载构建的场景列表中包含的场景,也就是说需要确保其中包含Main和Menu场景。设置步骤如下。
(1)打开Build Settings窗口。打开File菜单,然后选择File->Build Settings。
(2)将Main和Menu场景添加到Scenes In Build列表中。将Main和Menu场景文件从Assets文件夹拖放到Scenes In Build列表中。确保Menu是列表中的第一项,因为这是游戏启动时应该显示的场景。
(3)测试游戏。运行游戏,单击New Game按钮,你将进入游戏。