基于unity3D的趣味桌球游戏开发

时间:2024-03-26 09:50:49

设计主题
游戏中的主场景是一个四面有墙的场景,桌面上放置有可以滚动的小球和多个小方块,游戏开始后,玩家通过键盘控制球去吃方块,游戏得分会随着方块的减少而增长,当小球吃完全部的方块,得分达到最高,此时游戏结束。

设计思路
本项目设计思路围绕创建一个“趣味桌球游戏”,主要使用游戏对象(Game Objects),组件组成(Components),预设(Prefabs),物理和脚本等多种原理来完成游戏的实现。在本项目的实现过程中,主要通过以下思路和步骤完成游戏的制作:
(1)环境与玩家
a. 设置游戏;
b. 移动播放器。
(2)相机和播放区域
a. 移动相机;
b.设置播放区域。
(3)收集,评分和建立游戏
a. 创建收藏对象;
b. 收集拾物;
c.显示分数和文本;
d.建立游戏。
在本项目的设计与实验过程中,主要遵循的设计思路大致如下:首先需要利用Unity搭建游戏的主场景,例如桌面、四面边界等,然后对游戏中的小球和方块进行创建,并赋予其适当的材质和数据,最后利用程序代码的编写,实现小球的滚动、方块的碰撞和消失、得分的显示等,从而实现游戏的制作。

