滨江学院
学年论文
题目基于Unity3D在PC端的TPS游戏的开发与设计
院系电子系
专业电子信息工程
学生姓名杨鑫
学号20142305047
指导教师王新蕾
职称讲师
二O一七年十月二十五日
基于Unity3D在PC端的TPS游戏的开发与设计
杨鑫
南京信息工程大学滨江学院电子信息工程专业,南京210044
摘要:本文详细介绍了基于Unity3D游戏引擎(个人版)的TPS(第三人称射击)游戏的开发与设计的过程,主要包括游戏开发前准备,场景的制作以及游戏角色控制,子弹发射效果,敌对角色生成的实现方法等。并简单介绍了Unity3D引擎及其特点和资源商店的利用。详细阐述了游戏中的各种关键C#脚本程序。实现以键盘控制位置鼠标控制视角的人机对抗游戏模式。游戏操作简单,人物动作细腻多变,场景氛围代入感强,给玩家良好的游戏体验。
关键词: Unity3D;TPS;C#
第1章绪论
1.1基于Unity游戏开发的国内外现状
2016年又被称为VR元年。
虚拟现实(VR)是当今最前沿的科学技术之一,谷歌,微软,Facebook,苹果,三星,索尼等知名高科技企业对其视为上宾。VR通过计算机虚拟出现实世界,在VR技术影响下,仿佛置身于另一个世界。2016年,是VR技术突破性发展的一年,VR将与各行各业相互融合,产生庞大的岗位需求——VR开发工程师,而Unity已经成为VR内容开发的首选平台。
通过使用Unity引擎制作的游戏吸引了全球6亿游戏玩家。,Facebook拥有8.29亿的日常用户。用Unity 制作的应用和游戏目前的累计体验量已达到了87亿次。
根据Unity官方在2017年8月最新公布的数据[1],Unity中国区的开发者数量、用户活跃度和终端安装量均已经成为全球第一。在世界范围内,Unity占据全功能游戏引擎市场份额的45%,居世界首位。最接近我们的美国,其市场份额只有我们的三分之一。Unity的每月全球活跃用户超过60万。中国区每个月Unity引擎被使用的次数总和高达180万次,居世界首位。美国以150万次使用居世界第二。Unity中国区在3D手机游戏市场的占有份额已经达到75%,超越日本成为世界第一。也就是说在最火的前100款3D 手机游戏中,平均每10款就有7.5款是使用Unity引擎制作。
很多使用Unity制作的游戏都是跨平台的,其中不乏优秀作品,比如《神庙逃亡2》,《地铁跑酷》,《使命召唤》,《纪念碑谷》等。
国内首款基于Unity 3D引擎研发的三国题材网游《将魂》[2](现已停运),自2009年初就进入了研发历程,其后则还有骏梦游戏研发的Unity 3D游戏《新仙剑OL》[3]。
针对Unity 3D引擎的研发技术,九众互动CEO朱传靖也曾提过,该引擎基于特定的技术架构,实现了实时生成查看的功能,易用性高,更简化了开发的流程。基于此,九众互动的首款3D网游《将魂》,在游戏品质和研发时间上并没有太多的冲突。
在国外游戏厂商应用Unity 3D引擎方面,美国Playnet公司目前已经推出了3D军事战争网游《激战海陆空》。此外,俄国Nival公司研发的新型态Dota游戏《Prine world》在Steam上备受好评,欧美公司的3D魔幻MMORPG网游,都是非常受期待和关注的Unity 3D网游。
1.2课题研究目的与意义
游戏,对于很多人,占据了大学生活的大部分时光,许多大学生玩了4年游戏而碌碌无为。本文以新的视角为广大的游戏爱好者展现良好的发展前景,让大家了解一个游戏的简单制作流程,体验其中的乐趣,致敬每一个愿意把人生奉献给游戏事业的人。
Unity的迅速发展让Unity3d从业人才需求不断攀升,并且从业人员的薪资十分可观。以人才招聘来看,目前企业招聘人数呈现上升趋势,一般要求大专、本科学历,一年以上开发经验的人员一般待遇都会在10K左右,高级人才甚至达到20K-25K。随着工作经验和技能的增加,从业人员薪资水平不断增长。目前Unity需求主要集中在一线大城市,北京、上海、深圳、广州等,这些一线城市的薪资水平是非常可观的。从薪资角度来说,Unity3d工程师在棋牌游戏开发的工资能拿到15000元左右,当然还是要看具体的熟练水平的[4]。
所以说学习Unity并从事其相关工作,对于大学生来说是不错的出路。当然制作游戏不仅仅局限于此,还要懂美术,音乐,策划等多方面的知识。
通过本次课题的研究,不仅是熟悉了Unity开发工具,也为今后参加大型团队游戏制作项目提供了帮助。
1.3课题研究内容
本文主要介绍的是利用Unity 5制作一款TPS游戏的过程,具体内容有:
第二章,游戏的相关知识和开发平台的阐述,简单介绍Unity的诞生和优势以及引擎的各种系统和碰撞函数。阐明了游戏设计的基本流程和开发流程。
第三章,游戏的的总体设计,定制游戏的主体内容,包括名称,剧情,基本玩法,介绍开发前的项目准备。
第四章,游戏各个模块的具体实现,包括场景的制作,主人公的制作,子弹的制作以及敌对AI的制作等等。
第五章,PC 端游戏打包与发布,简单介绍利用Unity在PC端打包发布的方法。
第2章系统平台的阐述和游戏的相关知识
2.1 Unity 5的简介
Unity3D是由Unity Technologies开发的一个让玩家轻松创建例如三维视频游戏、建筑可视化、实时三维动画等类型互动内容的多平台的综合型游戏开发工具,是一款全面整合的专业游戏引擎。Unity类似于Director,Blender game engine, Virtools 或Torque Game Builder等利用交互的图型化开发环境为首要方式的软件。其编辑器运行在Windows 和Mac OS X下,可发布游戏至Windows、Mac、Wii、iPhone、WebGL (需要HTML5)、Windows phone 8和Android平台。也可以利用Unity web player插件发布网页游戏,支持Mac和Windows的网页浏览。它的网页播放器也被Mac 所支持。
2.1.1 Unity 5游戏引擎的诞生
业界现有的游戏引擎数不胜数,其中最具代表性的商业游戏引擎有虚幻引擎[5], CryEngine 3, HeroEngine, Rage Engine等,但因为其价格以及对PC配置要求高让很多个人游戏开发者尤其是学生望而却步。
在这样背景下,Unity公司提出了“大众游戏开发”的口号,让开发人员不在考虑价格,提供任何人都可以轻松开发的优秀游戏引擎。
2015年3月在旧金山举行的游戏开发者大会上Unity 5正式公诸于世。
2.1.2 Unity 5的优势
(1)支持多平台
跨平台运行,只需开发一次,稍加修改,就可以发布到23多个平台运行。现在,Unity已经可以支持以下平台[6]:
●移动平台(iOS、Android、Windows Phone、BlackBerry、Tizen)
●桌面平台(Windows、Windows Store、Mac、Linux)
●游戏主机(PS3、XBOX、Wii)
●网页游戏(Internet Explorer、WebGL)
●虚拟现实与增强现实(Oculus Rift、Gear VR)
(2)集成开发环境
从场景设计、编程、调试到构建、开发游戏的整个生命周期都可以在Unity IDE中完成,效率非常之高。另外,直观而合理的集成开发环境也为开发人员提供了便利。
(3)所有功能免费
只要你是独立开发者或是没有营收的小公司就符合使用Unity Personal Edition(个人版)的条件。但上一年营收或资本额超过了10万美金,就失去了使用个人版的资格,就必须购买Unity Professional Edition (专业版)。
(4)开放社区
社区提供了大量的帮助手册和体系化的示例文件,同时,Unity拥有一个资源分享和知识问答的交流平台,包括论坛、博客、在线视频等,以此帮助开发者更为便捷的了解Unity引擎。
(5)资源商店
Unity3D不仅拥有很强大的功能,丰富的模块,还有Asset Store提供开发过程中所需要的所有资源,具有超强的效能和超高的性价比,使编程周期大大缩短,即使是小型开发团队也可以轻松运作。也可以通过Asset Store销售自己制作的产品,获得利润。
2.2 相关Unity技术知识
2.2.1 物理系统
Unity内置了NVIDIA的Physx物理引擎,Physx是目前使用最为广泛的物理引擎,被很多游戏大作所采用,开发者可以通过物理引擎高效、逼真地模拟刚体碰撞、车辆驾驶、布料、重力等物理效果使游戏画面更加真实,更加生动[7]。
Rigidbody刚体组件,可使游戏对象在物理系统的控制下来运动刚体可接受外力与扭矩力用来保证游戏对象像在真实世界中那样进行运动。任何游戏对象只有添加了刚体组件才能受到重力的影响,通过脚本为游戏对象添加的作用力以及通过NVIDIA物理引擎与其他的游戏对象发生互动的运算都需要游戏对象添加了刚体组件。
Collides碰撞体,碰撞体是物理组件的一类它要与刚体一起添加到游戏对象上才能触发碰撞。如果两个刚体相互撞在一起,除非两个对象有碰撞体时物理引擎才会计算碰撞,在物理模拟中,没有碰撞体的刚体会彼此相互穿过。
Character Controller角色控制器,角色控制器主要用于对第三人称或第一人称游戏主角的控制,并不使用刚体物理效果。
2.2.2 动画系统
Mecanim动画系统随着Unity 4.0的升级而出现,这是一种动画中间引擎,使用其可以轻松制作柔和、平滑的动画效果,它提供了
●为人形角色提供的简易的工作流和动画创建能力;。
●Retargeting(运动重定向)功能,即把动画从一个角色模型应用到另一个角色模型上。
●针对Animation Clips(动画片段)的简易工作流,即针对动画片段以及它们之间的过渡和交互过
程的预览能力。这样可以使动画师更加独立地进行工作,而不用过分地依赖于程序员,从而在编写逻辑代码之前就可以预览动画效果。
●一个用于管理动画间复杂交互作用的可视化编程工具。
●通过不同逻辑来控制不同身体部位运动的能力[8]。
2.2.3 渲染系统
在Unity里,渲染路径(Rendering Path)决定了光照是如何应用到Unity Shader中的。因此,如果要和光源打交道,我们需要为每个Pass指定它使用的渲染路径,只有这样我们才能在Unity Shader中访问到Unity为我们准备好的光照信息。
Unity的渲染框架支持正向渲染与延迟光照渲染两种渲染模式、任意多光源、主直线光源的多层级阴影渲染以及各种自定义的材质和后置渲染特效。在Unity5.0版本之前,主要有3种:前向渲染路径(Forward
RenderingPath)、延迟渲染路径(Deferred Rendering Path)和顶点照明渲染路径(Vertex Lit Rendering Path)。但在Unity5.0版本以后,Unity做了很多更改,主要有两个变化:首先,顶点照明渲染路径已经被Unity抛弃(但目前仍然可以对之前使用了顶点照明渲染路径的Unity Shader兼容);其次,新的延迟渲染路径代替了原来的延迟渲染路径(同样,目前也提供了对较旧版本的兼容)。
2.2.4 脚本系统
Unity脚本开发是整个游戏开发过程中的重要环节,即便最简单的游戏也需要脚本来响应用户的操作,此外游戏常见的事件触发、游戏对象的创建与销毁等都需要通过脚本来控制[9]。
Unity 中可以选择两种脚本进行开发,分别为JavaScript和C#。
Unity使用的JavaSript语法与网页开发中基本相同,也可以称其为Unity脚本。而C#是一种分别借鉴了C++和Java优点的语言,国内开发主流的还是使用C#语言。Unity 5不再支持Boo脚本。
本游戏是运用C#进行开发的。
2.2.5 键盘交互技术
键盘交互主要是指能够控制游戏者在游戏场景中进行移动,键盘交互以设置方向键“↑”“↓”“→”“←”或者“W”“S”“A”“D”为控制键,分别用来控制游戏者的“前”、“后”、“左”、“右”的走动。在Unity中,可以通过函数实现这些功能,以用“W”“S”“A”“D”为控制键为例,脚本命名为js,其代码如下:
if(Input.GetKey(KeyCode.W))
{
transform.Translate(0 , 0 , 2*Time.deltaTime);
}
if(Input.GetKey(KeyCode.S))
{
transform.Translate(0 , 0 , -2*Time.deltaTime);
}
if(Input.GetKey(KeyCode.A))
{
transform.Translate( -2*Time.deltaTime , 0 , 0 );
}
if(Input.GetKey(KeyCode.D))
{
transform.Translate( 2*Time.deltaTime , 0 , 0);
}
2.2.6 碰撞检测技术
碰撞检测在3D游戏中是非常重要且常见的一件事情,好的碰撞检测要求人物在场景中可以平滑移动,当人物在在场景中漫游的时候,在各种前进方向上如果有被其他物体挡住的情况下,不但不能再继续往前走,而且要尽可能地沿合理的路线滑动。在Unity3d中,碰撞检测的功能是由函数封装好的,我们只需要调用函数就可以实现了。OnControllerColliderHit()函数是用于角色碰撞的,角色如果添加了Charactor Controller (Unity自带的用于角色控制的脚本)则使用这个函数检测碰撞,且不需要加刚体的。一般的刚体之间碰撞使用OnCollisionEnter()函数,范围触发用OnTriggerEnter()函数。
2.4 游戏项目流程
(1)原型阶段
实现游戏的必要技术验证。
产出:一个最简单的只有1关或者1个场景的的游戏原型。美术效果图。
(2)Alpha版阶段
完善游戏角色的逻辑,定义完善的数据结构和关卡配置,制作游戏UI,菜单UI等。
产出:一个能玩若干关卡的版本。
(3)Beta版阶段
完善逻辑,批量制作美术,关卡或者其他游戏内容,细化UI等各方面。加IAP,GameCenter等。
产出:完整的可玩版本,具备所有的游戏内容、关卡等。
(4)产品阶段
测试,修Bug,图标,截图,多语言说明,视频录制等等准备上线需要做的一切事情。提交上线。
产出:可以提交上线的app包。
本作由于个人能力有限,只制作了出游戏的原型和Alpha测试版。
2.5 Unity制作游戏流程
(1)游戏策划
一个游戏的诞生,往往是策划们脑海中的灵感一现,这是游戏诞生的第一步。主要工作是编写游戏背景故事,制定游戏规则,设计游戏交互环节,计算游戏公式,以及整个游戏世界的一切细节等。
(2)游戏原画设定
根据策划的文案,设计出整部游戏的美术方案,包括概念类原画设计和制作类原画设计两种,为后期的游戏美术(模型、特效等)制作提供标准和依据。
(3)游戏的模型及贴图制作
原画通过后指,游戏建模师就要按着原画中的场景、角色和道具按照比例制作设计成的物体,建模的过程很复杂,很多时候要靠建模师的发挥,好的模型和贴图会让游戏增色不少。
(4)游戏的程序编写
当模型完成后,程序员就要编写程序了,游戏角色的动作,人机交互系统,伤害的计算,血量的计算,AI的行为方式,巡逻路径等都是程序员的工作。
(5)游戏的测试
测试就是发现问题并进行改进,从而提升软件产品的质量。游戏测试也具备了以上的所有特性,不过由于游戏的特殊性,所以游戏测试则主要分为两部分组成,一是传统的软件测试,二游戏本身的测试,由于游戏特别是网络游戏,它相当于网上的虚拟世界,是人类社会的另一种方式的体现,所以也包含了人类社会的一部分特性,同时它又是游戏所以还涉及到娱乐性,可玩性等独有特性,所以测试的面相当的广。我们称之为游戏世界测试,常由真实用户参与完成,多以封测内测等形式出现。
第3章游戏的总体设计
3.1 游戏类型
第三人称射击游戏[10]简称:TPS,是射击游戏的一种。与第一人称射击游戏的区别在于第一人称射击游戏里屏幕上显示的只有主角的视野,而第三人称射击游戏更加强调动作感,主角在游戏屏幕上是可见的。
在游戏中,你可以看到游戏者,你好像一个旁观者或者操控者,而不是本人。这样更有利于观察角色
的受伤情况和周围事物,以及弹道。虽说没有第一人称射击的爽快感,但第三人称也有很多优势可以实现动作和枪战的完美结合,可以观察到一些第一人称看不见的地方,增强代入感。在一些第一人称射击游戏中,可以进行对第一人称至第三人称的转换。
3.2 游戏背景
本作游戏名称暂定为《SpaceShooter》,故事发生在未来,UNSC(联合国太空指挥部)收到一条来自远地殖民地的求救信息,主人公为UNSC的超级战士,收到指挥部的指令,率先前往远地殖民的军事堡垒进行调查,并发现可怕的外星人,与之发生了一番恶斗。
3.3 游戏开发步骤
●设置游戏开发环境
●下载并导入游戏资源
●设计游戏场景
●构建主人公移动和开火机制
●构建敌对角色的行为机制
●构建主人公和敌对角色之间的关系机制
●构建游戏UI
3.4 游戏总体规划
W、S、A、D键控制玩家行走,鼠标控制视角,鼠标左键按下开火。敌对角色在军事基地中固定点生成,玩家需消灭所有敌对角色完成通关。
玩家有100点HP,敌对角色会近身攻击玩家,每攻击一次,玩家收到10点伤害,被攻击10次后玩家死亡,击中敌对角色三次后,敌对角色死亡,玩家每击杀一个敌对角色获得50点分数。
3.5 开发前准备
3.5.1 创建资源商店账号
Unity运营商可以交易高品质资源的开放市场。资源商店中,可以购买所需的3D模型、贴图、动画、插件、脚本、音乐甚至是完整的游戏项目,其中有不少的优秀的免费资源。
要想使用资源商店,需要拥有账号,可以直接使用安装Unity时注册的账号登录。如果没有账号,则需现在资源商店中注册。
3.5.2 下载项目所需的游戏资源
打开Unity资源商店官网,在右上角搜索以下关键字进行搜索并下载资源导入到项目中来:
●Skybox Volume2(搜索Skybox V ol2)
●Sci-Fi Level (搜索Sci-Fi)
●Extreme Sci-Fi LITE(搜索Sci-Fi)
●Monster(搜索Monster)
●Barrel 3D模型(搜索Barrel)
至于主人公角色可以登录《Unity 5权威讲解》的作者李在贤的个人空间(https://www.sodocs.net/doc/1a15282317.html,/)来下载,以上部分资源也可以下载直接下载到。至于其他贴图音效等小型的资源可以根据喜好自行下载。
本作灵感来于《Unity 5》,但本作内容与其有很大出入,本人能力有限,离不开商店资源和书本指导,所以本作是站在巨人肩上的拙劣之作。
3.5.3 导入游戏资源
启动Unity,新建项目,在项目视图中创建Scenes(存放场景)、Scripts(存放脚本)、Prefabs(存放预制体)、Images(存放贴图和材质球)、Models(存放模型)、Sounds(存放音频)。导入游戏资源,至于是把游戏资源分类分别存入对应文件夹中这里不做介绍也不做要求(重命名资源文件名称或者移动位置可能会导致资源发生错误)。
第4章游戏各个模块的具体实现
4.1游戏场景制作
4.1.1 导入地图模型
点开SciFi Level文件夹中的SciFi Level.unity场景文件。将会看到图1(本文中给出的所有图片均是实机开发中画面)的地图资源载入到Senes面板。
图1 地图资源导入
4.1.2 3D模型
创建地形,材质包,并将材质包赋予创建好的Plane模型。
右击Hierarchy面板,3D Object→Plane,重命名为Ground,在Hierarchy面板中选中Ground,调整Inspector面板中的Transform组件中的属性,使其紧贴地图的正下方,如图2。
图2 地板的创建
4.1.3 材质渲染
选中Project面板中的Image文件夹,右击创建Materials文件夹,选中右击创建Material材质球,重命名为Ground 1,将适合的贴图(如06)拖入到材质球的Inspector面板中,最后在选中Project面板中将
Ground 1 材质包拖拽到Scenes面板中的Ground模型,就会有图3的效果。
图3 地板材质
4.1.4 天空盒的创建
在Project面板中的Images→Materials文件夹中创建新的材质球,重命名为Skybox,选择其Shader,
设置为Skybox/6 Side。在原先下载好的Skybox V olume2中找到天空盒的6面图像文件将其拖动到材质球
Skybox的对应版面。最后选择菜单栏Window→Lighting→Scene,将材质球Skybox拖入到Environment组
件中。最后得到如图3的场景。
图4 六面天空盒
4.1.5 场景的美化
利用下载好的SciFi_Battery_Pack_free文件中的模型,将其适当的添加到Scene面板中,为场景添彩。
如图5和图6。
图5 添加电池模型图6 添加铁箱模型
4.2 主人公的制作
导入的主人公角色模型的动画已经包含在内,这里主要处理三个问题,一是如何利用键盘的W、S、
A、D键控制角色的上下左右走向,如何利用鼠标来控制控制角色视角转向,二是在角色移动的同时实现对应动画的播放,三是如何实现第三人称摄像机视角对角色位置的跟随。
4.2.1 导入主人公模型
将下载好的AngryBotPlayer拖拽到Scene面板中的地图中的合适位置,如图7。
图7 主人公模型
4.2.2 角色移动实现
Unity中定义了游戏中许多必备的组合件,其中就包括控制角色移动的Input.GetAxis(“Horizontal”/ “Vertical”)组合键,它们分别控制方向左右和上下,当按下W、S键或者UP、DOWN键时,Input.GetAxis(“Horizontal”)函数即会返回-1~1之间的一个值。
在Scprits中创建C#脚本PlayerCtrl.cs,并将其拖拽到Scene面板中的Player。脚本代码如下:using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class PlayerCtrl : MonoBehaviour
{
private float h = 0.0f;
private float v = 0.0f;
//必须先分配变量,之后才能使用需要访问的组件,
private Transform tr;
//移动速度变量(声明为public并显示到检视视图)
public float moveSpeed = 10.0f;
//旋转速度变量
public float rotSpeed = 100.0f;
void Start () {
//向脚本初始部分分配Transform组件
tr = GetComponent
}
void Update () {
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
Debug.Log("H=" + h.ToString());
Debug.Log("V=" + v.ToString());
//计算前后左右移动方向向量
Vector3 moveDir = (Vector3.forward * v) + (V ector3.right * h);
//Translate(移动方向*速度*位移值*Time.deltaTime,基础坐标)
tr.Translate(moveDir.normalized * Time.deltaTime, Space.Self);
//以Vector3.up轴为基准,以rotSpeed速度旋转
tr.Rotate(V ector3.up * Time.deltaTime * rotSpeed * Input.GetAxis("Mouse X"));
}
}
4.2.3 摄像机追踪实现
为了实现摄像机平滑移动和震动效果,采用方法如下:将摄像机向主人公身后移动距离dist,再向上提高高度height,然后将摄像机方向调整为指向主人公方向[11],具体如图8所示。
cam
height
dist tr
图8 摄像头跟随示意图
在Scprits中创建脚本FollowCam.cs,将其拖拽到Hierarchy面板中的Main Camera。脚本代码如下:using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FollowCam : MonoBehaviour {
public Transform targetTr; //要追踪的游戏对象的Transform变量
public float dist = 10.0f; //与摄像机之间的距离
public float height = 3.0f; //设置摄像机的高度
public float dampTrace = 20.0f; //实现平滑追踪的变量
//摄像机本身的Transform变量
private Transform tr;
// Use this for initialization
void Start()
{
//将摄像机本身的Transform组件分配至tr
tr = GetComponent
}
//使用LateUpdate函数,调用所有Update函数后才会调用该函数
//要追踪的目标游戏对象停止移动后,调用LateUpdate函数
void LateUpdate()
{
//将摄像机防置在被追踪目标后方的dist距离的位置
//将摄像机向上抬高height
tr.position = V ector3.Lerp(tr.position //起始位置
, targetTr.position //结束位置
- (targetTr.forward * dist)
+ (Vector3.up * height)
, Time.deltaTime * dampTrace); //内插时间
//使摄像机朝向游戏对象
tr.LookAt(targetTr.position);
}
}
4.2.4 角色动画的实现
Unity支持两种动画系统:Legacy动画系统(旧版动画系统)和Mecanim动画系统(新版动画系统)。
Legacy动画系统:在3D Animation Tool中制作动画。
Mecanim动画系统:新的动画系统,可以利用动作复制功能重复利用现有的动画。
旧版动画系统是Unity引擎在4.0版本之前使用的。尽管Mecanim是在多数情况下(特别是针对人形动画)应该是优先选用的动画系统,但是旧版动画系统仍然在一些特殊场合被使用:一种情况是处理Unity 4.0之前版本生成的动画和相关代码;另一种情况是使用参数而不是时间来控制动画片段(例如控制瞄准角度)[12]。
而AngryBotPlayer模型不适合Mecanim动画所需的骨骼系统,同时PlayerCtrl中引用的
Input.GetAxis(“Horizontal”/“Vertical”)函数是使用参数控制动画片段的方式前提,所以这里使用Legacy
动画系统制作主人公的动画。
点开Player模型会看到Animations组件,将任务的休眠、前进、后退、左移、右移动画片段放入动画文件中,为各个动画片段添加开始帧和结束帧,如图9。
图9 Animations组件示意图对PlayerCtrl.cs脚本进行添加和修改(加粗字体为修改部分)。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
//此类需要声明属性System.Serializable,表示可视化
//显示到检视视图
[System.Serializable]
public class Anim
{
public AnimationClip idle;
public AnimationClip runForward;
public AnimationClip runBackward;
public AnimationClip runRight;
public AnimationClip runLeft;
}
public class PlayerCtrl : MonoBehaviour
{
private float h = 0.0f;
private float v = 0.0f;
//必须先分配变量,之后才能使用需要访问的组件,
private Transform tr;
//移动速度变量(声明为public并显示到检视视图)
public float moveSpeed = 10.0f;
//旋转速度变量
public float rotSpeed = 100.0f;
//要显示到检视视图的动画类变量
public Anim anim;
//要访问下列3D模型Animation组件对象的变量
public Animation _animation;
void Start () {
//向脚本初始部分分配Transform组件
tr = GetComponent
//查找位于自身下级的Animation组件并分配到变量
_animation = GetComponentInChildren
//保存并运行Animation组件的动画片段
_animation.clip = anim.idle;
_animation.Play();
}
void Update () {
h = Input.GetAxis("Horizontal");
v = Input.GetAxis("Vertical");
Debug.Log("H=" + h.ToString());
Debug.Log("V=" + v.ToString());
//计算前后左右移动方向向量
Vector3 moveDir = (Vector3.forward * v) + (V ector3.right * h);
//Translate(移动方向*速度*位移值*Time.deltaTime,基础坐标)
tr.Translate(moveDir.normalized * Time.deltaTime, Space.Self);
//以Vector3.up轴为基准,以rotSpeed速度旋转
tr.Rotate(V ector3.up * Time.deltaTime * rotSpeed * Input.GetAxis("Mouse X"));
//以键盘输入值为基准,执行要操作的动画
if (v >= 0.1f)
{
//前进动画
_animation.CrossFade(https://www.sodocs.net/doc/1a15282317.html,, 0.3f);
}
else if (v <= -0.1f)
{
//后退动画
_animation.CrossFade(https://www.sodocs.net/doc/1a15282317.html,, 0.3f);
}
else if (h >= 0.1f)
{
//向右移动动画
_animation.CrossFade(https://www.sodocs.net/doc/1a15282317.html,, 0.3f);
}
else if (h <= -0.1f)
{
//向左移动动画
_animation.CrossFade(https://www.sodocs.net/doc/1a15282317.html,, 0.3f);
}
else
{
//暂停时执行idle动画
_animation.CrossFade(https://www.sodocs.net/doc/1a15282317.html,, 0.3f);
}
}
}
4.3 子弹及其效果制作
一般情况下,对于射击类游戏子弹发射效果采用Ray Casting方式,经典的射击游戏“反恐精英”采用的就是这种方式,即没有实例化子弹,看不到子弹从枪口射出,而产生一条在游戏过程中看不见的射线,例如枪械的激光瞄准器,扣下扳机时枪口出现火焰效果,同时枪械瞄准的物体或者人物出现弹坑或者血迹效果。
而本文采用另一种方式,Projectile方式,例如早期的“侠盗猎车手”系列作品,即实例化子弹方式,扣下扳机后,在枪口出产生子弹,并向前给以一个比较大的力推动前进,子弹触碰到物体或者人物时产生弹坑或者血迹效果。但是这种方法可能会导致短时间内实例化多个子弹,这样无疑会增加电脑的负荷,所以就需要简化子弹模型,采用低多边形模型。
4.3.1 导入子弹模型
在Project面板中,Models→Bullet→lowpolybullet,将其拖入到Scene面板中,重命名为Bullet,将其Transform组件中的Rotation中的X值设为90,即绕X轴旋转90,再为其添加Rigidbody组件和Sphere Collider组件,取消勾选Rigidbody组件中Use Gravity选项,调整Sphere Collider的大小,使其覆盖子弹,如图10。
图10 子弹模型
4.3.2 子弹发射的实现
给子弹添加力,将其发射出去,添加脚本BulletCtrl.cs,其脚本代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class BulletCtrl : MonoBehaviour {
//子弹破坏力
public int damage = 20;
//子弹发射速度
public float speed = 1000.0f;
// Use this for initialization
void Start()
{
GetComponent
}
运行游戏后我们会发现子弹击中墙体后会被反弹,不符合现实,所以还需要让子弹碰撞到墙壁物体后可以立即消失,所以就要检测到碰撞。
在Unity中碰撞感知要满足两个条件,一是两个物体都有Collider组件,二是移动的一方必须有Rigidbody组件。所以需要将场景中所有类似于墙体的物体添加Collider组件。
检测碰撞时,主要运用两个事件,OnCollision和OnTigger事件。
每一种Collider组件中都会有一个Is Tigger选项,勾选Is Tigger选项就需要运用OnCollision事件,取消勾选Is Tigger选项就需要运用OnTigger事件,OnTigger事件和OnCollision事件主要的不同之处就是
OnTigger事件处理碰撞,移动物体会穿过被碰撞物体,如图11。
图11 OnColision
事件和OnTrigger事件的区别
本文利用OnCollision
事件处理碰撞,主要函数有OnCollisionEnter和OnCollisionExit函数。
子弹碰撞墙壁,墙壁就需检测到子弹,分辨出是子弹还是其他物体,在Unity中,可以个物体添加一个Tag标签,然后在脚本中调用该标签就可以识别所有具有该标签的物体,选中Bullet的预制体在Tag属性中添加新的Tag标签BULLET,如图12。
图12 Tag标签的设定
为墙体之类的被碰撞物体添加脚本WallCtrl.cs脚本,脚本代码如下:
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class WallCtrl : MonoBehaviour {
//表示火花粒子对象的变量
public GameObject sparkEffect;
//碰撞开始时触发事件
void OnCollisionEnter(Collision coll)
{
//比较发生碰撞的游戏对象的Tag值
if (coll.collider.tag == "BULLET")
{
//删除发生碰撞的对象
Destroy(coll.gameObject);
}
}
}
实例化子弹,当玩家按下鼠标左键发射一颗子弹,在Scene面板中新建一个空物体,调整位置,将其设置在枪口,重命名为FirePos,为枪口的空物体添加新脚本FireCtrl,代码如下。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class FireCtrl : MonoBehaviour {
//子弹预设
public GameObject bullet;
//子弹发射坐标
public Transform firePos;
void Update () {
//鼠标左击时调用Fire函数
if (Input.GetMouseButtonDown(0))
{
Fire();
}
void Fire()
{
//动态生成子弹的函数
CreateBullet();
}
void CreateBullet()
{
//动态生成Bullet预设
Instantiate(bullet, firePos.position, firePos.rotation);
}
}
4.3.3 子弹拖尾效果实现
创建新的材质球,赋予Trail.png,重命名为BulletTrail,改变其Shader属性为Particles/Additive。在Scene面板中为Bullet添加Trail Renderer组件,在其Materials属性中的Element选项中赋予材质球BulletTrail,适当调整其他属性,如图13。