Unity3D手机游戏开发[试读]
3.1 策划
第3章 第一人称射击游戏 本章将使用Unity制作一款第一人称射击游戏,这是时下最流行的游戏类型之一。在本章的内容中,将涉及摄像机控制、物理、动画、智能寻路等。 3.1 策划 在开始制作游戏之前,按惯例还是先准备一份游戏策划。我们将要制作的游戏并不复杂,场景中只有一个主角和一种敌人,尽管如此,它已经具备了第一人称射击游戏的主要要素。 3.1.1 游戏介绍 在游戏场景中,会有若干个敌人的出生点,它会定时生成一些敌人,它们会寻找并攻击主角。游戏的目的就是生存下去,消灭更多敌人,获取更多分。 3.1.2 UI界面 游戏中的UI比较简单,包括主角的生命值、弹药数量、得分和瞄准星。... 查看全部[ 3.1 策划 ]
3.2 游戏场景
3.2 游戏场景 首先我们要准备一个游戏的场景,场景中的美术部分本书光盘已经提供,但我们还需要进行一些设置,使其具有碰撞功能。 打开本书光盘目录chapter03_FPS_Start内的Unity工程,在这个工程中,已经预先提供了本游戏所需要的模型、动画、音效等资源。 打开本工程准备好的场景,这个场景使用了Lightmap和Light Probe表现静态和动态模型的光影效果,如图3-1所示。在本书第5章对Lightmap和Light Probe有专门的介绍。 图3-1 游戏场景 选择三个场景模型,如图3-2所示,然后在菜单栏选择【Component】→【Phy... 查看全部[ 3.2 游戏场景 ]
3.3 主角
因为是第一人称射击游戏,所以主角是不可见的,但在屏幕上可以看到主角手中拿的枪,尽管如此,我们还是需要为主角创建碰撞体,并控制其移动。 3.3.1 角色控制器 在菜单栏选择【GameObject】→【Create Empty】创建一个空的游戏体,将它的Tag设为Player,它便是我们的主角。 在菜单栏选择【Component】→【Physics】→【Character Controller】为主角添加一个角色控制器组件,使用这个组件提供的功能,我们将可以实现在控制主角移动的同时与场景的碰撞产生交互,比如在行走时不会穿到墙里面去。 为主角再添加一个Rigidbody组件,取... 查看全部[ 3.3 主角 ]
3.4 敌人
3.4.1 寻路 在很多游戏中,敌人经常要在复杂的地形中追着主角跑,因为场景中存在很多障碍物,敌人的AI要足够聪明,才能找出到达目标点的最近道路,且绕开障碍物。写一个完善的寻路算法是比较有挑战的,特别是在复杂的3D场景中,好在Unity Pro版提供了一个非常实用的寻路功能,只需要较少的代码即可实现复杂的寻路功能。 Unity的寻路系统分为两部分,一部分是对场景进行设置,使其满足寻路算法的需求,另一部分是设置寻路者。 选择场景模型,然后在Inspector窗口选项Static旁边的小三角显示出下拉菜单,确定其中Navigation Static被选中。对于与场景地形无关的模型选项,... 查看全部[ 3.4 敌人 ]
3.5 UI界面
3.5 UI界面 在继续改进主角和敌人的脚本之前,我们需要创建一个游戏管理器来管理游戏中的事件和UI界面显示。 在前一章,我们使用OnGUI制作了一些简单的UI,使用OnGUI可以更快地创建UI元素,但它的缺点是性能较差,在编写脚本的同时也无法预览UI的效果。这一次我们将使用另一种方式,直接在场景中创建2D贴图表示UI界面。 在Project窗口找到预设的UI贴图文件,如图3-12所示 图3-12 设置动画过渡 选择贴图文件,在菜单栏选择【GameObject】→【Create Other】→【GUI Texture】创建2D贴图,然后在Inspector窗口移动贴图... 查看全部[ 3.5 UI界面 ]
3.6 交互
3.6 交互 当前的敌人虽然会攻击主角,但并没有造成实际伤害,主角暂时也不能攻击敌人。下面我们将分别为主角和敌人添加处理逻辑的代码,使其具备攻击对方的能力。 3.6.1 主角的射击 打开脚本Player.cs,添加OnDamage函数,该函数的作用是减少主角的生命,并更新UI界面的显示,当生命小于零时,取消鼠标锁定。 public void OnDamage(int damage) { m_life -= damage; // 更新UI GameManager.Instance.SetLife(m_li... 查看全部[ 3.6 交互 ]
3.7 出生点
3.7 出生点 接下来,我们需要为敌人制作出生点,使其在场景中的不同位置每隔一定时间生成一定数量的敌人。这个出生点的制作与在前一章完成的出生点类似,但需要略加一些其他功能。为了能够控制敌人的数量,每个出生点需要能清楚自己生成了多少敌人,当达到最大值时,则暂停生成敌人。当敌人被消灭时,则需要通知出生点更新生成数量。 创建脚本EnemySpawn.cs: using UnityEngine; using System.Collections; public class EnemySpawn : MonoBehaviour { // 敌人的Prefab pu... 查看全部[ 3.7 出生点 ]
小结
本章完成了一个完整的第一人称射击游戏实例,在这个过程中,我们了解了如何控制带有物理功能的角色移动,并使摄像机伴随移动。游戏中的射击判定使用了基于射线的物理碰撞,还涉及了Mecanim动画系统,寻路功能等。本章最后为游戏创建了一个小地图,使用了分层显示的功能。... 查看全部[ 小结 ]
4.1 策划
第4章 塔防游戏 本章将使用Unity完成一款塔防游戏。我们将在Unity内创建二维数组保存场景信息,自定义路点引导敌人行动,还将涉及摄像机控制,读取XML文件,自定义按钮等。 4.1 策划 移动平台上的塔防游戏已经多得数不胜数,笔者也曾经开发过一款叫作《野人大作战》的塔防游戏(英文名为Wild Defense)。塔防游戏的基本玩法比较类似,在场景中我方有一个基地,敌人从场景的另一侧出发,沿着相对固定的路线攻打基地。我方可以在地图上布置防守单位,攻击前来进攻的敌人,防止他们闯入基地。 本章我们也将制作一款塔防游戏,它将具备塔防游戏的最基本要素。 4.1.1 场景 塔防游戏的场... 查看全部[ 4.1 策划 ]
4.2 游戏场景
4.2 游戏场景 塔防游戏的场景通常比较简单,就像一个棋盘格,可以在上面摆放防守单位,并专门留给敌人一条通道。在这个实例中,我们使用二维数组来表示场景中的格子,每个格子只有两种状态,允许摆放防守单位或不允许。 打开本书光盘目录chapter04_TD_Start内的Unity工程,在这个工程中,已经预先提供了本游戏所需要的模型、动画、音效等资源,如图4-1所示。 图4-1 塔防游戏场景 这是一个使用Terrain制作的简单场景,场景中间绘制了一条通道,敌人将从通道的左侧出发,目的地是通道右侧的房子,它是我们的基地。在通道以外的地方我们可以设置防守单位进攻敌人。 创建... 查看全部[ 4.2 游戏场景 ]
4.3 摄像机
4.3 摄像机 因为游戏的场景可能会比较大,我们需要移动摄像机才能观察到场景的各个部分。接下来我们将为摄像机添加脚本,在移动鼠标的时候可以移动摄像机。 在为摄像机创建脚本前我们需要先创建一个空游戏体作为摄像机观察的目标点,并为其创建脚本CameraPoint.cs,它只有很少的代码。 using UnityEngine; using System.Collections; public class CameraPoint : MonoBehaviour { public static CameraPoint Instance = null; vo... 查看全部[ 4.3 摄像机 ]
4.4 游戏管理器
4.4 游戏管理器 接下来,我们将创建一个游戏管理器,它有几个作用,包括UI显示,控制鼠标操作和显示调试信息等。 创建3个GUI Text,分别表示游戏中的敌人进攻波数,我方生命和我方的点数,如图4-7所示。 图4-7 UI 创建一个空游戏体作为游戏管理器,确定它的坐标位置为0,将前面创建的文字作为它的子物体,如图4-8所示。 图4-8 游戏管理器 创建脚本GameManager.cs,指定给前面创建的游戏管理器,添加代码如下: using UnityEngine; using System.Collections; public class G... 查看全部[ 4.4 游戏管理器 ]
4.5 路点
在前一章,我们使用Unity提供的寻路功能实现敌人的行动,但在塔防游戏中,敌人通常不需要智能寻路,而是按照一条预设的路线行动。接下来我们将为敌人创建一条前进路线,这条路线是预设的,敌人将从游戏场景的左侧沿着通道一直走到右侧。 路线是由若干个路点组成,首先为路点创建脚本PathNode.cs: using UnityEngine; using System.Collections; public class PathNode : MonoBehaviour { // 父路点 public PathNode m_parent; // 子路点 ... 查看全部[ 4.5 路点 ]
4.6 敌人
敌人一共有两种,一种在陆地上前进,另一种则会飞行。我们将先创建前一种,然后继承它的大部分属性和函数,略加修改完成另一种。 创建敌人的脚本Enemy.cs: using UnityEngine; using System.Collections; public class Enemy : MonoBehaviour { // 路点 public PathNode m_currentNode; // 生命 public int m_life = 15; // 最大生命值 public int m_maxLife = 1... 查看全部[ 4.6 敌人 ]
4.7 敌人生成器
4.7 敌人生成器 塔防游戏的敌人通常是成批出现,一波接着一波,因为敌人的数量众多,所以需要一个生成器按预先设置的顺序生成不同的敌人。为了提高工作效率,我们将在Excel中设置每一波出现的敌人,然后将其导出为XML格式,敌人生成器将读取这个XML文件,按其设置生成敌人。 4.7.1 在Excel中设置敌人 实际上我们也可以在Unity的Inspector窗口设置组件的数值,但对于一个复杂的项目来说,这么做会使项目的维护变得困难,而游戏策划又偏爱使用Excel表格,所以可以先在Excel中设置数据,再将其导入Unity,这会是一个非常好的选择。 首先要创建一个用于定义XML格式的... 查看全部[ 4.7 敌人生成器 ]
4.8 防守单位
4.8 防守单位 本游戏中唯一的一个防守单位是个袍塔,它的功能很简单,当敌人进入它的攻击范围便会开火。 为了能方便地遍历场景中的所有敌人,我们可以准备一个ArrayList,将所有生成的敌人都存进去,这样可以很容易查找到任何一个敌人。 打开GameManager.cs脚本,添加一个ArrayList属性用来存放所有的敌人。 public ArrayList m_EnemyList=new ArrayList(); 打开Enemy.cs脚本,在Start和OnDisable函数中分别在存放敌人的ArrayList中添加敌人和删除敌人。添加一个SetDamage函数减少生... 查看全部[ 4.8 防守单位 ]
4.9 生命条
4.9 生命条 敌人在受到攻击的时候,我们并不知道它受到了多少伤害,为了能够提示它的剩余生命值,我们需要为它制作一个生命条。 在Project窗口的Rawdata/Lifebar目录下可以找到一个LifeBar.fbx文件,这是一个普通的平面模型,并附有一张贴图,如图4-25所示,贴图由简单的黄色和红色组成,我们将使用改变平面模型UV的方式,使黄色表示剩余生命值,红色表示失去的生命。 图4-25 生命条模型 创建脚本LifeBar.cs: using UnityEngine; using System.Collections; public class Li... 查看全部[ 4.9 生命条 ]
4.10 自定义按钮
4.10 自定义按钮 在塔防游戏中,防守单位都是动态创建的,通常游戏中将提供若干个按钮,当选中其中一个按钮后,这个按钮将保持激活状态,这时在场景中选择位置按下鼠标,即可创建一个防守单位,同时也会扣除一些用于创建防守单位的资金或点数。 接下来我们将创建一个自定义的按钮,虽然使用OnGUI创建按钮更容易,但OnGUI的效率较低,也不利于制作布局复杂或有特殊需求的UI,更难为它制作动画。 创建脚本GUIButton.cs: using UnityEngine; using System.Collections; public class GUIButton : MonoBeha... 查看全部[ 4.10 自定义按钮 ]
小结
小结 本章完成了一个塔防游戏的实例,内容较多,我们使用二维数组定义场景中的单元格数据,制作引导敌人行动的路点,并添加一些简单的编辑器功能帮助设置路点。塔防游戏的敌人较多,设置复杂,我们使用了Excel表格完成了敌人的数据,并导出为XML格式,供Unity使用。最后,我们完成了一个自定义按钮,使用它来创建防守单位。... 查看全部[ 小结 ]