具体构建步骤
(1)创建项目
打开unity,在Projects中可以查看当前的本地项目或者云端项目,点击New project或者右上角的New都可以新建项目。在Unity中创建一个新的工程,将其命名为“RollABall”,如图5-1所示。
基于unity3D的趣味桌球游戏开发
图5-1 新建工程
(2)保存场景
File->save scence,保存游戏场景,保存在工程目录的Scences目录中,命名为Main。进入unity之后,可以看到已经预设的SampleScene和其中的Main Camera(主摄像机)和Directional Light(平行光)组件,直接点击修改名称并使用Ctrl+S保存修改即可,如图5-2所示。
基于unity3D的趣味桌球游戏开发
图5-2 保存场景
(3)创建桌面
使用unity的内置GameObject的Plane(平面)类型来作为游戏场景的“地面”,可以在Hierarchy视窗下右键选择3D Object下找到Plane创建,也可以在顶部菜单栏的GameObject下的3D Object下找到Plane创建。当然也可以看到unity为我们创建了很多预置的Game Object,比如3DO bject、2D Object、Effects、Light、Audio、 Video、UI、Camera等等,每一个分类下还有更详细的分类。在Hierarchy视图中,点击Create->Plane,创建Plane元素作为桌面,命名为Ground,如图5-3所示。
基于unity3D的趣味桌球游戏开发
图5-3 创建桌面
这里只需要创建一个Plane并将其命名为Ground,可以看到Plane出现在了MainScene中,同时Hierarchy视窗中的MainScene右上角出现了一个*号,这就表示该Scene处于待保存的状态,可以通过菜单栏的File->Save或者快捷键Ctrl+S保存Scene。
桌面创建完成后,选中刚刚创建的Ground,Inspector视窗中就会出现其所有的Components,这些都是预先被untiy设置给Plane的,点击Transform这一Component的右侧的齿轮状图标,可以选择Reset(重置)选项,这样,刚刚创建的Plane的Transform就会被重置为初始值,它的Position会被设置为(0,0,0),这是整个游戏世界的原点坐标,游戏中的所有GameObject的坐标都是基于此原点进行计算的。点击“Reset”对Ground进行数据重置,完成桌面的大小及规模设置,如图5-4所示。
基于unity3D的趣味桌球游戏开发
图5-4 对Ground进行重置
(4)小球创建及相关设置
在Hierarchy视图中,点击Create->Sphere,创建Sphere元素作为小球,命名为Player,点击“Reset”对其进行数据重置,完成小球的大小及规模设置,如图5-5所示。
基于unity3D的趣味桌球游戏开发
图5-5 创建小球并进行重置
此时小球的中心已经被定位到了(0,0,0)处,为了让小球能在平面上滚动,需要进行相应调整,将小球放到平面上。
观察小球的Transform可以发现,它的Scale的值为(1,1,1),也就是说它的三个方向的大小都为1单位,为了让小球放到平面上边,显然需要将其向上移动半个球的距离。在Inspector中更改相应数据,将position中的Y改为0.5,从而使得小球在桌面之上,如图5-6所示。
基于unity3D的趣味桌球游戏开发
图5-6 设置小球数据
(5)让小球成为刚体
为了让小球有滚动的效果,需要让小球拥有一系列的物理属性,物理属性已经由unity内置,选中Player,在Inspector面板中通过Add Component中找到Physics下的Rigidbody即可,如图5-7所示。
基于unity3D的趣味桌球游戏开发
图5-7 为小球添加刚体
为小球添加刚体属性以后,在Inspector面板中将小球的质量mass设为1,勾选重力作用use Gravity,如图5-8所示。
基于unity3D的趣味桌球游戏开发
图5-8 设置小球数据
(6)创建Material
为了使GameObject美观,我们通常会对其表面进行一系列装饰,而其表面的表现是通过为这个GameObject添加Material(材料)来实现的。接下来为Ground和Player添加最简单材料:纯颜色。
在Assets下新建Materials目录用于管理各种材料,如图5-9所示。
基于unity3D的趣味桌球游戏开发
图5-9 创建materials文件夹
然后右键该目录选择Create->Material新建一个材料命名为Background,如图5-10所示。
基于unity3D的趣味桌球游戏开发
图5-10 创建background
选中Background,就可以看到它的Inspector面板了,在Albedo(反射率)一栏中可以选择一种颜色,本项目中将桌面设置为深绿色,设置完成后,在下方的预览中就可以看到效果了,如图5-11所示。
基于unity3D的趣味桌球游戏开发
图5-11 设置颜色
想要将创建的Material运用在某个GameObject上,很简单,只需要拖动该Material到Scene中的目标GameObject上或者拖动到Hierarchy的该GameObject上即可,如图5-12所示。
基于unity3D的趣味桌球游戏开发
图5-12 为桌面赋予颜色
(7)创建C# Script脚本
有了刚体属性的小球需要在控制下滚动,那么对于一个有物理属性的刚体来说,为了能够动起来,当然需要力(Force)作用在物体上,这些有关于如何控制GameObject的方法需要使用脚本(Scripts)来完成。在Assets下创建Scripts目录来管理脚本,在该目录处右键->Create->C# Script创建一个脚本,命名为PlayerController,如图5-13所示。
基于unity3D的趣味桌球游戏开发
图5-13 创建脚本
为了让创建的脚本与Player联系起来,可以在Player的Inspector面板下选择Add Component,在其中搜索脚本名字就可以找到该脚本,根据unity的命名规范,喜欢将脚本各个单词使用“驼峰法”并且首字母同样大写的方式。还可以直接将Assets中的脚本拖到Inspector面板下,就可以添加成功。
(8)编辑脚本内容
双击脚本文件或者在Inspector面板中点击脚本的右上角的齿轮图标选择Edit Scrpit都可以打开编辑器对其进行编辑。unity预置好了脚本的最基本结构。所有的unity脚本都继承自MonoBehaviour类,有两个预设函数,Start函数是在第一帧开始渲染前调用,Update函数在每一帧刷新前调用,都是非常常用的函数。
分析游戏需求,项目需要检测用户的输入,并且通过输入的按键来控制小球的滚动方向,检测用户的输入同时也需要识别输入的是哪一个按键,除此之外还需要一些物理学有关的逻辑,这些逻辑当然是每一帧都要进行一次,所以需要将这些逻辑写在每一帧更新都要执行的函数中。
显然可以写到Update函数下,因为Update函数是每一帧刷新前都会调用的,也可以用FixedUpdate函数,它在每一次进行物理学运算的时候调用,每次检测到用户输入都需要进行物理学运算,所以本项目可以将逻辑写到FixedUpdate函数下。
在编写脚本的过程中,首先创建一个对于这个Player小球的引用,这样才能知道控制的是哪个小球,这里小球是刚体,所以创建一个刚体(Rigidbody)的引用,并且需要在第一帧开始渲染之前通过GetComponent方法来找到小球创建刚体的引用,这一逻辑自然就需要写到Start函数中了。然后对用户输入的读取就需要写到FiexedUpdate函数中了,使用Input类的GetAxis方法来获取水平或者垂直的运动轴,这个方法会返回一个float值作为该轴的移动距离。接下来通过Rigidbody类的AddForce方法可以为刚体添加作用力,AddForce方法接受一个三维向量(Vector3)参数,这个三维向量就可以表示力,显然三维向量可以用刚才的moveHorizontal和moveVertical两个变量作为X值和Z值,因为不需要小球在Y方向上移动的,也就是将Y方向的力作用设置为0.0f即可。详细脚本代码如图5-14所示。
基于unity3D的趣味桌球游戏开发
图5-14 编辑脚本
经过调试会发现小球的移动速度过慢,为了方便调节小球的速度,只需要在表示力的三维向量前乘以一个倍数即可,为了方便调整,可以设置一个public的float类型的变量speed来调节这个乘积。这里必须说明的是,凡在unity的脚本中被声明为public类型的变量,在unity的Inspector界面中的该脚本的Component下都会出现一个可以设置的值的方框。此处将speed的值设为10比较合理,如图5-15所示,运行游戏就会发现通过键盘的控制,小球动了起来。
基于unity3D的趣味桌球游戏开发
图5-15 设置速度speed
(9)设置摄像机
可以发现,Camera的角度和位置都比较刁钻,这导致游戏中看到的画面并不完整,接下来对Camera进行设置,使其能够跟随小球滚动来同时移动。首先调节Main Camera的Position和Rotation使得画面和角度比较合适,比如这里将Position的Y值设为6,Z值设为-6,将Rotation的X值设为45得到了一个较为合适的位置,如图5-16所示。
基于unity3D的趣味桌球游戏开发
图5-16 设置摄像机
接下来通过脚本控制Main Camera跟随小球Player一同移动,即在Position上保持相对静止。新建脚本CameraController,并添加给Main Camera做一个Component,如图5-17所示。
为了使Main Camera的Transform的Position和Player的保持相对静止,Rotation并不和其保持一致,可以想到一个办法:设置一个偏移量,这个值初始化为游戏开始时Main Camera和Player之间的Position的差值,然后在球滚动时,每一次滚动都改变Main Cmaera的Position,使其新的Position等于现在球的Position的值加上刚才的偏移量,这样就会在每次球的位置改变时Main Camera都会跟上它的步骤。
基于unity3D的趣味桌球游戏开发
图5-17 新建脚本CameraController
显然,偏移量的设置需要在Start函数中完成,每一次球的位置发生变化时的逻辑可以在Update函数中完成,但还有一个更好的选择,就是LateUpdate函数,该函数在每次有GameObject发生变动时才会调用。脚本代码如图5-18所示。
基于unity3D的趣味桌球游戏开发
图5-18 编辑脚本CameraController
同时,脚本是加在Main Camera上的,所以Main Camera的Transform可以直接调用,但是球的Transform则需要单独获取,这里可以设置一个public的GameObject量,然后在unity中将球Player拖动到这个量处作为参数即可,如图5-19所示。
基于unity3D的趣味桌球游戏开发
图5-19 添加Player参数
这时候运行游戏就可以发现Main Camera的位置随着球的改变而发生了改变。
(10)建立围墙
为了不让小球总是滚落到Plane之外,可以在其四周围建立起一圈围墙,很简单,使用预设的Cube就可以了。为了更好的管理四个围墙,可以先创建一个空的GameObject,如图5-20所示。
基于unity3D的趣味桌球游戏开发
图5-20 创建空的GameObject
将其命名为Walls,Reset使其重置位置,然后在其上右键新建一个Cube,并命名为WestWall,这样这个Cube就成为了Walls的子物体。通过Edit菜单的Duplicate或快捷键 Ctrl+D复制出三个West Wall元素,并命名为East Wall、South Wall、North Wall,改变其大小位置,正好放在地板的四面,如图5-21所示。
基于unity3D的趣味桌球游戏开发
图5-21 创建围墙
接下来如何调整墙的大小、位置就很简单了,可以在Inspector中直接输入具体数值,也可以直接在Scene中拖动和缩放,就可以得到这个墙体结构。围墙的的相关数据分别如图5-22至图5-25所示。
基于unity3D的趣味桌球游戏开发
图5-22 设置East Wall相关数据
基于unity3D的趣味桌球游戏开发
图5-23 设置West Wall相关数据
基于unity3D的趣味桌球游戏开发
图5-24 设置South Wall相关数据
基于unity3D的趣味桌球游戏开发
图5-25 设置North Wall相关数据
至此完成围墙元素。运行游戏会发现小球只能在围墙内活动了。
(11)创建碰撞小立方体
我们在游戏场地中加入一些旋转的小方块儿,然后由球来碰撞这些小方块儿,碰撞之后就加一定的分数。在Hierarchy中创建一个Cube,并命名为PickUp,使其Reset,然后调整一下它的Rotation和Scale,使得其变成一个斜放的小立方体,如图5-26所示。
基于unity3D的趣味桌球游戏开发
图5-26 创建碰撞小立方体
(12)添加脚本让小立方体旋转
为了让小方块儿更有趣,可以添加一个脚本让其旋转起来,新建脚本Rotator,并添加给PickUp,编辑此脚本。这个逻辑中是不需要Start函数的,只需要每一帧都让小方块儿转动一下,所以将逻辑写到Update函数中,这里使用Ratate方法,需要一个Vector3作为参数,为了不让旋转过快,可以给每一帧都乘以一个小的时间量。保存脚本,运行游戏可以看到小方块旋转起来了。脚本内容如图5-27所示。
基于unity3D的趣味桌球游戏开发
图5-27 编辑脚本Rotator
(13)创建Prefab
把这个设计好的立方体生成一个Prefab(预设体),让它变成一个asset,就可以从prefab创建这个立方体的实例,才能分别控制每一个由prefab生成的实例或者控制prefab本身。在这个游戏中,被小球碰撞到的小立方体会消失,也就是需要更新每一个小立方体的状态,所以需要创建一个Prefab。
在Assets下新建Prefabs目录来管理预设体,只需要将MainScene中的PickUp拖拽到新建的目录下就可以生成对应的asset了,这时也会看到MainScene中的PickUp变成了一个蓝色的图标。此时在MainScene中新建一个空的GameObject来管理所有的小立方体,命名为PickUps,将刚刚的第一个PickUp拖拽到它的上边使其成为其子物体,如图5-28所示。
基于unity3D的趣味桌球游戏开发
图5-28 创建预设体
(14)放置更多的立方体
接下来放置小立方体,为了调整一个好的视角,可以点击Scene中右上角的方位标志的Y轴的小锥体,就会调整视角到俯视的角度。
由于立方体是一个斜放的立方体,在原本的坐标轴下很难调整立方体在水平面上的位置,点击右上角的Local变成Global,这样就会在Global的坐标中对小立方体进行调整了,可以看到,小立方体的三个坐标轴变成了只有两个方向的轴,非常方便就可以调整了。然后调整位置复制摆放出12个立方体,如图5-29所示。
基于unity3D的趣味桌球游戏开发
图5-29 创建多个立方体
(15)为小立方体涂色
将Material用于Assets中的小立方体的Prefab就可以,找到Assets中的PickUp的Prefab,点击Inspector面板中的Open Prefab,就会在Scene窗口中预览该Prefab,再拖动粉色的Material到上面,这个Prefab就会被染成粉色了,如图5-30所示。
基于unity3D的趣味桌球游戏开发
图5-30 为小立方体涂色
(16)为PickUp添加标签
如果小球碰撞了旋转的立方体,那么小立方体就会消失。此处可以通过为PickUp添加特定的标签来识别。添加标签再Prefab上,在Assets中找到Prefab并打开它,可以在它的Inspector面板中发现它还没有添加标签(Untagged),点击Tag后的按钮选择Add Tag…,来添加一个名为PickUp的标签,然后再回到最开始的面板处选择新添加的这个标签,这样PickUp的标签就添加好了。如图5-31所示。
基于unity3D的趣味桌球游戏开发
图5-31 为PickUp添加标签
(17)实现碰撞操作
重新编辑PlayerController的脚本,这里将碰撞发生的逻辑写到函数OnTriggerEnter中,这个函数在发生碰撞事件的时候调用,而且用碰到的Collider(碰撞机)作为参数,也就是的Player碰到的Collider。可见,如果要检测到的碰撞,被碰撞的物体需要由碰撞引擎,也就是要有Collider的属性。作为Cube保存的一个Prefab,在创建之初就已经有Box Collider的这一Component了,所以不再需要添加。
OnTriggerEnter函数用其碰撞到的Collider作为参数,现在需要识别这个碰到的Collider是不是一个PickUp了,显然可以使用Tag来鉴别,这里使用gameObject的CompareTag方法来完成,该方法以一个字符串作为参数,返回一个布尔值,如果gameObject的Tag和字符串一致,就返回true。
接下来完成控制小立方体消失的逻辑,很简单,使用gameObject的方法SetActive来完成,这个方法控制的就是在Inspector面板中看到的每一个GameObject前的小对勾,该方法接受一个布尔值作为参数来控制GameObject的消失与显现。具体代码如下:
void OnTriggerEnter(Collider other)
{
if (other.gameObject.CompareTag(“PickUp”))
{
other.gameObject.SetActive(false);
}
}
此时运行游戏,在小球碰到小立方体的时候,小立方体并没有消失,这里的原因需要一定的Unity对与碰撞到原理。
Unity将Collider(碰撞机)分为静态碰撞机(Static Collider)和动态碰撞机(Dynamic Collider)两种。静态的碰撞机比如墙面、地板等一些列静态的物体,与他们碰撞时,不允许两个Collider相互重合,也就是说会发生反弹,而为了让碰撞能够实现,需要将立方体设置为动态的(Trigger)触发器,成为Trigger的Collider是可以被穿过的,这样才会引发“碰撞事件”的逻辑。
找到PickUp的Prefab,在它的Box Collider的Component中有个Is Trigger勾选项,勾选Is Trigger选项,这样它就成为了一个触发器,如图5-32所示。
基于unity3D的趣味桌球游戏开发
图5-32 勾选Is Trigger
此时运行游戏可以发现,小立方体在受到碰撞后消失。
(18)添加计分机制
接下来添加一个计数器,需要编辑PlayerController脚本,声明一个int类型的变量,在Start函数中初始化为0,在每一次碰撞到小立方体后都增加一。在Hierarchy面板中右键,选择UI->Text,就会创建一个UI组件,但是我们会发现其实Text外还有一层Canvas(画布),下方还出现了一个EventSystem,这些都是Unity为我们自动创建的,这是因为所有的UI元素都必须是一个Canvas(画布)的子元素才能正常工作。这里将Text命名为Count Text,如图5-33所示。
基于unity3D的趣味桌球游戏开发
图5-33 创建Count Text
调整Text的位置,在Inspector面板中,可以调整Text显示的内容,字体的样式,字体颜色以及这个UI组件的位置,先把文字显示改为Count Text,接下来改变其字体颜色为白色,如图5-34所示。
基于unity3D的趣味桌球游戏开发基于unity3D的趣味桌球游戏开发
图5-34 设置CountText的属性
找到Inspecctor的Rect Transform,可以看到UI的Transform和一般GameObject的定位方式不同,这个位置的确定是相对于游戏屏幕的,点击左边的这个方框,展开位置选择的面板,根据提示:按住Shift键选择中心轴(pivot),按住Alt键选择位置(position)。同时按住Shift和Alt键,将Text放到Canvas的左上角。这样就可以看到Count Text放置到了Game窗口的左上角。接下来可以改变Rect Transform的Pos X的值和Pos Y的值让Count Text稍微离左边缘和顶部边缘一段距离,如图5-35所示。
基于unity3D的趣味桌球游戏开发
图5-35 设置分数显示位置
(19)编辑脚本显示分数
接下来当然是将分数显示到Text中,继续编辑PlayerController脚本,首先需要添加新的Namespace。然后自然需要创建一个Text变量来表示CountText的一个引用,将此Text变量声明为public的类型,为了可以在Inspector中对其进行直接的赋值。接下来要初始化CountText中所显示的文字,使用Text的text变量即可,在Start函数中进行初始化,然后再每一次碰撞到小立方体的时候再重新更新Text的内容,保存脚本回到Unity,将CountText拖动到Inspector中新产生的这个Text变量处来实例化即可。
(20)添加游戏成功提示
当所有的小立方体都被收集后,再屏幕中心显示“You Win!”的字样,这看起来就很简单了,同样是:添加一个新的Text组件、命名、改变字体颜色大小和位置、在脚本中新建一个Text变量、在Start函数中将其初始值设为空、满足count值大于等于8的时候即显示“You Win!”、将新的Text拖动到Inspector面板中的变量处,如图5-36所示。
基于unity3D的趣味桌球游戏开发
图5-36 游戏成功提示
PlayerControler的脚本代码如图5-37所示。
基于unity3D的趣味桌球游戏开发
图5-37 PlayerControler脚本代码
(21)Build游戏
Unity创建游戏的平台非常广泛,在无需任何其他插件的前提下,可以创建Windows、Mac和Linux平台下的游戏,这里创建一个Windows平台的.exe文件。
先保存Scene,然后选择File下的Build Settings…。
默认即PC,通过Add Open Scene来选择需要创建的Scene,不过本游戏只有一个Scene,不进行选择也是可以的。点击Build,选择要保存到目标目录,然后稍等片刻,就会得到了最终的.exe文件,如图5-38所示。
基于unity3D的趣味桌球游戏开发
图5-38 Build游戏

成果展示
运行游戏,会在左上角显示当前得分,可以利用键盘对小球的运动进行控制,从而碰撞使得方块消失,如图6-1所示。
基于unity3D的趣味桌球游戏开发
图6-1 游戏运行结果
当游戏成功时,会在左上角显示当前得分,并在中心部分显示“You Win!”提示玩家游戏成功,如图6-2所示。
基于unity3D的趣味桌球游戏开发
图6-2 游戏成功效果