Unity官方教程 2D UFO(下)

2D UFO 游戏

前言

Unity官方教程 2D UFO(上)中,我们学会了:

  • 新建一个项目Project
  • 从资源商店下载素材包
  • 新建一个GameObject
  • 给UFO添加刚体组件(Rigidbody 2D)和脚本(Script),让我们通过方向键或者WASD来控制UFO移动

我们会看到一个问题,UFO随便移动几步就会从平台掉下去,看也看不见追也追不着。我们可以给平台添加一圈围墙来防止这种情况的产生。那么这一节我们将学会以下内容:

你将学会操作什么?

  • 如何制作围墙防止UFO从平台掉下去
  • 如何让摄像机跟随UFO移动
  • 添加“旋转小马达”——金币
  • 制作预制件Prefab
  • 实现UFO吃掉金币
  • 添加计分板和游戏结束提示
  • 如何发布游戏到本地

一、添加围墙防止UFO掉出平台

代入到现实生活里面,人和围墙之间会发生什么使得人不能直接穿越围墙到外面去?机智的A同学可能想到了:物理碰撞。Unity里要想拥有类似围墙的效果,其实可以通过给BackgroundPlayer分别添加碰撞器来实现。

把目光放回到Scene窗口,可以看到Background整个平台四条边的格子是特殊颜色和材质,这个意味着把墙设置在这4个区域是比较合适的。那么我们先来添加第一面墙吧!

选中Background,通过Add Component-->Physics 2D-->Box Collider 2D,就可以给平台添加一个碰撞器组件(墙是方形的所以选择Box)。

Box Collider 2D

碰撞器默认是包裹在Background外围,在Scene窗口可以看到一圈原谅色在平台边缘。把Box Collider 2D组件的Offset内的X设置为-14.26,SizeX改为3.3,可以看到绿色碰撞器区域变成是在平台最左侧一列格子,这一面墙就添加好了。

碰撞器设置

有两种办法添加其余三面墙:

  • 新增法:和添加第一面那样,Add Component-->Physics 2D-->Box Collider 2D
  • 复制法:在已有的Box Collider 2D组件的右上角小齿轮里选择Copy Component,然后再点开一次,选择Paste Components As New
复制组件

参考数值:

  • 右:Offset,X为14.26,Y为0;Size,X为3.3,Y为31.64
  • 上:Offset,X为0,Y为14.26;Size,X为31.64,Y为3.3
  • 下:Offset,X为0,Y为-14.26;Size,X为31.64,Y为3.3
四面墙添加完毕

最后一步,给Player添加碰撞器Circle Collider 2D。添加之后双击Player可以快速定位到UFO,清晰地看到UFO外面那一圈原谅色。

Circle Collider 2D

修改Circle Collider 2D里面的Radius值可以调整碰撞区域,在这里设置为2.15是比较合适的。
这些都完成之后,运行游戏看看,现在UFO不会再飞出去了吧?(o゚▽゚)o

二、让摄像机跟随UFO移动

有丰富游戏经验的同学都知道,在游戏里面,主角总是处于画面中心的,换句话说就是摄像机应该是跟随主角移动,保持主角万众瞩目状态。很好,那怎么样才能让摄像机跟随UFO走起来呢?可能机智的A同学又想到了:把摄像机变成UFO的小弟(子对象),这样UFO移动,摄像机也会跟着变化。就听你一次,来试试看

把摄像机拖动到Player下面变成它的子对象

然后运行游戏看看效果怎么样:

大家来转圈圈

A同学????
的确,摄像机是跟随UFO移动了,但是变动地不止是位置,它的角度也跟随UFO变化了,所以就会如图一样出现天旋地转的情况。我们想要的效果只是想让摄像机的位置跟随UFO移动,不需要角度变化。这条路走不通,那么只能通过脚本了。

先把Main Camera从Player移出去,然后给摄像机添加一个脚本CameraController,脚本语言是C Sharp。

添加脚本之后记得先把脚本移动到Scripts文件夹,好习惯尽早养成。

脚本代码如下:

CameraController

简单解读下代码含义:

  • 首先定义了一个public的GameObject变量player,这个变量是用来告诉程序,摄像机会跟随哪个GameObject来移动
  • 然后定义一个private的Vector3变量offset,这个变量用来记录游戏初始化的时候,摄像机和UFO之间的距离
  • Start方法中,摄像机和UFO的位置差赋值给offset变量,有了这个固定值才能在后续UFO移动的过程中,UFO和摄像机的距离保持不变
  • 最后在LateUpdate方法中,把摄像机的新位置变更为球体的新位置加上固定的offset偏移位置

保存脚本,回到Unity编辑器页面,我们会发现摄像机的脚本组件中,多了一个Player属性。

Player

这就是刚才我们在脚本内定义的public属性player

在Unity脚本里,public属性会在编辑器内显示,需要填充内容才可正常运行。

把UFO拖动到Player属性中,如图:

Player

运行游戏,现在再撞墙,摄像机也不会翻跟斗了。

拖好的样子

三、添加“旋转小马达”——金币(Pickup)

