基于Unity3D的塔防游戏设计与实现

龙源期刊网 http://www.qikan.com.cn

基于Unity3D的塔防游戏设计与实现

作者:刘俊 郭祖江

来源:《科技传播》2015年第05期

摘 要 以游戏场景设计与开发、AI(人工智能)、ShaderLab(着色器)系统为主要研究目标,阐述游戏场景规设计,分析AI设计过程中的主要思路和主要算法的实现。通过高效的、复杂的AI系统,以及ShaderLab开发创造出游戏中更加真实的行为,丰富的画面效果。实践证明,该技术具有一定的实际应用价值。 关键词 Unity3D;AI;ShaderLab

中图分类号TP39 文献标识码 A 文章编号 1674-6708(2015)134-0152-03

近几年来,Android平台游戏、iPhone平台游戏以及Web的网页游戏迅猛发展,已经成为带动游戏产业发展的中坚力量。遗憾的是目前除了少数的作品成功外,大部分的游戏属宣传攻势往往大于其内容品质,加之玩家体验游戏时,对游戏的沉浸感和操作性的要求也逐渐提高。在这种局面下,3D游戏成为当前游戏的发展热点。而本文所采用的Unity3D游戏引擎提供了创造高质量的3D游戏和真实视觉效果的核心技术,为开发3D游戏提供了强大的驱动力。 本文基于Unity3D游戏引擎,研究游戏中AI设计过程的主要思路和主要算法实现,通过高效复杂的AI系统以及特定的shaderLab(着色器)编程开发一款基于Unity3D的3D塔防类游戏,使之具备丰富的画面而且保证游戏运行的流畅度。实践证明,本文所讨论的关键技术可以应用于增强现实、游戏开发等多个领域,具有一定的实际应用价值。 1游戏场景

塔防游戏的基本玩法比较类似,在场景中我方有一个基地,敌人从场景的一侧出发,沿着相对固定的路线攻打基地。我方可以在地图上布置防守单位,攻击前来进攻的敌人,防止他们闯入基地。

本游戏的场景通常比较简单,就像一个棋盘格,可以在上面摆放防守单位,并专门留给敌人一个通道。在本游戏中,使用二维数组来表示场景中的格子,每个格子只有两种状态,允许摆放防守单位或不允许。

这是一个使用Terrain制作的简单场景,场景中间绘制了一条通道,敌人将从通道的左侧出发,目的地是通道右侧的房子,它是我们的基地。在通道以外的地方我们可以设置防守单位进攻敌人

塔防游戏的场景游戏固定的模式,它由一个二维的单元格组成,每个格子的用途可能不同,通常是下列用途之一:

龙源期刊网 http://www.qikan.com.cn

1)专用于摆放防守单位。

2)无法摆放防守单位,也不允许敌人通过。 3)专用于敌人通过。

摄像机始终由上至下俯视游戏场景,按住鼠标左键并移动可以移动摄像机的位置。 2 AI系统的实现

在BuildMap函数中,首先创建保存场景信息的二维数组,默认每个单元格都是可以摆放防守单位。然后在当前场景中找到所有Tag名为gridnode的游戏体,将其属性赋予和它位置相同的单元格。

在OnDrawGizmos函数中,我们使用线段绘制场景中的单元格,并将不能放置防守单位的单元格绘制为红色,这个功能主要是帮助我们预览场景单元格的状态。在OnDrawGizmos中绘制的图案并不会出现在最后的游戏界面中。

我们创建一个游戏管理器GameManager函数,它由几个作用,包括UI显示,控制鼠标操作和显示调试信息等。

正在塔防游戏中,敌人通常不需要智能寻路,而是按照一条预设的路线行动。我们为敌人创建一条前进路线,这条路线是预设的,敌人将从一个路点到达另一个路点,在PathNode脚本中,主要是通过SetNext函数设置它的子路点。

