unity入门制作space shooter

目标

  • 这个游戏是和雷电类似的游戏
  • 需要设定碰撞等等游戏逻辑,然后设计音乐,图等等东西

setup,player,camera

set up

  • 需要确定好应用的开发平台file-build setting
    • 注意这个游戏想开发网页版的,但是现在已经不支持web player,建议使用web GL
  • 可以在project setting-player里面改变一些游戏的设置(这里改变了宽度和高度)
  • 在右上角的layout可以改变窗口的布局

放置游戏的object

  • 直接从model里面拖进来放进scene或者hierarchy里面
    • 点击F可以锁定这个东西(最佳视角)
  • 需要设置这个object在原点
  • 有一个mesh filiter来决定这个东西用的什么模型
  • 一个mesh renderer来渲染这个模型
    • 这个里面有两个不同的材料
  • 因为需要物体之间的碰撞,所以需要增加physics--rigidbody
    • 加入了这个东西之后,物体就有了物理上的特征
  • 下面由于需要碰撞,所以需要定义这个物体的体积
    • 增加一个physics -- capsule collision
    • 相当于把这个物体的周围加上了一个cage,来确定他的体积
    • 需要在这里面定义碰撞的方向(因为这里面是沿着z运动的,所以碰撞在z轴上面)
    • 可以改一改视角,然后直接拉bar来调节这个consule的大小
  • 关于coliider
    • 除了这里面用到的胶囊型的以外,还有square的sphere的,confound的(混合)?,在能解决问题的时候尽量用上面的基础图形
    • 除此之外,还有一个mesh coillder,用来专门契合这个物体的体积的,但是是最后的选择,选择的时候最好也选择一些比较简单的形状(如图所示,新的碰撞范围会完整契合这个物体)
    • 在coillder里面可以自己设定这个对应的mesh的种类,即使和使用的模型不同也可以(也就是说可以建立一个相对于这个模型简单的模型,然后建立碰撞)

  • 为了选中的这个东西可以被识别为碰撞物体,选择is trigger
  • 为了增加一点神奇的新功能,在预设好的prefab(一个可以重复克隆的对象)里面找到一个引擎的动画,拖到player的子目录下面,这个东西就自动加进去了

相机和light

相机

  • 因为一开始相机会初始化在物体之后的位置,所以现在在game界面只能看到这个物体的屁股部分,需要设置相机
  • 点击main camera,这时候右下角会出现相机位置的缩略图
  • 位置 -> 调节到物体上方,并且旋转90度
  • 设置相机的种类
    • 如果选择perspective的相机,可以通过调节FOV来决定看到的是多大
    • 这里选择orthographic(正投影,主视图那种感觉)的相机,然后直接调节看到的size就可以了
    • 因为希望object保持在原点上,所以在这里移动camera
  • 可以在game画面里面直接调节object的位置等等东西
  • 下面把在camera里面把背景改成黑色(soild color)
    • 但是这时候object的颜色并没有变黑,这是因为打开了ambiant light
    • window--rendering--lighting setting里面,把source改成color就可以改变环境光的颜色
  • 环境光:ambient light
    • 这个光没有方向,所以如果都加上了的话可能会很奇怪

  • 创建一个有方向的light -> main light

    • 应该是最亮的光
    • 希望可以看到飞机的颜色但是不希望太亮
    • 调整这个光的角度以及强度
  • 建立第二个光,来照亮不怎么亮的部分 -> fill light

    • 还是调整角度,照亮第一个光照不到的部分
    • 为了不让这个光那么强,把这个光的强度适当调小
    • 为了适应太空的冷色调,把光源颜色改成蓝绿色
  • 最后增加第三个光,把暗部勾边(相当于素描里面的在边上的高亮部分) -> rim light

    • 为了不照亮东西的上层,在x轴把角度调成复数
    • 为了勾边,颜色是白色的
    • 降低亮度
  • 最后建立一个新的空的object,位置reset好,来整理上面的三个光
    • 注意,因为这里的光是directional light,所以光照的效果和光源的位置无关,只和光源的角度有关

背景

  • 新创建一个quad,调整位置和角度让相机能看到他
  • remove掉碰撞的部分,因为背景不需要
  • 加上texture -> 可以直接把这张图片拽到对应的位置上面
    • 这样会创建一个新的material加到这个mesh的renderer上面去
  • 缩放这个方块,让这个图片可以完全显示(高宽比必须保持!)
  • 这时候照在player上面的光也可以照在背景上面,但是不是很希望这种结果
    • 一种方法是把background完全独立一个layer出来
    • 另一种方法是改变这个texture的shader
      • 这里改成完全的testure,这样就不会受到光的影响了
  • 最后把船从陷入的background里拽出来