万事俱备,就只差一些金币让我们的主角UFO去碰撞和拾取了。为了让金币更加耀眼,为了UFO能看见,我们让金币可以自动旋转起来。
首先我们把Sprites内的Pickup拖到Hierarchy窗口,添加一个新的GameObject——Pickup。把Pickup的Sorting Layer改成Pickups之后,因为UFO的Player层级比较高,他俩都在同一个位置(原点),所以我们看不见新增的金币。为了方便查看金币,我们可以暂时把UFO隐藏起来。

隐藏Player

在这里因为Pickup的名字和位置都刚好不需要修改,所以我没提到双标动作,但是一般添加GameObject之后最好是要改名和重置Transform的。

之后我们给这个金币添加一个自动旋转的脚本(记得放到Scripts文件夹),脚本名称为Rotator,脚本内容就一句代码,如下图:

Rotator

简单地说,就是调用transform下的Rotate方法按指定的角度(围绕Z轴旋转45°)旋转一个物体。

放在Update()函数中的代码是以帧来执行的,因为我们需要金币的旋转是以秒来执行,所以需要乘以Time.deltaTime增量时间。

保存脚本,运行游戏,可以看到金币变成“旋转小马达”了(。◕ˇ∀ˇ◕)~

四、制作预制件Prefab

为了丰富游戏,我们可以做多个金币让UFO拾取。这个可以通过制作预制件(Prefab)来实现。那什么是Prefab呢?举个可能不是太贴切的例子,就是我们生活中的样本,比如某辆车的A系列的模型,根据这个模型可以生产出很多一模一样的车辆(金币)。然后只要修改这个模型的参数,那么这个修改就会作用到所有由该模型生产出来的车辆上。

由上可以总结出预制件的好处主要是:

一处修改,全部生效:修改Prefab的属性之后,所有使用这个Prefab的对象的属性也会跟着变化。

炒鸡方便的好吗?
制作Prefab的方法也很简单。不过根据资源管理原则,我们先做两件事

  • 在Assets文件夹创建Prefabs文件夹来存放Prefab文件
  • 在Hierarchy窗口下,通过Create-->Create Empty创建一个空的GameObject对象,重命名为Pickups,reset Transform,然后把Pickup拖到Pickups下成为它的子对象。后续新增的金币对象都放在其下,好方便管理。
Pickups

Pickup拖到Prefabs文件夹,一个预制件就做好了。可以看到Pickup这个对象的名字也变成蓝色了。

制作Prefab
做好的Prefab

接下来有2个办法可以通过预制件制作其他金币。

  • 选中Pickup对象,按CTRL+D可以复制出一个金币对象,按多少次就复制多少个(推荐这个方法)
  • 把Prefabs文件夹里面的Pickup预制件拖到Pickups下就可以生成一个金币对象

在Scene窗口,鼠标左键拖动这些金币可以把它们随意放到自己觉得合适的地方。

金币群

我一共放了13个金币,中间位置留给UFO,同学可以把UFO显示出来了~

五、UFO拾取金币

接下来要实现UFO碰到金币的时候就拾取这个功能。关键词是“碰到”、“拾取”,那么它们分别意味着什么?

  • 碰到,也就是碰撞检测(两者都存在碰撞组件才能进行检测)
  • 拾取,UFO发现自己碰撞的是金币而不是墙的时候,让金币消失或者不显示就可以了。

很好,理清了思路,接下来就来看看怎么实现吧。

第1步:金币Pickup添加碰撞器

选中Pickups下的任意一个对象比如Pickup,通过Add Component-->Physics 2D-->Circle Collider 2D添加好碰撞器,然后双击Pickup定位放大,可以很清楚地看到金币周围的一圈绿色。

Pickup的碰撞器区域

放大的情况下好调整碰撞器区域大小。在这里把Radius值设置为0.93是比较合理的,如果有强迫症的同学可以调整Offset值来调整中心点。

合身的绿衣服

这样就给一个金币添加好了碰撞器了,可是我们还有12个金币也需要添加碰撞器怎么办?在这个添加好碰撞器的金币对象的Inspector窗口右上角有一个Apply按钮,点一下就可以把这个金币的设置同步到其他金币和预制件了。

Apply很方便,这就是预制件的好处,容易管理

第2步:编写脚本实现拾取功能

通过查官方API手册我们可以查到有个名为OnTriggerEnter的方法可以在UFO碰到金币的时候调用。另外前面也提到了,UFO是要判断碰撞到的东西的,因为不能什么东西都拾取,所以需要给拾取的金币添加一个标记(Tag)。
添加Tag的方法:

  • 一共13个金币,每个金币都添加是很麻烦的事情,这时候可以直接修改预制件Prefab就可以全部生效了。
  • 选中Prefabs内的Pickup,然后在Inspector的Tag里面选Add Tag,命名为PickUp(如果列表有PickUp那就无需再加了)
Add Tag
点加号输入新Tag名
  • 然后将预制件Pickup的Tag设置为“PickUp
Tag设置为“PickUp”

接下来就是编写脚本来实现拾取功能。打开UFO的PlayerController脚本,新增以下代码:

