2.2 飞机移动
要实现飞机移动,首先需要实现显示飞机,然后实现飞机移动,最后实现飞机的左、右循环移动。
2.2.1 显示飞机
下面介绍如何在Unity3D中显示飞机。
1.打开游戏项目资源,新建场景
首先找到光盘中的游戏项目资源——2.太空射击游戏项目资源——SpaceShoot,将整个文件夹SpaceShoot拷贝到系统的C盘根目录,如图2-12所示。
图2-12 SpaceShoot项目文件
然后启动Unity3D软件,如果Unity3D自动打开以前的项目文件,如图2-13所示,则需要单击菜单 “File”,选择 “Open Project” 命令,在如图2-14所示的对话框中,选择 “Open Project”窗格,然后在该窗格中选择文件夹SpaceShoot,这样就可以打开太空射击游戏SpaceShoot的项目资源,如图2-15所示。
图2-13 打开新的项目文件
图2-14 打开新项目对话框
图2-15 打开SpaceShoot项目资源文件
如果Unity3D是第一次运行,以前没有创建游戏项目文件,则会打开如图2-14所示的对话框,选择“Open Project”窗格,并需要单击“Open Other”按钮,打开“浏览文件夹”对话框,在“浏览文件夹”对话框中选择文件夹SpaceShoot,同样可以打开如图2-15所示的运行界面。
在图2-15中,SpaceShoot项目资源文件中包括三个资源文件夹,它们分别是Image、 prefabs和sound。
在Image文件中提供了各种图片,以便实现太空射击游戏项目的各种对象,如飞机、陨石、炮弹以及爆炸的效果帧序列图等,如图2-16所示。
图2-16 Image目录下的各种图片资源
在prefabs文件中,则提供了一个sprite预制对象,用于专门显示2D图片,以便构建游戏场景,如图2-17所示。
图2-17 prefabs目录下的资源
在如图2-18所示的sound文件夹中,提供了各种声音文件,选择相关声音文件,单击图片右下方的播放按钮,可以在Unity3D中直接播放声音。
图2-18 sound目录下的各种声音文件
由此可见,在太空射击这个2D游戏的资源文件中,主要是图片、声音和预制对象。
在图2-15中,首先单击菜单“File”→“New Scene”命令;然后再单击菜单“File”→“Save Scene as”命令,打开如图2-19所示的保存场景对话框,在其中输入Level场景名称,单击“保存”按钮,即可保存该场景。
图2-19 保存场景对话框
保存场景后的项目窗格如图2-20所示。
图2-20 项目窗格中的场景
2.设置游戏窗口分辨率
为方便游戏场景的设计,这里设置游戏的输出界面为固定大小,将游戏窗口的分辨率设置为800×600。
在图2-11中,单击“Build Setting”命令,打开如图2-22所示的构建设置对话框,选择平台“Platform”下拉框中的“PC, Mac & Linux...”,单击下方“Player Settings”按钮,在检视器中出现如图2-23所示的界面。
图2-22 构建设置对话框
图2-23 设置分辨率
图2-21 构建设置
在图2-23中,选择排在第二个的PC分辨率窗格,设置游戏界面的输出大小为分辨率800 ×600,然后关闭如图2-23所示的对话框。
3.设置摄像机
摄像机是Unity3D游戏开发中的一个重要组件。当新建一个场景时,Unity3D会自动生成一个Main Camera摄像机对象。
在图2-15中,选择层次Hierarchy窗格中的Main Camera对象,在游戏场景Scene窗格中,通过相关场景按钮、游戏对象平移按钮,调整摄像机的显示大小和旋转位置,出现如图2-24所示的游戏场景Scene界面。
图2-24 摄象机的形状
在图2-24中,摄象机的形状显示为一个四棱锥体,只有在这个四棱锥体范围内的游戏对象,才能被摄象机所看到,也就是在游戏输出窗格中出现。这个四棱锥体的大小由检视器窗格中的相关参数来决定,如图2-25所示。
图2-25 摄像机参数
在图2-25所示的摄像机Camera组件中,其中的三个参数决定摄像机四棱锥体的大小和形状,它们分别是Field of View视角,默认情况为60度,该角度决定了四棱锥体的角度,相当于真实世界中照相机的广角。如果将视角设置为45度,摄像机的游戏场景Scene界面如图2-26所示;剪切平面Clipping planes中的两个参数为近端平面near和远端平面far,如果设置near为30, far为100,此时摄像机的游戏场景Scene界面如图2-27所示。
图2-26 摄象机形状
图2-27 摄象机形状
从图2-27中可以看出,近端平面near参数决定四棱锥体上截面的位置,远端平面far决定四棱锥体的底面位置。只有在这两个平面之间的四棱锥体内的游戏对象,才能在游戏输出窗口中显示。
在图2-25所示的摄像机参数中,还有一个重要的参数就是投影方式Projection。在默认情况下,Unity3D设置的投影方式为透视投影Perspective,也就是3D投影,其摄像机形状是四棱锥体。
如果设置投影方式Projection为正交投影Orthographic,此时的投影方式则转为2D投影,其摄像机形状是长方体,如图2-28所示。
图2-28 正交投影的摄象机形状
从上述的图2-28所示可以看出,只有在这个长方体内的游戏对象,才能在游戏输出窗格中显示。
需要开发的太空射击游戏项目是一个2D的游戏,这里需要设置投影方式Projection为正交投影Orthographic,其他参数的设置,如图2-29所示。
图2-29 摄像机参数
4.新建Player对象
在项目Project窗格中,选择prefabs文件夹中的sprite对象,直接拖放该对象到层次Hierarchy窗格中,并将该对象的名称修改为Player,如图2-30所示。
图2-30 拖放sprite对象
在成功拖放游戏sprite对象之后,游戏窗格中将会显示该对象,如图2-31所示。但是该对象的显示结果是非常暗淡,这里需要说明的是,光源也是Unity3D中的一个重要组件,而sprite对象,则是专门用来显示2D图片的一个预制件prefab。
图2-31 游戏窗格
下面说明如何设置光源以便照亮上述游戏场景,以便可以看得清楚游戏对象Player。
单击菜单“GameObject”→“Create Other”→“Directuional Light”命令,如图2-32所示,此时就会在游戏场景中创建一个平行光对象,该平行光对象的基本属性可以在检视器中设置,如图2-33所示。
图2-32 创建平行光
图2-33 平行光设置
在图2-33中,设置该平行光的角度为0,以便直射照到Player对象上,至于位置则无关紧要,并不影响游戏的效果,就像太阳的效果一样,只与角度有关,而与位置无关。
设置完成平行光之后,游戏对象Player就变得明亮起来,其效果如图2-34所示。
图2-34 游戏窗格
5.显示飞机Player
在项目Project窗格中,选择Image文件夹中的Player图片,直接拖放该对象到层次Hierarchy窗格中的Player对象之上,如图2-35所示。
图2-35 拖放飞机图片
飞机图片拖放成功之后,就会在游戏窗格中显示出该飞机图片,如图2-36所示。
图2-36 显示飞机
从图2-36中可以看出,尽管原始的飞机图片背景是透明的,可是在Unity3D中显示的飞机却不是透明的。
下面来设置飞机的背景透明化。
在图2-37中,单击飞机图片Shader右边的下拉菜单,在出现的快捷菜单中选择“Transparent”→“Diffuse”命令,就可以将原有的飞机透明背景,设置为在Unity3D中也是透明的背景,显示的飞机Player,如图2-38所示。
图2-37 背景透明化设置
图2-38 显示飞机
2.2.2 飞机移动
要实现飞机移动,开发者需要编写代码,实现游戏对象移动的功能需求;然后将该实现代码拖放到飞机Player对象之上,这样Player就可以执行该代码,实现飞机移动。
1.移动飞机Player
在编写代码之前,首先在Project项目窗格中创建一个“Script”的文件夹,专门存放相关代码。
如图2-39所示,在右键出现的快捷菜单中选择“Create”→“Folder”命令,创建一个新的文件夹“Script”,如图2-40所示。
图2-39 新建文件夹
图2-40 创建“Script”
对于C#开发者来说,在图2-41中,选择Script文件夹,在右键出现的快捷菜单中选择“Create”→“C# Script”命令,创建一个C#文件,该文件名称为PlayerController,如图2-42所示。
图2-41 新建C#文件
图2-42 新建PlayerController.cs文件
对于JavaScript开发者来说,在图2-43中,选择Script文件夹,在右键出现的快捷菜单中选择“Create”→“Javascript”命令,创建一个JavaScript文件,该文件为playerController.js文件,如图2-44所示。
图2-43 新建Javascript文件
图2-44 新建playerController.js文件
对于C#开发者来说,在图2-42中,双击PlayerController文件,Unity3D打开如图2-45所示的代码编辑界面。
图2-45 C#代码编辑界面
在图2-45中书写相关代码,PlayerController的C#代码文件见代码2-1。
代码2-1 PlayerController的C#代码
1: using UnityEngine; 2: using System.Collections; 3: 4: public class PlayerController: MonoBehaviour 5: { 6: 7: void Update() 8: { 9: transform.Translate(Input.GetAxis("Horizontal")*Time.deltaTime,0,0); 10: } 11: }
在上述C#代码中,首先需要注意的是C#的类名称一定要与文件名称一致,这里类的名称为第4行代码中PlayerController,与文件名称PlayerController是一致的。
开发者需要在第7行到第10行之间的Update()中实现相关代码,以便Unity3D逐帧运行Update()中的相关游戏业务逻辑代码。
在第9行中,通过transform对象获得执行该代码的游戏对象Player,然后通过transform对象的Translate方法,实现Player的移动。
在Translate方法中,需要输入一个3D的矢量值,由于只需要实现飞机Player的左、右移动,因此只需要在3D矢量值中设置x的变量,其他2个值保持为0。
在实现沿X变量轴的左、右移动时,为了检测游戏玩家是否按下键盘左、右键,设置了Input.GetAxis("Horizontal")。如果按下了键盘左键,则Input.GetAxis("Horizontal")的值为-1;如果按下了键盘右键,则Input.GetAxis("Horizontal")的值为1。
通过Time.deltaTime,获得每帧之间的时间数值,默认情况下大约为0.02秒。
在图2-46中,选择PlayerController代码文件,拖放到层次Hierarchy窗格中的Player对象之上,如果代码没有编译错误,则可以成功拖放,并在右下角出现PlayerController代码组件;如果代码存在编译错误,不能成功拖放,则需要修改错误代码直到编译成功。
图2-46 拖放PlayerController.cs文件
这里需要说明的是,初学者常常多次重复拖放相同代码,在图2-47中,已经拖放了2次PlayerController代码;单击代码右边的齿轮按钮,在出现的快捷菜单中选择“Remove Com-ponent”命令,即可删除多余的代码,如图2-48所示。
图2-47 重复的PlayerController.cs文件
图2-48 删除多余的PlayerController.cs文件
对于JavaScript开发者来说,在图2-44中,双击playerController文件,Unity3D打开如图2-49所示的的代码编辑界面。
图2-49 JavaScript代码编辑界面
在图2-49中书写相关代码,playerController的JavaScript代码文件见代码2-2。
代码2-2 playerController的JavaScript代码
1: function Update() 2: { 3: transform.Translate( Input.GetAxis("Horizontal")*Time.deltaTime,0,0); 4: }
在上述JavaScript代码中,开发者需要在第1行到第4行之间的Update()中实现相关代码,以便Unity3D逐帧运行Update()中的相关游戏业务逻辑代码。
在第3行中,通过transform对象获得执行该代码的游戏对象Player,然后通过transform对象的Translate方法,实现Player的移动。
在Translate方法中,需要输入一个3D的矢量值,由于只需要实现飞机Player的左、右移动,因此只需要在3D矢量值中设置x的变量,其他2个值保持为0。
在实现沿x变量轴的左、右移动时,为了检测游戏玩家是否按下键盘左、右键,设置了Input.GetAxis("Horizontal")。如果按下了键盘左键,则Input.GetAxis("Horizontal")的值为-1;如果按下了键盘右键,则Input.GetAxis("Horizontal")的值为1。
通过Time.deltaTime,获得每帧之间的时间数值,默认情况下大约为0.02秒。
在图2-50中,选择playerController代码文件,拖放到层次Hierarchy窗格中的Player对象之上,如果代码没有编译错误,则可以成功拖放,并在右下角出现playerController代码组件;如果代码存在编译错误,不能成功拖放,则需要修改错误代码直到编译成功。
图2-50 拖放playerController.js文件
这里需要说明的是,初学者常常多次重复拖放相同代码,在图2-51中,已经拖放了2次playerController代码;单击代码右边的齿轮按钮,在出现的快捷菜单中选择 “Remove Component”命令,即可删除多余的代码,如图2-52所示。
图2-51 重复的playerController.js文件
图2-52 删除多余的playerController.js文件
单击Unity3D中的运行按钮,运行游戏,按下键盘左、右键,此时就会实现飞机移动。
但是左、右移动飞机的速度是不可以调整的,不利于游戏的调试,这里需要添加一个移动的速度变量speed。
对于C#开发者来说,添加速度变量speed之后,PlayerController的C#代码文件,见代码2-3。
代码2-3 PlayerController的C#代码
1: using UnityEngine; 2: using System.Collections; 3: 4: public class PlayerController: MonoBehaviour 5: { 6: public float speed=2.0f; 7: void Update() 8: { 9: transform.Translate(speed* Input.GetAxis("Horizontal")*Time.deltaTime,0,0); 10: } 11: }
在上述C#代码中,在第6行添加了一个速度变量speed,这里定义的speed变量的类型为public,对于公有属性变量speed,可以在Unity3D中的检视器中显示,方便开发者实时设置变量调试,如图2-53所示。
图2-53 公有属性变量speed
然后在第9行,根据添加的速度变量,实现真正的速度乘以时间等于移动的距离。
对于JavaScript开发者来说,添加速度变量speed之后,playerController的JavaScript代码文件,见代码2-4。
代码2-4 playerController的JavaScript代码
1: var speed:float=2.0f; 2: function Update() 3: { 4: transform.Translate(speed* Input.GetAxis("Horizontal")*Time.deltaTime,0,0); 5: }
在上述JavaScript代码中,在第1行添加了一个速度变量speed,这里定义的speed变量的类型为public,对于公有属性变量speed,可以在Unity3D中的检视器中显示,方便开发者实时设置变量调试,如图2-54所示。
图2-54 公有属性变量speed
然后在第4行,根据添加的速度变量,实现真正的速度乘以时间等于移动的距离。
再次单击Unity3D中的运行按钮,运行游戏,选择合适的speed变量值,按下键盘左、右键,此时就会实现飞机的合适移动。
2.循环左、右移动飞机Player
在上一节中,已经可以实现飞机的左、右移动,但是一旦飞机超出屏幕范围,则飞机再也看不见了。
下面实现一旦飞机超出屏幕左边,则飞机从右边屏幕出来;一旦飞机超出屏幕右边,则飞机从左边屏幕出来,实现所谓的左、右循环移动。
首先设置游戏输出界面的大小,以便在游戏场景中设置相关与界面有关的参数,如什么时候超出屏幕范围等。
在游戏Game窗格中单击Free Aspect下拉菜单,选择“Standalone (800×600)”,如图2-55所示,就会设置Game窗格的输出界面大小为800×600,如图2-56所示。
图2-55 设置分辨率
图2-56 设置游戏界面大小
为寻找飞机移动的左边边界和右边边界,在监视器中调整X轴的数值,当飞机刚刚消失之时,此时X轴的边界数值设定为-3.2和3.2,分别如图2-57和2-58所示。
图2-57 寻找飞机移动的左边边界
图2-58 寻找飞机移动的右边边界
对于C#开发者来说,为实现循环左、右移动飞机,PlayerController的C#代码文件,见代码2-5。
代码2-5 PlayerController的C#代码
1: using UnityEngine; 2: using System.Collections; 3: 4: public class PlayerController: MonoBehaviour 5: { 6: public float speed=2.0f; 7: 8: void Update() 9: { 10: if(transform.position.x < 3.2f && transform.position.x>-3.2f) 1: transform.Translate( speed*Input.GetAxis("Horizontal")*Time.deltaTime,0,0); 12: 13: if(transform.position.x<=-3.2f) 4: transform.position=new Vector3(3.1f, transform.position.y, transform.position.z); 15: 16: if(transform.position.x>=3.2f) 7: transform.position=new Vector3(-3.1f, transform.position.y, transform.position.z); 18: 19: } 20: }
在上述C#代码中,第10行判断飞机如果在屏幕之内,则执行原有的第11行飞机移动的代码;第13行如果飞机处于左边边界,则第14行代码将飞机设置为右边的边界位置;第16行如果飞机处于右边边界,则第17行代码将飞机设置为左边的边界位置。
这里需要说明的是,在C#中设置飞机的位置时,需要使用14行的方法,而不能直接设置其中的一个X值,与后面所述的JavaScript代码是不一样的。
对于JavaScript开发者来说,为实现循环左、右移动飞机,playerController.js的JavaScript代码文件见代码2-6。
代码2-6 playerController的JavaScript代码
1: var speed:float=2.0f; 2: 3: function Update() 4: { 5: if(transform.position.x>-3.2f && transform.position.x<3.2f) 6: transform.Translate( speed*Input.GetAxis("Horizontal")*Time.deltaTime,0,0); 7: 8: if(transform.position.x<=-3.2f) 9: transform.position.x=3.1f; 10: 11: if(transform.position.x>=3.2f) 12: transform.position.x=-3.1f; 13: }
在上述JavaScript代码中,第5行判断飞机如果在屏幕之内,则执行原有的第6行飞机移动的代码;第8行如果飞机处于左边边界,则第9行代码将飞机设置为右边的边界位置;第11行如果飞机处于右边边界,则第12行代码将飞机设置为左边的边界位置。
此时单击Unity3D中的运行按钮,运行游戏,选择合适的speed变量值,按下键盘左、右键,就会实现飞机的左、右循环移动。