移动player

  • 首先需要在player底下建立新的scripts
  • fixedupdate -> 确定物体现在的位置
    • 首先得到垂直和平行的输入(键盘或者鼠标输入)
    • 物体的移动是一个三维的数组,分别是xyz轴,这里y轴的移动是0.0f,其他两个分别是平行和垂直的移动
    • 因为已经用了rigid body,可以从里面给物体一个速度GetComponent<Rigidbody>().velocity -> 这时候移动的非常慢,因为input接收的只是0和1,所以每秒移动一个unit
    • 这时候加上了一个新的speed参数,每次在计算速度的时候乘上这个参数就可以了
    • 注意,因为这里的speed是个public的值,所以可以直接在unity的UI里面进行操作
  • 这时候出现了一个问题,player会跑出屏幕
    • 增加一个判断条件,移动这个东西如果到了边界,那么把position从先reset到边界上
    • 因为这样在更新下一帧之前都不会出界
    • 使用了mathf里面的一个函数clamp,来设定x和z的范围
      • 这个函数超过了下界就会一直显示下界,超过了上届就会一直显示上届
    • 为了不让设定的xmax,xmin,zmax,zmin在UI里面太占地,所以建立了一个新的class来装这些东西(注意新的class不需要继承),然后在需要用的时候建立新的对象,call
    • 为了能在UI里显示,需要在新创建的class上面加上[System.Serializable]
    • 这些边缘设置什么值可以直接把东西拖到边缘然后看看是什么值就可以了
  • tilt或者bank:让飞船到左右移动的时候可以旋转一下
    • 增加了旋转功能Quaternion.Euler

shots

希望把这部分的逻辑和这部分的图像分隔开:这样换模型的时候就很方便了

  • 首先创建一个新的quan,在这个上面加上texture
    • 创建一个新的material,然后再这个里面选择一个texture
    • 然后再把新的material加到对应的东西里面
  • 希望这个东西黑色的部分消失,shader选择mobile--particle--addtive(mobile比较有效率)
  • 增加这个东西的碰撞,去掉VFX的碰撞
  • 然后加上这个光的运动逻辑
    • transform.forward()向前运动,乘上速度
  • 把这个东西设定成一个prefab(直接拖到prefab的文件夹里面)

shoot shots

  • 已经把需要射出去的光线设定成了一个prefab,这时候只要在每次点鼠标的时候把这个东西射出去就可以了
  • 创建一个新的空的object作为player的子目录来定义发出去激光的位置(shotSpawn)
  • 在player中新增一个功能,public的对象是shot和shotSpawn,这两个东西都可以直接从UI里面拖进来,然后设定这个子弹发射的逻辑,每次按下鼠标都并且在0.25秒外会发射子弹
    • 按下鼠标后把showSpawn的transform赋值给shot,这样就知道shot的位置了
  • 问题:现在游戏进行过程中会往root里面增加很多prefab

boundary,hazards,enemy

boundary

在画面里面消失的子弹也删掉 -> 建立一个box

  • 打开trigger
  • 给这个box里面用一个函数,判断是否撞上这个边框,撞上了的话就删除撞上的物体OnTriggerExit
1
2
3
4
5
6
7
public class DestroyByBoundry : MonoBehaviour
{
void OnTriggerExit(Collider other)
{
Destroy(other.gameObject);
}
}

hazrads

会撞上player的陨石

  • 首先建立一个新的陨石对象,这个对象应该可以被撞击的,加上碰撞和刚体
  • 加上这个陨石的自动旋转,使用随机的数字,并且把angular drag改成0
  • 加上激光和陨石碰撞之后,两个东西同时消失的效果
    • 单纯的加碰撞效果会发现因为边界引发的陨石消失bug
    • 因为陨石先和边界碰撞了,然后两个一起消失了
    • 需要把Boundary加上一个新的tag
      1
      2
      3
      4
      if (other.tag == "Boundary")
      {
      return;
      }

爆炸!就是艺术!

  • 在contact destroy的文件里面增加新的爆炸效果
  • 新建一个explosion的gameobject,给这个对象赋值位置Instantiate(explosion, transform.position, transform.rotation);
  • 给player一个新的tag,然后在碰撞里面判断是陨石撞player还是陨石撞激光,赋值不同的爆炸效果
  • 把mover增加到陨石里面,速度设置为负值,这样陨石就能往自己身上掉了

game controller

  • 创建整个游戏的逻辑
  • 设置好的陨石创建成新的prefab
  • 创建一个新的对象作为控制器,加入一个新的对象hazard,初始化好掉下来的敌人的位置,让敌人可以从随机的位置往下掉
  • 每次掉落之间隔着时间(这部分和C++有些不一样),把所有的掉落放在一个while里面
  • 去掉剩余的爆炸效果

score,audio,building

加声音

  • 首先把陨石爆炸的背景音加到陨石的prefab里面
  • 背景音乐加到game controller,武器的音乐加到player
    • 武器的音乐需要在每次发射的时候触发
  • 调整各个音量的大小

计算score

  • 新建一个text,设定好这个text的字体效果之类的
  • 然后把这个text reference到gamecontroller里面,然后把最开始的分数初始化,并且写出来更新score的代码
  • 把这个score reference陨石里面

增加文字效果

  • 需要增加重新开始游戏和游戏结束的text
  • 在游戏逻辑里面加上的是这个玩意怎么更新和计算,需要两个flag判断有没有游戏结束
  • 需要在碰撞里面把player弄死

增加最后的效果

  • 增加陨石
    • 复制之前的asteroid并且给他们不同的模型和碰撞
    • 把之前的对象改成一个数组就可以handle很多个对象了,随机选择
  • 增加移动的小星星(项目里面自带的)
  • 让背景重复起来
    • 把背景设置在一个范围内,一旦超过了这个范围就重新开始