Unity练习FlappyBird

教程及素材源自unity官方的learning资料FlappyBird

整体思路:在游戏里物体本体是不会移动的,只有后面的背景滚轴一直在移动,然后每次在玩家视野外生成随机高度的柱子。柱子和背景一起滚动。

生成鸟的物体

sprite

  • sprite是一种半透明的texture。不会直接被用于mesh,而是会用在长方形或者正方形上
  • 修改texture type就可以修改
  • 与canvas render的区别:前者必须放在canvas里面,而后者可以放在hierarchy的任何地方
  • sprite支持网格构造,可以清除不必要的透明元素,可以一定情况下避免overdraw的问题

sorting layer

  • 在sprite render里面会有一项叫做sorting layer,这个功能可以决定画面的前景和后景的遮挡关系。写的越靠下的越前

rigidbody + collider

  • 需要设置刚体和碰撞关系
  • 这里面的碰撞器设置的种类是多边形的

animator(getcomponent

  • 在这个游戏里,鸟的不同动作会触发不同的动画,所以需要为这个鸟构建一个动画来表现
  • 在animation里面,可以给鸟不同的动作不同的clip。在运行状态下修改鸟在不同clip里面的renderer。
  • 在animator里面可以设置不同动画之间切换的逻辑关系
    • 一种是根据条件切换,需要为不同的条件设置不同的paramter(这里设定的是trigger,这个状态可以直接在script里面set,注意拼写需要一样)(正常 -按-> 挥动翅膀/ 正常 -撞墙-> 死亡)
    • 一种是根据时间切换(挥动翅膀 -> 正常状态)

鸟的行为逻辑

  • 运动:本身的x轴不会运动,y轴在每次按鼠标的时候上升(addForce),不按的时候重力自由落体(对应上升动画)
  • 碰撞:碰撞到地面或者柱子都会死亡(对应死亡动画)
  • 在鸟死亡的时候,会对应鸟的死亡状态在controller里面的切换

UI制作

  • UI使用的就是普通的UI模式,注意所有text都是在canvas里面的
  • 导入素材包字体,可以给字体加阴影
  • UI的分数变化在gamecontroller里面进行操作
  • 字体锚点位置调整需要按alt/option

gameControll

  • 设定了一个static的GameControl(这是这个自建类的名字)的object,名字是instance。设定成static之后,无论在哪里的code里面想要访问这个instance,只需要callGameControl.instance就可以了
  • 为了保证里面拥有这个instance,需要在awake的时候进行检查

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    void Awake()
    {
    if (instance == null)
    {
    instance = this;
    }
    else if(instance != this)
    {
    Destroy(gameObject);
    }
    }
  • 在gameControl里面设置好了游戏结束的变量,这个变量可以直接在bird的script里面访问,这样就可以直接在bird里面决定游戏结束没结束,再在现在的control里面决定分数的变化,scene的切换等

  • 也可以在这里操作,游戏重新开始
    1
    2
    3
    4
    5
    6
    7
    void Update()
    {
    if (gameOver && Input.GetMouseButtonDown(0))
    {
    SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
    }
    }

地面(及背景:作为地面的子物体)

  • 地面应该有collider,这样鸟撞到地面上才会死。需要用rd
  • 地面应该在start开始就按照一个速度进行负移动,如果游戏结束的话,地面停止移动
  • 地面应该复制两份,当每次第一份快要移动到头的时候,第二份移动到第一份前面去(这个距离可以直接用collider的size来决定
  • 地面的rd应该设置成kinematic,也就是除了script让移动,其他的方法不会让他移动

障碍物

  • 障碍物应该设置成prefab,制作好的东西直接拖进prefab文件夹就可以了。在用的时候可以直接在gamecontrol的物体里面操作这个prefab,直接拖进去就可以了
  • 障碍物本身应该增加了一个box collider的trigger,然后在每个柱子本身里面加上了OnTriggerEnter2D(Collider2D other),也就是在这个trigger的区域里面遇到鸟的时候,会call加分的函数

pool

  • 生成柱子的方法,目前的方法是每次生成五个柱子,存在一个array里面,每次时间到了就随机新的柱子的位置。如果五个柱子都用完了就重头开始,也就是从index是0的柱子开始,重新定位坐标
  • 在初始化五个柱子的时候,用了Object.Instantiate,也就是把这五个柱子在指定的位置复制了五次。其中rotation的参数设置的是Quaternion.identity,也就是没有旋转的意思
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class ColumnPool : MonoBehaviour
{
public int ColumnSize = 5;
public GameObject columnPrefab;
public float SpwandRate = 4f;
public float columnMin = -2f;
public float columnMax = 2f;

private GameObject[] columns;
private Vector2 objectPoolPosition = new Vector2(-15f, -25f);
private float timeSinceLastSpwand;
private float spwandXPosition = 10f;
private int currentColumn = 0;

// Start is called before the first frame update
void Start()
{
columns = new GameObject[ColumnSize];
for (int i = 0; i < ColumnSize; i++)
{
columns[i] = (GameObject)Instantiate(columnPrefab, objectPoolPosition, Quaternion.identity);
}

}

// Update is called once per frame
void Update()
{
timeSinceLastSpwand += Time.deltaTime;

if (GameControl.instance.gameOver == false && timeSinceLastSpwand >= SpwandRate)
{
timeSinceLastSpwand = 0;
float spawnYposition = Random.Range(columnMin, columnMax);
columns[currentColumn].transform.position = new Vector2(spwandXPosition, spawnYposition);
currentColumn++;
if(currentColumn == 4)
{
currentColumn = 0;
}
}
}
}

以上,简易版的flappybird就制作完毕了