使用unity3d制作像素鸟游戏

时间:2024-04-08 20:08:21

个人博客文章链接:http://www.huqj.top/article?id=140

unity3d虽然是被设计用来制作3D游戏的,但是它提供了很多2D组件,所以也可以轻松的设计制作2D游戏,下面记录一下制作经典2D游戏flappy bird的过程。下面是最终效果:(github: https://github.com/Scottle-Hu/MyFLappyBird)

使用unity3d制作像素鸟游戏

使用unity3d制作像素鸟游戏

使用unity3d制作像素鸟游戏使用unity3d制作像素鸟游戏

一、设计

像素鸟的游戏规则非常简单,就是通过点击或者按键控制小鸟向上飞,场景会随机出现障碍物,碰到障碍物就算输。游戏流程一共需要三个场景:开始场景、游戏主场景、游戏结束场景

在开始场景选择开始游戏按钮加入到主场景开始游戏,主场景中失败后进入到结束场景选择继续或者退出。开始和结束场景都是比较简单的,只涉及一些场景跳转。主要的游戏逻辑在主场景中,涉及小鸟的前进和向上飞控制,以及障碍物的随机出现,另外场景是没有尽头的,也就是随着游戏的进行,背景会不断变长。

二、主场景

下面介绍主场景的搭建和脚本编写过程。

①场景搭建

游戏场景主要就是一个垂直的平面,使用unity自带的Quad组件即可,背景组件的属性如下图:

使用unity3d制作像素鸟游戏

首先是该背景的位置和旋转度数,和主相机对应即可。为了给背景加上图片,需要使用一个材质球(这里就是图中的bg)

使用unity3d制作像素鸟游戏

给材质球选择事先添加好的图片即可。除了背景之外,还需要一个天花板和地板,因为当小鸟撞到天花板或者地板的时候也会死,天花板和地板同样使用quad即可,只不过需要水平放置在背景图片的上下,3d透视图如下:

使用unity3d制作像素鸟游戏

主相机和平行光照就不说了,需要注意的是,背景不能只有一个,需要有三个,其中一个是准备背景,即没有障碍物的背景,还需要两个有障碍物的背景,之所以要有两个,是因为为了实现无限背景,会在小鸟进入一个背景的时候在下下个背景的位置添加一个背景,而不能下个位置因为这样可能会导致刚进入背景的时候右边有空缺。背景上需要有标识过一个障碍物的方块和障碍物,都使用cube组件横截背景实现,并且需要将关卡标识设为透明,障碍物需要加一个材质球贴上图片。障碍物的透视图的属性分别如下:

使用unity3d制作像素鸟游戏

使用unity3d制作像素鸟游戏

背景的c#脚本如下:

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

48

49

50

51

52

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

 

//地面背景的脚本

public class BackgroundScript : MonoBehaviour {

 

    //一个背景上有六个障碍物

    public GameObject barrier1;

    public GameObject barrier2;

    public GameObject barrier3;

    public GameObject barrier4;

    public GameObject barrier5;

    public GameObject barrier6;

 

    //背景预制体,用于循环赋值

    public GameObject bg;

 

    //防止重复出发复制背景事件,记录当前背景是否已经被复制

    bool copied = false;

 

    // Use this for initialization

    void Start () {

        //随机初始化障碍物位置

        //上面的障碍物的y坐标在0.55~0.9,下面的障碍物的坐标在-0.55~-0.7

        RandomY(barrier1, 0.4f, 0.7f);

        RandomY(barrier3, 0.4f, 0.7f);

        RandomY(barrier5, 0.4f, 0.7f);

        RandomY(barrier2, -0.5f, -0.2f);

        RandomY(barrier4, -0.5f, -0.2f);

        RandomY(barrier6, -0.5f, -0.2f);

    }

 

    // Update is called once per frame

    void Update () {

         

    }

 

    //当小鸟进入一个背景时,复制一个到下下个

    private void OnTriggerEnter(Collider other)

    {

        Instantiate(bg, new Vector3(this.transform.position.x + 20 * 2, 0, 0), Quaternion.identity);

    }

 

    //随即初始化障碍物的函数

    static void RandomY(GameObject barrier, float min, float max)

    {

        Vector3 v = barrier.transform.position;

        barrier.transform.position = new Vector3(v.x, 10 * Random.Range(min, max), v.z);

        //Debug.Log(barrier.transform.position.y);

    }

}

三、小鸟对象

小鸟是游戏控制的主体,负责交互,小鸟的翅膀扇动效果通过纹理动画实现,即给小鸟加上一个材质球,这个材质球的图片设置为一个三个小鸟状态的图片,通过设置图片的偏移量来表示小鸟的翅膀挥动和死亡,如下:

使用unity3d制作像素鸟游戏

其中Tiling设置图片缩放,Offset设置图片偏移。

小鸟的c#脚本如下:

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

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.UI;

using System.Threading;

using UnityEngine.SceneManagement;

 

//flappy bird 小鸟控制

public class BirdScript : MonoBehaviour {

 

    public float velocity = 0.1f;

 

    //摄像机

    public Camera camera;

 

    //分数UI

    public Text text;

 

    //摄像机与小鸟的初始相对位置

    private Vector3 distance;

 

    //一秒钟运行十帧

    private int frameNum = 10;

 

    private float timeCount;

 

    //记录小鸟贴图的位置,控制纹理动画

    private int birdCount;

 

    //小鸟刚体

    private Rigidbody rigidBody;

 

    //小鸟是否已经GG

    private bool failed;

 

    //通过障碍物个数

    private int score = 0;

 

     

    void Start () {

        //初始化纹理偏移

        birdCount = 0;

        //记录时间帧

        timeCount = 0;

        //初始化刚体

        rigidBody = this.GetComponent<Rigidbody>();

        //小鸟初速度

        rigidBody.velocity = new Vector3(velocity, 0, 0);  //x方向初速度

        //计算摄像机和小鸟的x轴和z轴方向相对位置

        Vector3 cameraPos = camera.transform.position, birdPos = this.transform.position;

        distance = cameraPos - birdPos;

    }

     

     

    void Update () {

        //让小鸟始终保持在游戏平面内

        Vector3 birdPos = this.transform.position;

        this.transform.position = new Vector3(birdPos.x, birdPos.y, 0);

        //小鸟已死,不接受任何操作

        if (failed)

        {

            return;

        }

        if (timeCount > 1.0/frameNum)  //2d游戏一秒10次就可以了

        {

            //小鸟每帧扇动翅膀的动画

            birdCount = (birdCount + 1) % 2;

            //Debug.Log(birdCount);

            this.GetComponent<Renderer>().material.SetTextureOffset("_MainTex"new Vector2(birdCount * 0.3333f, 0));

            timeCount = 0;

        }

        timeCount += Time.deltaTime;

        //Debug.Log(timeCount);

        //控制小鸟向上

        if (Input.GetMouseButtonDown(0) || Input.GetKeyDown(KeyCode.Space))  //按下鼠标左键或者键盘空格键

        {

            //Debug.Log("press");

            //给小鸟一个向上的速度

            rigidBody.velocity = new Vector3(velocity, 3, 0);

        }

        //手机屏幕点击事件

        if (Input.touchCount == 1 && Input.touches[0].phase == TouchPhase.Began)

        {

            //给小鸟一个向上的速度

            rigidBody.velocity = new Vector3(velocity, 4, 0);

        }

        //摄像机与小鸟保持同步

        camera.transform.position = new Vector3(this.transform.position.x + distance.x, 

            camera.transform.position.y, this.transform.position.z + distance.z);

 

    }

 

    //小鸟撞到柱子或者掉到地面

    private void OnCollisionEnter(Collision collision)

    {

        if (failed)

        {

            return;

        }

        string tag = collision.collider.tag;

        if (tag == "Finish")

        {

            Debug.Log(collision.collider.name);

            failed = true;

            //变成死鸟

            this.GetComponent<Renderer>().material.SetTextureOffset("_MainTex"new Vector2(0.6666f, 0));

            //速度变成0

            rigidBody.velocity = new Vector3(0, 0, 0);

            //TODO 播放失败音效,显示游戏结束

 

            //退出当前场景,回到结束场景

            Thread.Sleep(2000);

            SceneManager.LoadScene("end");

        }

    }

 

    //小鸟穿过障碍物

    private void OnTriggerExit(Collider other)

    {

        if (other.tag == "pass")

        {

            score++;

            text.text = "通过障碍物:" + score;

            //TODO 播放通过障碍物的音效

        }

    }

 

 

}

以上就完成了小鸟的设计。注意小鸟死亡的判断是撞到tag为“Finish”的刚体,这里把天花板和地板,以及障碍物都设置为"Finish",而通关标识cube的tag设置为"pass",当小鸟穿过"pass"的时候,分数++,分数的显示见后文。

四、UI组件

这里的UI组件比较简单,只有一个分数显示,小鸟每通过一个障碍物,分数加一,使用Text实现显示分数,Text组件的属性如下:

使用unity3d制作像素鸟游戏

分数组件作为小鸟对象的一个属性,在小鸟穿过障碍物的时候改变。

五、开始和结束场景切换

上面基本完成了主场景的开发,接下来需要加一下开始和结束的逻辑,其实就是场景的切换。

开始按钮点击脚本:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.SceneManagement;

 

public class StartClick : MonoBehaviour {

 

    // Use this for initialization

    void Start () {

        Debug.Log("start...");

    }

     

    // Update is called once per frame

    void Update () {

         

    }

 

    public void OnStartClick()

    {

        SceneManager.LoadSceneAsync("main");

    }

}

结束和再来一局点击脚本:

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

using System.Collections;

using System.Collections.Generic;

using UnityEngine;

using UnityEngine.SceneManagement;

 

public class EndOrAgainClick : MonoBehaviour {

 

    // Use this for initialization

    void Start () {

         

    }

     

    // Update is called once per frame

    void Update () {

         

    }

 

    //点击came over

    public void OnClose()

    {

        Application.Quit();

    }

 

    //点击再来一局

    public void OnAgain()

    {

        //回到主场景

        SceneManager.LoadSceneAsync("main");

    }

}

给按钮添加事件的方法是在属性中设置,如下是开始按钮的事件脚本绑定:

使用unity3d制作像素鸟游戏