拾取代码
  • OnTriggerEnter方法是检测物理发生碰撞的时候调用执行里面的代码,参数other变量表示UFO碰到的其他2D碰撞器
  • 先调用CompareTag方法判断碰到的这个对象是否被标记了Tag"PickUp",如果是的话则调用SetActive把这个对象设置为未激活状态(不显示),也就是false

编写完毕,保存脚本,回到Unity编辑器页面,运行游戏看看。

......机智的A同学大喊:哈哈哈哈,还是碰撞了,并没捡起来!

(尴尬.jpg)这是因为,我们没有把金币设置成碰撞触发器(Is Trigger)。把金币设置成触发器之后,在碰撞的时候才会执行脚本里面的OnTriggerEnter等方法。在预制件上勾选之后,再运行游戏,现在可以正常拾取金币了。

Is Trigger

第3步:优化性能

现在看起来一切正常,好像并没有什么问题。但,实际上真的如此么?

  • 在Unity的物理引擎中,静态的碰撞体(没有刚体)会被单独进行运算并保存在缓存中,节约计算资源优化性能。
  • 所以如果我们移动或者旋转一个不带刚体的碰撞体(金币)的话,这个缓存会被重新计算生成,这会耗费一定的资源。
  • 所以我们最好给金币添加上刚体(变成动态碰撞体),那么它的旋转不会导致缓存在每一帧都被刷新,一定程度上可以达到节约资源的目的。

那好,我们给Prefab Pickup 加上Rigidbody 2D,然后运行游戏试试。

给金币预制件添加刚体

就像天上掉下很多金色饺子一样,金币都受到了重力掉下来了。的确可以和之前UFO一样,把Rigidbody 2D的Gravity Scale改成0就不会掉下来,但这只能解决部分问题。我们希望的是金币不仅仅不受重力影响,也不受其他物理作用力的影响。而这可以通过修改Rigidbody 2D组件的Body TypeKinematic来实现。

Kinematic

Kinematic:开启运动学,开启后不再受力的影响,只能通过Transform属性来操作。

六、添加计分板和结束提示

第1步:添加计分板

游戏完成了基本玩法了,但是我们还需要做一个计分板来鼓励玩家多多拾取金块。关键词,“分”和“计分板”,也就是说我们需要做两个事情:

  • 定义一个变量来保存玩家的分数(捡取的金币数量)
  • 把这个分数显示在UI上

那么我们来修改下PlayerController脚本,内容如下:

分数count

三行代码:定义一个变量count用来保存分数,在Start方法里count值初始化为0,最后拾取金币的时候,count数量+1。

count++是一种简写,效果等同于 count +=1,也等同于count = count +1

分数有了,还需要一个UI展示给玩家。保存脚本,回到Unity编辑器,创建一个UI Text

UI Text

改名为Count Text,重置下Transform,双击Count Text定位放大,鼠标左键把它拖到合适的位置,比如屏幕左上角。

Count Text

Inspector的Text组件内的属性可以修改UI的展现。Text是默认文字内容,Font Size是字体大小,Color是字体颜色,可以自己试着修改。

接下来再次修改PlayerController

计分板UI代码
  • 最上面的命名空间,我们需要引入UnityEngine.UI,这样后面代码才会识别Text类型的变量
  • 定义countText变量来保存UI Count Text
  • 接着我们在Start方法中调用setCountText方法,来更新countText的内容
  • 然后我们在每次UFO拾取金币的时候,也更新countText的内容
  • 最后是我们定义的setCountText方法,里面调用的ToString方法是让int类型的count转换成字符串

保存脚本,回到Unity,把Count Text UI 拖入到Player里面的Count Text属性框里面。

计分板

做完这些运行游戏看看效果!

第2步:添加游戏结束提示

为了让游戏更加友好,在玩家拾取完毕所有金币之后,应该提示玩家通关了。首先我们也需要先创建一个文本UI(Win Text),字体18号,黄色,位置在UFO上方,这应该是个不错的选择。

Win Text

回到PlayerController添加代码:

Win Text代码
  • 定义winText变量来保存UI Win Text
  • 接着我们在Start方法中初始化winText为空字符串,因为游戏开始的时候这个内容是不显示的
  • 最后我们在setCountText方法里面,判断当分数大于等于13的时候,就更新winText的内容为“You win !”

这个13是因为我的金币数量最多是13,同学可以根据自己的金币数量来修改这个数字。

保存脚本,回到Unity,把Win Text UI 拖入到Player里面的Win Text属性框里面,再运行游戏就可以看到效果了。

七、本地发布游戏

游戏制作完毕,可以发布游戏到本地了。呼(๑>ڡ<)☆不容易啊,不过最后一步最简单......保存场景,通过菜单栏File-->Build Settings打开发布页面。

Build Settings
  • Platform选择第一项,PC,Mac&Linux Standalone
  • 点击Add Open Scenes按钮,把当前场景添加进去并且勾选
  • 点击Build按钮,选择存放路径,就可以完成发布了
    找到保存路径下的exe文件双击运行就可以开始捡钱了!ヾ(◍°∇°◍)ノ゙
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342

推荐阅读更多精彩内容