敌人一共有两种,一种在陆地上前进,另一种则会飞行。我们将先创建前一种,然后继承它的大部分属性和函数,略加修改完成另一种。在Enemy脚本中,定义了敌人的一些基本属性,如生命值、移动速度、类型等,它由一个路点属性作为当前的出发点。在其MoveTo函数中,敌人向当前路点的子节点前进,当距离子路点较近时,即将子路点作为当前路点,再向下移个路点前进。注意这里计算敌人与子路点的距离时没有计算Y轴,因为我们希望空中的敌人飞到路点上方即认为是到达该路点。当敌人走到最后的路点,即是到达我方基地,销毁自身,并使基地减少一点生命值。接下来创建另一个飞行敌人的脚本AirEnemy,它继承了Enemy脚本的大部分功能,只添加一个Fly函数,作用是当高度小于2时向上飞行。 敌人生成器(EnemySpawner):塔防游戏的敌人通常是成批出现,一波接着一波,因为敌人数量众多,所以需要一个生成器按预先设置的顺序生成不同的敌人。为了提高工作效率,我们将在Excel中设置每一波出现的敌人,然后将其导出为XML格式,敌人生成器读取这个XML文件,按其设置生成敌人。实际上我们也可以在Unity的Inspector窗口设置组件的数值,但对于一个复杂的项目来说,这么做会使项目的维护变得困难,而游戏策划又偏爱使用Excel表格,所以可以先在Excel中设置数据,再将其导入Unity,这会是一个非常好的选择。

龙源期刊网 http://www.qikan.com.cn

本游戏中唯一的防守单位是个袍塔(Defender),我们先准备一个ArrayList,将所有敌人遍历都存进去,这样很容易查找到任何一个敌人,当敌人进入它的攻击范围便会开火。在这个脚本中,FindEnemy函数主要用于查找进入其攻击范围的敌人,然后在这些敌人中再选出一个生命值最低的敌人作为目标敌人。Attack函数向敌人攻击,这里只是很简单地调用了敌人的SetDamage函数减少敌人的生命值。当创建了一个防守单位后,它所处的单元格则被当前防守单位占据,不能再创建其他东西,因此我们在Start函数中改变了防守单位所处单元格的属性。

生命条(LifeBar):敌人在受到攻击的时候,生命条可以显示它受到多少伤害,和提示它的剩余生命值。在Project窗口的Rawdata/Lifebar目录下引入了一个LifeBar.fbx文件,这是一个普通的平面模型,并附有一张贴图,贴图由简单的黄色和红色组成,我们将使用改变模型UV的方式,使黄色表示剩余生命值,红色表示失去的生命值。

在LifeBar脚本中,Ini函数负责初始化,主要是获取生命条模型的UV。在UpdateLife函数中,我们根据当前生命值和最大生命值计算出一个比例,然后调用Pad函数左右移动UV的位置,当生命值越低,黄色显示的越少,红色显示的越多。SetPosition函数负责设置生命条的位置,因为生命条始终要伴随乡音敌人的移动,并出现在它的上方,所以这个函数设置了一个yoffset参数,使生命条的位置向上偏移一定距离。 3 UV旋转纹理动画shaderLab

shaderLab主要用Cg语言来开发。Cg语言(C for Graphics)是为GPU编程设计的高级着色器语言,由NVIDIA公司开发。Cg极力保留C语言的大部分语义,并让开发者从硬件细节中解脱出来,Cg同时也有一个高级语言的其他好处,如代码的易重用性,可读性得到提高,编译器代码优化。下段代码实现了图片中纹理自动旋转的功能。 half4 frag(v2f i):COLOR {

float2 uv=i.uv.xy-float2(0.5,0.5);

float2 rotate=float2(cos(_RSpeed*_Time.w),sin(_RSpeed*_Time.w)); uv=float2(uv.x*rotate.x-uv.y*rotate.y,uv.x*rotate.y+uv.y*rotate.x); uv+=float2(0.5,0.5);

half4 c=tex2D(_MainTex,uv)*_Color; return c;

联系客服:779662525#qq.com(#替换为@) 苏ICP备20003344号-4