由于初学Unity,写下此文作为笔记,文中难免会有疏漏,不当之处还望指正。
章节列表:
一、从Asset Store中下载资源并导入
二、设置相机投影模式(Projection)
三、创建背景(BackGround)
四、设置灯光(Lighting)
五、创建玩家对象(Player)
一、从Asset Store中下载资源并导入
首先我们新建一个工程,然后点击Window->Asset Store,搜索Space Shooter,找到如下资源:
点击资源进入资源详情,点击导入即可导入。
如果已经下载了资源,那么可以在下载管理中导入(或者在新建项目时点击找到已经下载好的Assets文件夹,新建完成后资源会自动导入):
二、设置相机投影模式(Projection)
该实例是一个二维的游戏,可以设置相机的模式为正交模式(Orthographic),这样在相机的视野内,游戏对象不会随着距离的增加而变小,游戏对象的大小只会受到相机Size属相的影响,Size越大视野越大,游戏对象越小,反之Size越小视野越小,游戏对象越大。在本例中设置主相机的投影模式为正交模式(Orthographic),Size属性设置为10,相机绕X轴旋转90对,让相机正对地面:
三、创建背景(BackGround)
首先在Hierarchy中创建一个Quad,重命名为BackGround,由于背景不需要碰撞器,所以我们删除Mesh Collider组件。由于相机绕X轴旋转了90°,为了使BackGround正对相机,我们需要把BackGround也绕X轴旋转90°。查看背景图片,发现图片大小为1024*2048,为了保持图片的缩放比例,我们设置BackGround的Scale属性为X:15,Y:30,Z:1,然后把背景图片拖放到BackGround上。由于我们的相机是正交相机,游戏对象显示的大小和对象离相机的远近没有关系,为了下一步的制作,我们把BackGround的Position的Y轴设置为-10。这时我们再复制一个BackGround,命名为BackGround_01,并把BackGround_01拖动到BackGround下,让BackGround_01成为BackGround的一个子对象,重置一下BackGround_01的Transform属性,并把Position的Y轴属性设置为-1,制作好的背景如下所示:
BackGround的属性如下所示:
为了让背景能够有一个缓慢滚动的效果,我们需要给背景增加一个脚本来执行背景的滚动。点击选中BackGround,点击Inspector视图下方的Add Component->New Script,输入脚本名字BGScroller,编辑脚本内容如下:
(1)、声明两个公有类型的变量,scrollSpeed:背景图片滚动速度,tileSizeZ:滚动长度;声明一个私有变量startPosition记录初始位置
(2)、初始化startPosition的值
(3)、Mathf.Repeat函数原型为:
static float Mathf.Repeat(float t,float length);
该函数类似于模运算符(返回值=t%length),但可以使用浮点数,返回值在0~length之间。例如t=3,length=2.5,返回值为0.5,t=5,length=2.5,返回值为0.0。Time.time为该帧开始时的时间(只读),是游戏开始到现在的时间,单位为秒。Update()中第一句的意思就是随着Time.time一直递增,newPosition的值会在0~tileSizeZ之间重复变化;Vector3.forward是Vector3(0,0,1)的简码,也就是Z轴方向,第二句的意思是让组件沿Z轴方向在0~tileSizeZ之间往复(加上起始点偏移量)。
回到Hierarchy视图,点击BackGround打开Inspector视图,设置scrollSpeed和tileSizeZ的值分别为-0.25和30,-0.25代表BackGround向后(Z轴负方向)移动,该值的绝对值越大滚动速度越快。30代表BackGround图片的高度,我们用BackGround和BackGround_01拼接在一起就是为了让背景在滚动的时候是连续的。运行一下可以看到背景已经可以连续滚动了。
四、设置灯光(Lighting)
为了让现实效果更好,我们需要增加额外的光照。为了实现资源分类的目的,我们将光照单独分组,首先建立一个空的GameObject,重命名为Lighting,将系统默认建立的Directional Light重命名为Main Light,并拖拉到Lighting下,再在Lighting下建立两个Directional Light,分别命名为Fill Light和Rim Light,调整光照角度和光照颜色(可以自行调整有助于理解光照),按照官方的设置,Main Light角度为Rotation(20,-115,0),Fill Light角度为Rotation(5,125,0),Rim Light角度为Rotation(-15,65,0)。
五、创建玩家对象(Player)
我们的游戏是驾驶一架飞船,发射炮弹击落小行星和敌机,如果我们操作失误我们的飞船就会坠毁,那么这样一个对象就应该包括,飞船本体、引擎特效、检测碰撞、弹药挂载点、控制飞船等,让我们一步一步建立起来。
(1)、我们建立一个空的GameObject,将对象置于圆点位置,重命名为Player,我们在Models文件夹下找到飞船模型vehicle_playerShip,将模型拖拽到Player对象下;在Prefabs->VFX->Engines文件夹下找到飞船引擎特效engines_player,将特效拖拽到Player下面,这样我们的飞船模型就建好了。
(2)、给飞船增加刚体组件和碰撞检测器。给飞船增加刚体组件后,我们不希望飞船受到重力的作用而往下掉,所以去掉Use Gravity选项:
添加完刚体后给飞船增加碰撞器组件,我们可以尝试一下胶囊碰撞器(Capsule Collider)和网格碰撞器(Mesh Collider),看看两者的不同之处,首先我们给飞船增加一个胶囊碰撞器(Capsule Collider),设置碰撞器的属性如下所示:
Scene视图中飞船的碰撞边界如下所示:
可以看出,红色圈内的范围也是胶囊碰撞器(Capsule Collider)的检测范围,即使这一部分并没有船体。这就是胶囊碰撞器的特点:检测精度不高,检测范围可能和模型不匹配,但是任何形状的物体都可以使用胶囊碰撞器,并且检测效率较高。
接下来我们删除胶囊碰撞器,给飞船添加一个网格碰撞器(Mesh Collider),点击Mesh参数行右侧的小齿轮,选择碰撞模型为vehicle_playerShip,勾选Convex和Is Trigger:
可以看到飞船的检测范围为紧贴飞船模型的很多三角面片,检测精度非常高:
Mesh Collider的检测精度高,但是性能消耗也很大。有一个折中的办法,就是画出飞船模型碰撞的大概轮廊,这样既可以提高碰撞检测精度,也可以减少性能消耗,具体方法是点击Mesh参数行的右侧的小齿轮,把模型选为已经做好的player_ship_collider,可以看到碰撞检测精简了许多(这里可以把飞船模型的Mesh Renderer选框去掉,就只剩下碰撞检测范围框了):
(3)、给飞船添加武器挂在点。右键点击Player->Create Empty,重命名为ShotSpawn,调整ShotSpawn的位置,使其位于飞船前端,这样当飞船发射子弹时就会从这个位置射出。
(4)、制作子弹预设体。首先建立一个子弹的预设体,具体步骤如下:
a、创建一个空的游戏对象GameObject,重命名为BoltEnemy,给BoltEnemy添加刚体(Rigidbody)组件,去掉刚体组件中的Is Gravity选项,使对象不受重力作用。
b、在BoltEnemy下建立一个Quad,重命名为VFX,在Textures(纹理)文件夹下找到fx_lazer_orange_dff,拖拽到FX上,并在Shader(着色器)中选择Particles->Additive,此时VFX平面平行于相机,相机是无法显示VFX的,所以需要将VFX沿X轴旋转90度:
c、给BoltEnemy添加胶囊碰撞器(Capsule Collider),由于我们只需要一个碰撞器,所以我们先删除VFX对象中的Mesh Collider,然后给BoltEnemy添加一个Capsule Collider,勾选Is Trigger选项,可以点击Edit Collider编辑Capsule Collider的检测范围,也可以手动设置碰撞检测范围:
这里我们设置Capsule Collider的胶囊半径为0.03,高度为0.5,方向为Z-Axis,设置完毕后效果如下:
d、让子弹移动。要让子弹移动,我们需要为子弹添加一个脚本组件,点击BoltEnemy,在Inspector视图底部点击Add Component->New Script,输入脚本名字Mover,完成创建,为了资源的统一管理,我们把Mover拖拽到Scripts文件夹下,编辑Mover内容如下:
首先建立一个公有类型的变量speed,方便在Inspector视图中修改速度值,创建一个Rigidbody类型的私有变量rg,方便在类内部访问对象的刚体组件。在Start()函数中给rg对象赋值并设置刚体的速度,transform.forward为rg对象的运动方向。关于Vector3.forward和transform.forward的区别,可以参考http://blog.csdn.net/kaluluosi111/article/details/17206655。回到Hierarchy视图,选中BoltEnemy设置Mover组件的speed为20,运行一下游戏可以看到BoltEnemy已经可以向前运动了。
e、在Prefabs文件加下新建一个DonePrefabs文件夹,右键点击DonePrefabs->Create->Prefab,新建一个Prefab,重命名为BoltEnemy,将Hierarchy视图下的BoltEnemy拖拽到DonePrefabs文件夹下的BoltEnemy上,完成Prefab的创建:
这时可以删除Hierarchy视图中的BoltEnemy。如果想再次编辑Prefab,可以将制作好的Prefab拖拽到Hierarchy视图中,编辑好以后再拖拽回Prefab,以完成Prefab的更新。
(5)、控制飞船。
a、给飞船增加一个控制器脚本,用来控制飞船的移动。
点击Player->Add Component->New Script,输入脚本名称为PlayerController,编辑脚本内容如下:
公有变量speed用于在Inspector视图中调整飞船的移动速度,私有变量rg用于在类内部访问刚体组件。与Update()函数不同,FixedUpdate()函数是一个与帧率无关的刷新函数,固定时间间隔调用一次,这个时间间隔可以通过Edit->Project Settings->Time,Fixed Timestep参数设定,默认为0.02s。
以下摘自圣典百科:Input是输入系统接口,使用这个类能够读取输入管理器设置的按键,以及访问移动设备的多点触控或加速感应数据。想要读取轴向使用Input.GetAxis方法获取下列默认轴: “Horizontal” 和“Vertical” 映射于控制杆、A、W、S、D和箭头键(方向键)。 “Mouse X” 和“Mouse Y” 映射于鼠标,“Fire1”, “Fire2” “Fire3”映射于键盘的Ctrl、Alt、Cmd键和鼠标中键或控制器的按钮。新的输入设置可以使用输入管理器来添加。注意:每次输入在“Update()“之前不会再更新,所以建议你将所有的输入调用都写在Update方法中(Update循环中)。
回到Unity编辑器,点击Player对象,在Player Controller组件中把speed设置为10,运行游戏,可以看到飞船已经可以移动了。
b、给飞船增加倾斜效果。
打开PlayerController脚本,编辑以下代码:
添加公有变量tilt,便于在Inspector视图中调整倾斜度。Unity内使用四元数(Quaternion)表示所有的旋转,Euler(x,y,z)返回一个旋转角,该旋转角绕z轴旋转z度,绕x轴旋转x度,绕y轴旋转y度(像这样的顺序)。
回到Unity编辑器,点击Player对象,在Player Controller组件中把tilt设置为5,运行游戏,可以看到飞船在移动的时候已经有了倾斜的效果。
c、限制飞船的移动范围。
运行游戏会发现,飞船可以移动到背景以外的地方,所以我们要对飞船的移动范围做一下限制,通过限制Transform组件的position属性,可以达到限制飞船移动范围的目的。由于我们的游戏是俯视图的,所以Y轴方向无需限制,只要限制X和Z轴范围即可。打开PlayerController脚本,编辑以下代码:
首先序列化一个类Boundray,实例化一个对象boundray,用来限制移动范围。Clamp(float value,float min,float max)用来限制value的值在min和max之间, 如果value小于min,返回min,如果value大于max,返回max,否则返回value。
回到Unity编辑器,点击Player对象,按下快捷键W,把飞船分别移动到左右边界,记录下X轴的位置范围,再把飞船分别移动到上下边界,记录下Z轴的位置范围,移动飞船时注意观察Game视图中飞船是否到达了边界。把记录的边界值填入boundray属性中,运行游戏发现飞船已经在范围内移动了。
d、让飞船发射子弹。
当我们按下“Fire1”键时,子弹从子弹挂载点发射出去,所以子弹需要在脚本中动态生成。打开PlayerController脚本,编辑以下代码:
GameObject是Unity场景中所有实体的基类,在这里用于实例化子弹。ShotSpawn用于获取子弹挂载点的位姿信息。fireRate用来设置子弹发射速率。nextFire用于判断是否可以进行下一次子弹发射。当玩家按下了“Fire1”键,并且子弹冷却时间已到,就可以发射下一发子弹。
“Fire1”键是一系列系统定义好的字符串,可以通过Edit->Project Settings->Input来修改键值:
回到Unity编辑器,点击Player对象,为shot和ShotSpawn变量关联对象,把BoltEnemy拖拽到shot变量处,把Player中的ShotSpawn拖拽到ShotSpawn变量处,fireRate改为0.5:
运行游戏,按下鼠标左键或者做Ctrl键,飞船已经可以发射子弹了。
下一篇将制作小行星和敌机。