前言

  为了记录重构笔记的进度,我在Github上创建了一个名为PotatoGloryTutorial的Repository,里面的每个分支都记录着对应文章所做的修改。因为篇幅有限,很多具体的细节不会一一赘述,本篇文章对应的分支为essay1,读者可以将PotatoGloryTutorial这个仓库clone至本地之后切换到essay1分支,以便查看具体的细节。


导入资源

  打开Unity(2017.3.0f3),点击New,创建一个名为PotatoGloryTutorial2D项目:

创建项目
创建项目

  打开Unity界面之后,我们需要导入资源。前面提到过,本项目大部分素材来源于Unity Assets Store上一个免费的package 2D Platformer,因此可以直接在Asset Store上Download并Import。

Asset Store
Asset Store

  需要注意的是,2D Platformer是一个完整的项目,里面还包含了很多脚本,里面有很多写得很不错的代码,有兴趣的读者可以直接下载下来参考。此外,2D Platformer里面还包含已经制作好的AnimationPrefab,不想浪费时间自己从头制作的读者可以直接下载2D Platformer后删除脚本文件,直接使用2D Platformer提供的资源。

  在这里,因为本项目的脚本不完全和2D Platformer一致,所以我们不直接下载完整的项目,而是导入我预先准备好的资源package。下载完成之后,在Unity上方的菜单栏找到Assets选项,点击Assets->Import Package->Custom Package...,然后找到自己下载好的PotatoGlory.unitypackage,然后点击Import导入全部资源。

导入资源
导入资源

调整Unity布局

  在正式开始搭建游戏背景之前,为了提高开发的效率,我们还需要调整一下Unity界面的布局。点击右上角的Layout按钮,会出现一个下拉菜单。

Layout
Layout

  个人最喜欢的布局方案是2 by 3,大家可以根据自己的喜好进行选择。选择2 by 3方案之后,我们还需要做一些小调整,将Project窗口拖动到Hierarchy窗口下方。当然,这个调整只是出于我个人的习惯,读者可以选择不调整,也可以根据自己的喜好调整其他窗口,调整的方法都是鼠标单击窗口上方的选项卡,然后按住不放进行拖动

  调整完成之后,再次点击Layout,选择Save Layout...,将其命名为Favorite,然后点击Save。这样,我们就新建了一个名为Favorite的布局,以后就可以通过选择Favorite来快速恢复到我们现在调整的布局了。我们最终调整完成的布局如下所示:

调整后的布局
调整后的布局

创建游戏场景

  做好前期准备之后,终于进入我们今天的主题——创建游戏场景了。首先,我们右击在Project窗口下的Assets文件夹,然后选择Create->Folder来创建一个名为Scenes的文件夹,用于保存我们的游戏场景。然后直接按快捷键Ctrl + S,将Unity默认打开的Untitled场景保存到Scenes文件夹下,并将其命名为SinglePlayerGameScene.unity

创建游戏场景
创建游戏场景

设置Aspect

  接着,因为我们最后的目标是做成一个Android手机游戏,所以我们还需要Game窗口下设置一个Aspect来预览在手机上运行的效果。这里,我们创建一个固定分辨率为1920x1080的Aspect,并将其命名为Android

设置Aspect
设置Aspect

放置Sprite

  创建好Aspect之后,我们将Sprites\Environment目录下的图片env_bgProject窗口直接拖动到Hierarchy窗口里,可以看到在场景中出现了一张天空的背景图,但在Game窗口中,这张图片的可见范围很小。我们需要调大Main CameraSize,使其能看到更大的范围,这里,我们将其设置为11

调整Main Camera
调整Main Camera

  调整完Camere之后,我们继续通过拖拽往场景里面添加其他的素材。但奇怪的是,在添加素材的过程中,有可能出现后面拖进去的素材在SceneGame窗口里看不到的情况。这是因为在Unity里,摄像机按照从远到近的顺序来渲染物体,后渲染的物体会覆盖在先渲染的物体之上。而对于在摄像机投影方向上距离摄像机距离一样的物体,它们的渲染顺序是随机的

  想要保证物体A物体B之后渲染,我们可以设置物体B在摄像机投影方向上与摄像机的距离比物体A近。在Unity的2D项目中,默认使用的是Orthographic Camera,也就是正交摄像机,其投影方向为Z轴的正方向,默认垂直于屏幕。因此,我们只需要按照物体的前后关系来设置它们的z坐标的大小即可。但如果这样做,当场景中的物体增多时往往会出现记不清其他物体坐标的问题,不仅难以管理,而且效率也低。


