- 创建一个新的项目(New Project)
- 创建第一个游戏场景(Scene)
- 添加游戏对象——平台(Plane)
- 添加我们的主角——球体(Sphere)
- 添加灯光(Light)
- 让球体动起来——添加脚本(Script)和刚体(Rigidbody)
- 编写脚本
- 让摄像头跟随球体移动
- 制作围墙防止球体跑出平台
- 添加一个旋转的方块
- 制作一个Prefab和使用Global模式
- 让球体拾取方块
- 制作一个计分板
- 发布游戏
一、创建一个新的项目(New Project)
第1步:通过File->New Project菜单打开创建新项目对话框
第2步:确定项目名称、存放路径以及游戏模式
- Project name:项目名称
- Location:项目存放路径
点击Create project按钮创建新项目。
第3步:观察下创建后的编辑器界面
有可能你创建出来的项目视图布局不是上图所示,你可以通过编辑器右上角的layout按钮来选择视图布局,上图的布局是选择的2 by 3模式,还有其他模式,可以自己选择来体验一下
二、创建第一个游戏场景(Scene)
第1步:创建一个文件夹来存放游戏场景文件
unity中,所有的游戏资源文件都放在Assets文件夹下面,为了便于管理游戏资源文件,我们一定要对游戏资源进行合理的分类,这一点很重要,尤其是后期游戏资源文件多起来的时候,合理的分类能帮你更好的管理资源,所以我们首先创建一个名为_Scenes的文件夹,来存放游戏场景文件。
创建方法有2种:
- 通过Create按钮创建,我们在Project窗口中,选中Asset文件夹,然后点击Create弹出下拉菜单,在菜单中选中Folder,如下图:
- 通过右键弹出创建菜单,个人觉得这种方式会更加便捷一些
第2步:保存当前游戏场景
- 我们通过File->Save Scene来保存当前游戏场景,你也可以通过快捷键【Cmd + S】来保存。(PS:windows用户快捷键为【Ctrl + S】)
- 然后给Scene命名和制定存放路径,记住,这里一定要将场景文件保存在_Scene文件夹下面,我们要从一开始养成良好的习惯
三、添加游戏对象——平台(Plane)
保存了游戏场景后,我们就可以开始在场景中添加一些我们所需要的游戏对象了,我们第一个需要添加的就是游戏进行的平台,这里我们使用的是unity自带的Plane对象,添加一个游戏对象(GameObject)有3种方法
- 第1种:通过菜单GameObject->3D Object->Plane来创建,如下图:
- 第2种:通过Hierarchy窗口中Create按钮来创建,如下图:
- 第3种:通过右键菜单创建,我们在Hierarchy窗口中单击右键会弹出菜单,如下图:
平台对象创建成功后,我们最好给他起一个好的名字,来解释它的作用,我们可以给所有个游戏对象重新命名,命名的方法有2种:
- 在Hierarchy窗口中缓慢的双击对象名称
- 在Hierarchy窗口中选中你要修改名称的GameObject后,然后按回车键
在这里我们将平台的名称修改为Ground。
名字修改完成后,我们还需要做一个很重要的事情(官方强力推荐),我们把平台的Transform属性给重置(reset)一下,我们在Inspector窗口中找到Transform组件,然后点击它右上角的小齿轮,选择reset选项,如下图:
这个重置操作,官方是建议每次我们添加新的GameObject后最好都做一次,好的习惯我们尽早培养
平台添加成功后,我们可以对其的属性进行一些调整,例如我们调整一下平台的大小,将目光锁定到Scene窗口,我们可以在其中可直观的来修改平台的属性,这里有3个很实用的快捷键可以使用:
- W:切换到移动模式,该模式下我们可以任意拖动平台,改变它的位置
- E:切换到旋转模式,该模式我们可以任意旋转平台,改变它的角度
- R:切换到缩放模式,该模式下我们可以任意缩放平台,改变它的大小
当然我们也可以直接在Transform里面直接输入想要的数值,在本例中,我们把平台的Scale X和Z的数值设置为2
Tips:先选中一个GameObject,然后点击F快捷键,可以在Scene窗口将摄像机对准你选中的GameObject,方便你快速定位
四、添加我们的主角——球体(Sphere)
有了平台后,制作Roll-a-Ball游戏我还需要一个球体,我们可以通过方向键来控制球体移动,添加球体的方式,和上面添加平台的方式一样,只不过我们选择的是Sphere对象,如下图:
球体对象创建成功后,我们最先要做什么呢?没错,就是官方推荐的做法,我们把球体的Transform属性重置,然后给他起一个好的名字,这里我们将其命名为Player,因为在这个游戏里面,这个球就代表这我们玩家。
重置Transform和命名这两个动作,我们尽量养成好习惯,在创建新的GameObject后,做这两个标准化动作
然后我们选中球体,通过F快捷键,定位到球体,我们会发现此时球有一个半是陷入在平台中的,不要紧,我们通过调节他的Position的Y值为0.5,让它正好处于平台上
五、添加灯光(Light)
这里首先要提一下,因为官方视频中所用的unity版本是4.3,而现在最新的版本是5.2,所以下面的内容会与视频有所不同,我们会以最新的版本为基础来说明
新版中,每个新建的项目,都会自动带有一个平行光(Directional Light),而视频中的版本,灯光是需要我们自己添加的,所以这里我们就不用再添加灯光了,直接修改平行光的属性就可以了
前面在讲场景文件保存的时候,就提到的好的资源分类可以帮助我们更好的管理游戏资源,这里我们对于GameObject的管理也是一样的,而在GameObject中,我们没有文件夹,所以我们使用一个空的GameObject(Empty)来代替文件夹的作用
- 我们首先创建一个空的游戏对象,Create Empty
- 然后将其的Transform重置
- 然后将其名称修改为Lighting
- 最后我们把Directional Light拖入到Lighting
- 这样我们就相当于把Lighting当成一个文件夹,把所有的灯光对象放到这个里面,便于管理
之后,我们为了让球和阴影有个明显的区分,我们在增加一个新的光源,用来照射在球体上,我们创建一个新的平行光(Directional Light),这样我们就有了两个名叫Directional Light的灯光,这样不便于区分,于是我们修改一下灯光的名字
- 先将我们刚刚新建的灯光改名为Fill Light
- 然后把之前那个灯光改名为Main Light
- 然后把Fill Light也拖入到Lighting下面
然后我们选中Fill Light,首先我们将其的灯光颜色设置为红色,这样便于和Main Light区分开来,然后将它的Rotation属性分别调整为-33,-135,180
这样修改后,我们就可以看到球体上一层红色的光泽。
六、让球体动起来——添加脚本(Script)和刚体(Rigidbody)
有了平台,有了球体,有了灯光,下一步我们就应该让球体可以动起来了。unity上手很简单的一个原因,就是他的做法非常符合我们平时生活的逻辑,比如我们这里想让球体动起来,那么按照我们正常的想法,我们要做的事情就是告诉球体,让他动起来,那么装换成unity的实现方法,就是给球体添加一个脚本组件,然后在脚本组件里面告诉他怎么动,下面我们来看看具体的操作
第1步:给球添加刚体
刚体可以给球体添加物理效果,让他可以检测物理碰撞,便于我们后面实现拾取物体和碰撞墙面
给球体添加刚体有2种方法:
- 第1种:通过Component->Physics->Rigidbody添加,如下图
- 第2种:通过Add Component按钮添加,如下图
第2步:给球体添加脚本
首先我们要再提一下开始说到的资源管理思想,为了便于我们管理游戏的资源,所以我们会创建一个文件夹,来专门存放所有的脚本文件,如下图:
要想给球体或者说任何一个GameObject添加一个脚本,我们首先选中GameObject,这里我们选中球体也就是我们的Player,然后在Inspector窗口中点击Add Component按钮,在弹出的菜单中选着New Script
之后会进入脚本名称和语言类型选择,这里我们将脚本命名为PlayerController,然后语言选择C#(C Sharp)
点击Create and Add后,我们就成功给球体添加一个脚本组件,然后我们点击脚本组件右上角的小齿轮按钮,在弹出来的菜单中选择Edit Script便可打开脚本编辑器了
七、编写脚本
下面没有编程经验的同学,可以直接按照例子来抄写代码,后面再来慢慢理解
新打开的脚本会是如下的样子:
我们可以看到,里面有两个方法,Start和Update,在本例中,这两个方法我们展示不用到,我们添加一个FixedUpdate的方法,该方法只在计算有关物理效果是调用,然后代码如下:
这里有两点需要特别说明一下:
- 第1点:上图代码中最后一句,和视频中的不一样,由于unity版本问题,视频中的代码在新版中是无法使用了,所以必须用修改过的代码
- 第2点:上图中用红线标出的语句,我们通过定义public的变量后,该变量可以在编辑器中显示并进行修改,如下图:
在本例中,我们可以将Speed数值设置为500,这是一个比较合理的数值,做完这些之后,我们就可以运行游戏看看效果了!
八、让摄像头跟随球体移动
首先我们选中我们的摄像头(Main Camera),然后我们会看到如下的情况:
在上图中,我们可以看到,在Scene窗口的右下角,也就是图中红框处,有一个小窗口,这个窗口就显示我们此时选中的摄像机所有看到的内容,方便我们调整摄像机的位置,所以我们先拖动摄像机的位置和角度,来处于一个合适的视角,本例中,我们将摄像头的Position的Y和Z分别调至5和-6,然后把其的Rotation的X值调至45,这样摄像机的视角就变成了45°俯视角
视角调整好后,我们接下来要让摄像头跟随球体来移动,我们第一个想到的办法,也是最简单的方法,就是把摄像机变成球体的一个子对象,这样球体移动,摄像机也会跟着变化,好,我们马上做做看
将摄像机变为球体的子对象
然后我运行游戏,看看能否达到我们的效果
天了噜,我们发现摄像头的确是跟着球体移动了,但是它不止位置跟着球体变化,他的角度也会跟着球体变化,这样摄像头就会出现天旋地转的效果,这不是我们想要的效果
Tips: Unity中,子对象的Transform属性会跟随父对象一起进行变化
我们想要的效果只需要摄像机的位置跟随球体移动,角度不需要,所以我们只能用脚本来实现这一效果,首先我们给摄像机添加一个脚本(大家应该还记得如何添加吧,不记得可以回去看第一节的内容,这里就不再重复介绍了),我们给脚本命名为CameraController,脚本语言选择C#。然后我们看看脚本内容:
我们一句句来解读脚本的含义:
- 首先,我们定义了一个public的GameObject变量,这个变量就是用来告诉程序,摄像机会跟随哪个GameObject来移动
- 然后我们定义一个private的Vector3的变量,这个变量我们主要用来记录摄像机初始的位置,用作之后更新摄像机的位置的偏移向量
- 然后我们在Start方法中,摄像机的position数值赋给offset变量,意思是在开始前,用offset变量记录下摄像机的初始位置
- 最后我们在LateUpdate方法中,把摄像机的位置变更为球体的位置加上最开始的偏移位置
这里其实脚本中使用Update方法一样可以达到效果,但是我们使用LateUpdate(最后更新)效率会更高一点
写完脚本内容后,我们保存一下脚本,然后回到Unity编辑器界面,我们会发现摄像机的脚本组件中,多了一个Player属性,如下图:
这就是我们刚刚在脚本中定义的public类型的属性
Tips: 在Unity脚本中,public的属性会在编辑器中显示出来
然后我把把球体拖入到Player属性中,如下图:
接下来我们运行一下游戏,就可以发现摄像机现在可以正常跟随球体移动了
九、制作围墙防止球体跑出平台
摄像机可以跟随球体移动后,我们又看到一个问题,球体如果移动超过平台的边界,就会掉下去,这不太友好,所以我们接下来给平台加上一圈围墙,来防止球体跑出平台,我们新建一个cube对象,然后reset他的Transform属性会发现cube和球体挡住到了一起,这样不方便我们来编辑cube
为了方便编辑cube,我们可以暂时不显示球体,我们选中球体,将球体的Inspector下方的勾选去掉,如下图:
这样一来,球体就展示在我们的Scene窗口中不显示了。接下来我们可以编辑cube的属性,将其的长度设置成和平台一样,然后将其的位置移动到平台北面的边缘,如下图:
然后同样的,我们给平台的南面,西面,东面都制作一堵墙,如下图:
然后在运行一下,可以看到球体就没法跑出平台了
十、添加一个旋转的方块
有了平台,有了球体,接下来我们就需要一个方块,这个方块可以让球体碰撞并拾取,为了让方块变得有吸引力一点,我们让方块可以自动旋转起来,首先我们创建一个cube对象(不要忘记创建GameObject之后的两个标准动作),然后我们将cube命名为PickUp,并把它的Rotation的X、Y、Z值都设置为45,然后将其拖动到一个你觉得合适的位置,比如这样:
之后我们给这个方块添加一个自动旋转的脚本,脚本名称为Rotator,脚本内容如下:
里面我们就添加了一句话,就是红线标记的,Time.deltaTime就是根据时间变化来改变方块的Rotation属性,从而达到旋转的效果,保存脚本,然后运行一下,就可以看到方块自己旋转起来了。
十一、制作一个Prefab和使用Global模式
为了让游戏丰富起来,我们只有一个方块是不够的,因此我们需要多创建几个方块,在这之前呢,我们需要先制作一个Prefab(预制件),制作一个预制件有以下好处:
- 一次制作,重复使用:可以在任何项目中使用Prefab
- 一次修改,全部变化:我们修改Prefab的属性后,所有使用该Prefab的对象属性都会跟着发生变化
而制作Prefab的方法也非常简单,我们为了资源管理方便,先在Assets文件夹下面创建一个Prefabs文件夹来存放Prefab文件,然后拖动Pickup对象到Prefabs,一个Prefab就创建好了
然后我们可以复制PickUp对象,并拖拽新的PickUp到合适的位置,此时你会发现拖拽没有办法保持Y轴不变,因此为了方便我们移动PickUp对象的位置,我们先将Scene视图改为Y轴模式
然后将Local模式改为Global模式
此时我们便可以方便的调整PickUp对象的位置了,最后效果如下:
从图中我们可以看到,一共拥有8个PickUp方块。
十二、让球体拾取方块
接下来我们实现球体拾取方块的功能,我们通过查API得知有一个OnTriggerEnter的方法可以用来在球体碰到物体的时候调用,光有这个方法还不够,我们还需判断球体碰到的是什么东西,我们不能碰到任何东西都拾取,所以我们需要给拾取的方块增加一个标记(Tag),增加标记的方法如下:
- 因为我们场景里面一共有8个方块,如果一个个的设置标记,就有点太麻烦了,还记得上面我们提到的Prefab的第2点好处吗?对了,这边我只需要给Prefab标记就可以了
- 首先我们选中PickUp Prefab,然后在Inspector的Tag里面新增一个Tag,我们命名为PickUp
- 然后我将PickUp Prefab的Tag设置为“PickUp”
接下来我们就可以进行脚本编写了,我们打开球体的PlayerController脚本,然后新增下面的代码
首先这里other变量代表球体碰到的对象,在这个方法里面,我先用if语句判断碰到的对象的Tag是否等于“PickUp”,如果等于,我就将碰到的对象设置为不激活(不显示)
做完这些,我们就可以运行一下游戏,看看效果
…………
…………
…………
咳咳,我们运行了游戏发现,球体碰撞方块并没有将它拾取,这是为什么呢?原因是我们没有将方块设置为碰撞触发器(Is Trigger),只有设置成碰撞触发器,我们才可以的OnTriggerEnter方法才能起效果,我们设置成后,再运行游戏,可以发现,现在球体碰到方块就可以拾取了
十三、制作一个计分板
好了,我们的游戏基本可以玩了,但是我们还需给玩家增加一点刺激,做一个计分板来鼓励玩家多拾取方块,那么实现一个计分板我们需要以下元素
- 用一个变量保存玩家的分数
- 然后将分数显示在UI上面
首先我们修改PlayerController脚本,如下:
上图第一句红线处,我们定义了一个count变量用来保存分数,然后在Start方法中将Count的值设置为0,即我们在游戏开始时,将分数初始化为0,最后我们在拾取方块的时候,把count的数量加1
这里count++是一种简写,其实它的效果等同于**count = count + 1
现在我们有了变量来记录分数,但是我们还没有显示给玩家,所以我们需要一个UI来显示分数,我们创建一个文本UI(Text UI)
然后我们调整Text的位置至屏幕的左上角
接下来我们再次修改PlayerController,如下:
- 在代码最前面,我们需要引入UnityEngine.UI,只有这样后面代码才会识别Text类型的变量,
- 然后我们在定义countText变量来保存UI Text
- 接着我们在Start方法中调用setCountText方法,来更新countText的内容
- 然后我们在每次球体碰到方块的时候,也需要更新countText的内容
- 最后是我们定义的setCountText方法
然后我们保存代码,回到Unity编辑器里面,将Text拖入到Player里面的Count Text属性
做完这些,我们就可以运行游戏,看到效果了!
十四、发布游戏
游戏到这里我们就告一段落了,接来下我们可以尝试将游戏发布到网页,让你的朋友试玩你的游戏,Unity发布游戏非常简单
- 第1步:首先选择File->Build Settings
- 第2步:我们选择Web Player平台,然后点击Switch Platform
- 第3步:我们点击Add Current按钮,将当前游戏场景加入进去
- 第4步:点击Build按钮,然后选择保存路径,就可以完成发布了
最后我们找到保存路径下生成的文件,点击后缀为html的文件,就可以运行游戏了