我的Unity3D学习日记-06(自己动手制作FlappyBird)

自从上次跟着敲了官方示例拾荒者之后,开始对Unity制作2D游戏感兴趣了起来,虽然本文标题叫做Unity3D学习日记。但是Unity其实本来名字里是没有3D这俩字的……很有名的雨血前传 蜃楼就是一个使用了Unity来开发的2D游戏。

用Unity做2D游戏有几个优势(对我来说):1.可以继续使用我感兴趣的Unity引擎,不用转回局限性较大的cocos2d,当然,这点是废话。2.Unity的跨平台机能依然是去选择它的很重要的一个因素。3.还没想好。

前几天本来想再琢磨一个官方的2D游戏样例,就是一个土豆人扛着火箭筒杀外星人的,很多视频教程都喜欢用它来做实例,而我觉得国内的讲师节奏太慢,选择了观看官方原版视频,果不其然,听力受限。故找到了一位听译的视频作者制作的视频观看,再次非常感谢,来自B站的风农同学。然后偶然间看到了另一个人发的自制视频,叫做教你用Unity 20分钟做出FlappyBird,我点进去刚看了2分钟立马关了视频,不是因为有急事,而是我觉得如果我独立思考着制作也许会更有意思一些。这个想法也来源于一直是在看视频学习,而没有亲自上手制作过一款完整的游戏。当时已是深夜,于是决定第二天在一天之内自己独立制作一个仿照FlappyBird的小游戏。

废话说了那么多,下面开始简单展示一下制作的流程。

第一步,绘制可能会用到的Sprite。

既然是自制的小游戏,自然不想使用网上的素材,于是开始直接用电脑绘制一些简单的几何图形组成的Sprite。

我的Unity3D学习日记-06(自己动手制作FlappyBird)_第1张图片

↑首先是鸟的Sprite,想要未来添加一个简单的动画,所以眼球鸟嘴分开做了其实就是几个几何图形


我的Unity3D学习日记-06(自己动手制作FlappyBird)_第2张图片

↑ 在FlappyBird中作为障碍物的迷之管道。

我的Unity3D学习日记-06(自己动手制作FlappyBird)_第3张图片

↑ MyFlappyBird标题。。弄这么霸气是个人的恶趣味

我的Unity3D学习日记-06(自己动手制作FlappyBird)_第4张图片

↑ 最后是来自我的签名Pb。。(CSDN的这个编辑器使用直接上传的图片好像并不能改大小,每张上传上来都奇大无比,下次试试Markdown编辑器)

我的Unity3D学习日记-06(自己动手制作FlappyBird)_第5张图片

↑ 最后制作的作为背景云朵的Sprite(由于本来Png背景是透明的,云是白色的,上传之后背景自动变为白色,所以现在是一个只能看见灰色圆球的情况。。)


第二步,在Unity里制作可能要使用到的Prefab

我的Unity3D学习日记-06(自己动手制作FlappyBird)_第6张图片

由于是整个游戏做完之后才截的图,所以上面挂了很多组件,其实都是后来陆续一点点添的,最开始就只有Rigibody2d和一个圆形Collider2d,

为什么上面没有SpriteRenderer呢?


嗯。是因为Bird由切割过的Sprite组合而成,每个子组件分别使用SpriteRenderer渲染。

接下来是用于阻挡小鸟用的管道的Prefab:

我的Unity3D学习日记-06(自己动手制作FlappyBird)_第7张图片

没什么特别的。3个碰撞体,上下管子各一个,中间空气一个用于加分。


第三步,写脚本。

大概构思使用3个脚本,Bird身上一个用于每次点击时给鸟一个向上的力,以及检测是否碰撞到了管道,来判断游戏是否结束,还有检测是否通过了管道中间的部分来加分,以及最后添加上的一部分音效,代码如下:

using UnityEngine;
using System.Collections;

public class Bird : MonoBehaviour {
    public float flyforce = 500f;
    private Rigidbody2D rbody2d;
    public bool isGameOver = false;
    public int score;
    public AudioSource addScore;
    public AudioSource die;
    CircleCollider2D circleCollider2d;
	void Start () 
    {
        rbody2d = GetComponent();
        //addScore = GetComponent();
        circleCollider2d=GetComponent();
    }

	
	void Update () {
        if (Input.GetMouseButtonDown(0))
        {
            fly();
        }
	}


    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag=="Wall")
        {
            gameover();
        }
        
    }

    public void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.tag == "MainCamera")
        {
            gameover();
        }
        if (collision.gameObject.name=="wall_scoreget")
        {
            score++;
            addScore.Play();
        }
        
    }

 

    void gameover()
    {
        //print("Game Over");
        isGameOver = true;
        circleCollider2d.enabled = false;    
        rbody2d.AddForce(new Vector2(0, flyforce*2));  //在死亡时会关闭碰撞,并使鸟向上跳一下,是模仿马里奥的死亡模式
        die.Play();
    }
    void fly()
    {
        if(!isGameOver)  //没死才能调用fly使鸟向上飞
        {
        rbody2d.AddForce(new Vector2(0, flyforce));
        //print("Called a fly function");
        
        }
    }
}