Sorting Layer

  为了解决这一问题,Unity在Sprite Renderer组件中提供了Sorting LayerOrder In Layer属性让我们使用。Unity在渲染Sprite时,首先根据按照Sorting Layer的渲染顺序来渲染Sprite,如果两个Sprite处于相同Sorting Layer,那么就按照它们Order In Layer的值从小到大进行渲染。倘若两个SpriteOrder In Layer的值也相同,再按照在摄像机投影方向上距离摄像机距离的距离远近、也就是Z轴上的坐标来渲染。

  选中场景中的env_bg,然后在Inspector窗口,点击Add Sorting Layer...。打开Sorting Layer管理界面后,点击右下角的+创建BackgroundForeground两个Sorting Layer,并用鼠标选中Background将其拖到Default上方。创建完毕之后,已有的Sorting Layer如下所示:

设置Sorting Layer
设置Sorting Layer

  在Unity中,Sorting Layer的渲染顺序为从上到下渲染,也就是说,Unity会先渲染所有Sorting LayerBackgroung的Sprite,然后绘制所有Sorting LayerDefault的Sprite,最后绘制所有Sorting LayerForeground的Sprite。

了解了Sorting Layer的使用之后,我们往场景中添加剩下的所有Sprite,场景中所有的Sprite及其属性如下:

  • env_bg:
    • Position: (0, 0, 0)
    • Sorting Layer:Backgroung, Order In Layer: 0
  • env_cloudTop:
    • Position: (0, 0, 0)
    • Sorting Layer:Backgroung, Order In Layer: 1
  • env_BigBen:
    • Position: (0, 0, 0)
    • Sorting Layer:Backgroung, Order In Layer: 1
  • env_Bank:
    • Position: (0, 0, 0)
    • Sorting Layer:Backgroung, Order In Layer: 2
  • env_RiverBase:
    • Position: (0, -11, 0),Scale(2, 1, 1)
    • Sorting Layer: Backgroung, Order In Layer: 3
  • env_TowerFull:
    • Position: (-22, 0, 0), Scale(1, 1, 1)
    • Sorting Layer: Foreground, Order In Layer: 0
  • env_TowerFull (1):
    • Position: (22, 0, 0), Scale(-1, 1, 1)
    • Sorting Layer: Foreground, Order In Layer: 0
  • env_PlatformBridge:
    • Position: (-12.3, -11.2, 0), Scale(1, 1, 1)
    • Sorting Layer: Foreground, Order In Layer: 1
  • env_PlatformBridge (1):
    • Position: (12.3, -11.2, 0), Scale(-1, 1, 1)
    • Sorting Layer: Foreground, Order In Layer: 1
  • env_PlatformTop:
    • Position: (-14.4, 0, 0), Scale(1, 1, 1)
    • Sorting Layer: Foreground, Order In Layer: 1
  • env_PlatformTop (1):
    • Position: (14.4, 0, 0), Scale(-1, 1, 1)
    • Sorting Layer: Foreground, Order In Layer: 1
  • env_PlatformUfo:
    • Position: (0, -4.62, 0)
    • Sorting Layer: Foreground, Order In Layer: 2
  • env_UfoLegs:
    • Position: (0, -1.44, 0)
    • Sorting Layer: Foreground, Order In Layer: 2

组织场景中的物体

  将所有的Sprite添加进去之后,我们发现场景中的物体太多,不太雅观。为了方便管理,我们可以使用Empty GameObject来组织场景中的物体。在Unity中,Empty GameObject只有Transform这一个组件,可以当作空节点用来组织、管理其他的物体。

  在Hierarchy窗口右击鼠标,选择Create Empty,然后在Inspector窗口将其命名为Background,并ResetTransform组件的属性值。

设置Empty GameObject属性
设置Empty GameObject属性

  接着我们用同样的方法,创建另外一个命名为ForegroundEmpty GameObject,并重置其Transform组件的属性值。创建完毕之后,我们在Hierarchy窗口中,将Sorting LayerBackground的物体拖到空物体Background下成为其子物体,将Sorting LayerForeground的物体拖到空物体Foreground下成为其子物体,最后,Hierarchy窗口的结构如图所示:

场景物体组织结构
场景物体组织结构

后言

  因为这是本系列第一篇讲解项目具体制作过程的文章,有些地方写得比较详细,也用了比较多的截图来说明一些基础操作。在后面的文章中,对于一些已经介绍过、或者比较简单的基础操作,将会使用文字描述。最后,本篇文章所做的修改,可以在PotatoGloryTutorial这个仓库的essay1分支下看到,读者可以clone这个仓库到本地进行查看。


参考链接

  1. Unity的Sprite Renderer组件
  2. Sorting Layer