第二部分是Wall的脚本,主要就是让管道生成之后自动向左移动,在移到一定X轴坐标时自我销毁,代码如下:

using UnityEngine;
using System.Collections;

public class Wall : MonoBehaviour {
    public float movespeed = 5f;
	void Start () {
       
	   
	}

    public void OnTriggerExit2D(Collider2D collision)
    {
        if (collision.gameObject.name == "Out")
        {
            print("des");
        }
    }

   

	void Update () {
        gameObject.transform.Translate(-movespeed * Time.deltaTime, 0, 0);
        if (gameObject.transform.position.x<-13f)
        {
            Destroy(gameObject);
        }
	}
}

第三部分是Main,挂载在MainCamera上,用于管理游戏进行的一些事务,主要是刷新GUI、判断游戏是否结束、判断重新加载场景。其中还有一些细节,比如在鸟死亡时的反应、在游戏结束后什么时候能重开游戏的一些判断,会在注释中提到。

using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Main : MonoBehaviour {

    public Bird  birdscript;
    public GameObject wall;
    private GameObject bird;
    private Rigidbody2D birdrbody2d;
    bool gamestart = false;
    bool isGameOver = false;
    bool readyForRestart = false;
    
    int showscore;
    public Text score;
    public GameObject gameovertext;
    public Text startTip;
    public GameObject restartTip;
    public GameObject title;

	void Start () {
        bird=GameObject.Find("Bird");
        birdrbody2d = bird.GetComponent();
        birdrbody2d.gravityScale = 0;  //在游戏刚开始时,使鸟的重力缩放为0,这样在第一次单击之前鸟会保持一个漂浮的状态
        InvokeRepeating("creatwall",0f,1f);
       
	}
	
	// Update is called once per frame
	void Update () {
        if (gamestart==false&&Input.GetMouseButtonDown(0))
                gamestart = true;
        if (gamestart)
        {
            birdrbody2d.gravityScale = 1; //第一次单击游戏开始,鸟开始拥有1倍重力
            startTip.text = "";
            title.SetActive(false);
        }
        isGameOver=birdscript.isGameOver;
        showscore = birdscript.score;
        score.text = "分数:" + showscore; //刷新得分GUI
        if (isGameOver)
        {
            //print("game over in main");
            gameover();
        }
        if (readyForRestart&&Input.GetMouseButtonDown(0))
        {
            SceneManager.LoadScene(0);  //当准备好重开之后单击才会重新加载场景

        }
	}

    void creatwall()
    {
        if (gamestart&&!isGameOver)
        {
            Instantiate(wall, new Vector3(6.2f + Random.Range(-1f, 1f), Random.Range(-1.82f, 1.82f), 0), Quaternion.identity); //在屏幕右边实例化管道
            //位置具有一定随机性
        } 
    }

    void gameover()
    {
        gameovertext.SetActive(true);
        birdrbody2d.gravityScale = 7;   //在死亡时更改鸟的重力,使其快速下落
        Invoke("prepareForRestart", 2);  //在玩家死亡之后2秒才可以重开游戏
    }
    void prepareForRestart()
    {
        restartTip.SetActive(true);  //显示重开游戏提示GUI
        readyForRestart = true;
    }
}


第四步,加背景,加动画,加音效

这里就不详细讲了,背景就是之前画的云朵,也给云朵添加了一个会缓慢上下运动的动画,然后给鸟添加了一个眼球左右动的动画,鸟嘴上下微动的动画,都是作为默认的状态,为了不让鸟显得太过于死板。

音效可能是唯一非原创的部分,因为确实不会制作音效。。于是从网上下载了FALCOM双星物语里经典的村庄BGM作为BGM,马里奥中起跳的音效作为加分的音效,以及一个音量递减的低音作为死亡的音效。具体如何添加可以在代码中看出来,并没有像一般的做法专门添加一个音频管理器,因为音效较少,可以选择直接挂在在对象身上。


第五步,测试。效果可以见下GIF:


(由于GIF录制的原因,实际游戏运行速度比GIF中展示的要快,而且录制的过程中有点掉帧)

第六步,移动端适配调整,这一步暂且还没有做好,因为新换了Unity 5.X的版本,对安卓SDK要求23以上,之前用的22的不行了,新的SDK还没下好,大概导出到安卓平台的话Input.GetMouseDown()用不了吧,当然也还没测试,如果不行可以换成Input.GetTouch(0).Phase==TouchPhase.Down来试试。

这里适配或许会更新,或许会在下一篇里写到吧。


大概整个MyFlappyBird就是这样做出来的,大概前天用了4个小时吧,这篇总结是前天晚上开始写,然后昨天写了一天论文,今天中午继续写完了这篇学习日记。

你可能感兴趣的:(unity3d)