应用unity5.3.4制作flappybird小游戏
flappybird的设计思想:flappybird场景中主要分为背景、小鸟、和柱子。我们需要实现的是场景的布置、小鸟的飞翔动画、背景和柱子的循环移动、加分和碰撞检测以及游戏结束等功能。
(一)准备工作:首先进行的是游戏资源包的下载,下载好背景图片和声音资源以后打开unity,创建好一个新工程,在Assets中建立Animations、bgm、Prefabs、scenes、Scripts、sprites文件夹分别存放小鸟的飞翔动画、背景音乐、预制体、场景、脚本和图片精灵如下图。保存当前场景到Assets-scenes中。
然后把下载的声音资源拖到bgm中,把背景图片资源拖至spirits中,如果图片是一张张分割好的,就依次选中图片在Inspector面板中把每一张图片的格式改为支持透明的sprite格式,如下图:
如果图片资源是规范地拼凑在一起成为一张图片,选中图片,修改Texture Type为sprite后把sprite mode改为multiple,然后点击sprite editor弹出以下窗口:
点击slice后框选分割每一张图片确定-关闭即可。
(二)背景的布置:首先在Game面板中修改显示屏幕的大小,自己添加一个720X1280像素的Android屏幕尺寸,如下图:
(三)制作背景图预制体:把那张天空草地的背景图(名称改为bg)拖至场景中并调整图片尺寸至与屏幕大小契合,并且修改一下Sorting Layer(不同层级的显示顺序) 和 Order in Layer(相同层级的显示顺序)。添加一个Sorting Layer 名字为background,修改bg的Sorting Layer为background,Order in Layer 为-2。如下图:
再把地板的图片拖至场景作为bg的子物体,设置其sorting layer为background,order in layer设为0.给它添加一个Box Collider2D 因为要用来检测和小鸟的碰撞,大小只要刚好包裹到现实地板的地方就行了。然后我们把做好的bg拖入Prefabs文件夹作为一个预制物体。方便重复使用。 然后我们再拖两个预制bg到场景,分别命名为bg_1和 bg_2,三个bg的Position分别为 (0,0,0 )和 (4.81,0,0) 和 (9.62,0,0),这样的拼接是为了美观一些,同时,也是为了能让背景循环播放。做好的场景如下:
(四)制作柱子预制体:首先创建一个空对象GameObject并改名为pipe用来存放柱子,然后把上下两根柱子拖至pipe作为它的子对象分别改名为pipe-up和pipe-down,调节好柱子的位置.然后给pipe-up和pipe-down添加Box Collider2D 用来检测和小鸟的碰撞,为了能够检测小鸟通过两根柱子中间时加分,需要在两根柱子中间创建一个空对象GameObject改名为collider-score,给它添加一个Box Collider2D 用来检测小鸟飞过时加分,并把collider-score拖至pipe作为它的子对象。然后把pipe拖至Prefabs中。
(五) 制作小鸟动画:给小鸟添加一个动画组件animation,在assets下的Animations文件中create一个Animation改名为fly,并把动画fly拖拽至animation组件中的相应位置,然后选择菜单栏window下拉菜单中的animation调出动画制作窗口,然后把小鸟飞行的三个动作图片分别拖拽至相应位置,如下图:
点击运行即可看到小鸟动画效果。为了小鸟具有物理重力和碰撞效果,再给小鸟加上Rigidbody 2D组件和Box Collider2D 组件。
(六)背景的移动:在assets下的scripts文件中创建一个c#文件,改名为Background Transform,其代码如下:
using UnityEngine;
using System.Collections;
public class BackgroundTransform : MonoBehaviour {
static public float moveSpeed = 3f; //定义背景移动的速度
private Transform bgTrans; //获取背景的Transform组件
Vector3 bgPos; //获取当前背景图片的位置
// Use this for initialization
void Start () {
bgTrans = GetComponent<Transform>();
}
// Update is called once per frame
void Update () {
//每一帧都让背景向左移动
bgTrans.Translate(Vector3.left * moveSpeed * Time.deltaTime);
//获取当前帧的背景图片的位置
bgPos = bgTrans.position;
//当第一张图片移动到相机外时,把他的位置拼接到最后。这样就可以实现背景的循环播放
//数据是通过在scene面板拖动得到的
if (bgPos.x < -4.81)
{
bgTrans.position = new Vector3(9.62f, 0, 0);
}
}
}
把
Background Transform拖拽至Prefabs文件中的bg预制体中。点击运行即可看到背景移动效果。
(七) 柱子的移动:在assets下的scripts文件中创建一个c#文件,改名为Pipe Transform,其代码如下:
using UnityEngine;
using System.Collections;
public class PipeTransform : MonoBehaviour {
//获取Transform组件
static public float moveSpeed=3f;
private Transform pipeTrans;
Vector3 pipePos; //获取当前的位置
// Use this for initialization
void Start () {
pipeTrans = GetComponent<Transform>();
}
// Update is called once per frame
void Update () {
//每一帧都向左移动
pipeTrans.Translate(Vector3.left * moveSpeed * Time.deltaTime);
//获取当前帧的图片的位置
pipePos = pipeTrans.position;
//当图片移动到相机外时,把他销毁
if (pipePos.x < -3.27f)
{
Destroy(gameObject);
}
}
}把
Pipe Transform拖拽至Pipe预制体中,点击运行即可看到柱子移动。
(八)柱子自动生成:在assets下的scripts文件中创建一个c#文件,改名为CreatPipe,然后把其添加到Main Camera中,其代码如下:
using UnityEngine;
using System.Collections;
public class CreatePipe : MonoBehaviour {
public GameObject pipe; //用来获取障碍
public float createTime = 1; //用来记录创建障碍的间隔
// Use this for initialization
void Start () {
//过0秒后调用createPipe() 然后每隔createTime秒调用一次
InvokeRepeating("createPipe", 0, createTime);
}
// Update is called once per frame
void Update () {
}
void createPipe()
{
//因为障碍物的位置改变只有上下,所以随机获取他的y值
float y = Random.Range(-1.74f, 2.72f);
//创建一个pipe,位置是上下随机的,其他不变,没有旋转
Instantiate(pipe, new Vector3(13.17f, y, 0), Quaternion.identity);
}
}
把CreatPipe拖拽至Main Camera中,并把预制体Pipe拖入其中,如下图:
点击运行即可看到柱子不断地生成。
(九)小鸟跳动:在assets下的scripts文件中创建一个c#文件,改名为Bird,要实现点击鼠标左键或空格键时小鸟跳动,
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Bird : MonoBehaviour {
private Rigidbody2D birdRig; //获取Rigidbody2D组件
public float upSpeed = 5; //定义点击时给小鸟的向上的力的大小
// Use this for initialization
void Start () {
birdRig = GetComponent<Rigidbody2D>();
}
// Update is called once per frame
void Update () {
//当按下空格键时
if (Input.GetKeyDown(KeyCode.Space)||Input.GetMouseButtonDown(0))
{
//给小鸟添加一个向上的速度
birdRig.velocity = Vector2.up * upSpeed;
}
}
}
(十)
小鸟加分检测:要实现小鸟碰撞柱子间的空对象时加分,首先创建一个分数UI面板,在场景中Creat一个UI-Text,把Text中的文字改为Score:0,居中置顶如图:
然后在Main Camera处加一个管理分数的c#脚本,改名为Game Manage,其代码如下:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
public class GameManager : MonoBehaviour {
//把GameManager做成单例,这样就不用每次都获取对象
private float score = 0; //记录分数
public Text scoreText; //得到分数的文本
private static GameManager _instance;
public static GameManager Instance
{
get
{
return _instance; //可以在其他类通过 _instance 访问该对象
}
}
void Awake ()
{
_instance = this; //赋值该对象
}
//修改分数的方法
public void addScore ()
{
score = score + 1; //分数加一
scoreText.text = "Score: " + score; //设置显示的文本
}
}
要实现碰撞检测则需要在pipe-up、pipe-down的
Box Collider2D 组件中勾选Is Trigger使其成为触发器,然后为了分辨小鸟碰撞到的是什么,给它们分别添加标签为collider-score(先add这些标签后选择), 如下图:
然后在Bird脚本中添加 OnTriggerEnter2D(Collider2D other)方法,当小鸟碰撞到触发器则立即跳至该方法运行,代码如下:
//进入触发器时,通俗的讲就是当小鸟碰撞到障碍中间的空碰撞器时
void OnTriggerEnter2D(Collider2D other)
{
//如果碰撞到的物体的tag是collider_score,用来判断碰撞到的是不是collider_score
if (other.tag == "collider_score")
{
Debug.Log (other.name);
other.SendMessage("addScore");
}
为了使小鸟碰撞到柱子中的collider-score时实现加分,还需要给collider-score添加一个c#脚本改名为ColliserScore,其代码如下:
using UnityEngine;
using System.Collections;
public class ColliserScore : MonoBehaviour {
void Start(){
}
//被小鸟碰撞时调用的方法
public void addScore ()
{
//通过单例模式调用增加分数的方法
GameManager.Instance.addScore();
}
}
(十一)小鸟碰撞柱子时死亡检测:给Pipe预制体中的collider-score即柱子间的空对象勾选
Box Collider2D 组件中的Is Trigger,并添加一个collider-score标签,改其flag为collider-score,如下图:
然后在Bird脚本的OnTriggerEnter2D(Collider2D other)方法中的相应位置添加如下代码:
if (other.tag == "obstacle")
{
GameObject.Find("bird").GetComponent<Bird>().enabled = false;
//GameObject.Find("bird").GetComponent<AudioSource>().enabled = false;
PipeTransform.moveSpeed = 0f;
BackgroundTransform.moveSpeed = 0f;
}//销毁Bird脚本和
PipeTransform脚本以及BackgroundTransform脚本使游戏画面停止。
然后在场景中创建一个UI-Image,并把游戏结束的spirit图片拖拽至相应位置,如下图:
注意把Image前面的勾去掉,等到小鸟碰撞柱子时再通过代码调用它,然后再重载游戏,代码如下(新增的代码添加至Bird脚本的相应位置):
if (other.tag == "obstacle")
{
Debug.Log ("2");
//当碰撞到障碍或地板时播放sfx_hit音效
birdAudioSource.clip = birdAudio[1];
birdAudioSource.Play();
GameObject.Find("bird").GetComponent<Bird>().enabled = false;
//GameObject.Find("bird").GetComponent<AudioSource>().enabled = false;
PipeTransform.moveSpeed = 0f;
BackgroundTransform.moveSpeed = 0f;
GameObject.Find ("GameOver").GetComponent<Image> ().enabled = true;
Invoke ("ReStart", 5);
}
}
void ReStart(){
SceneManager.LoadScene ("flappybird");
PipeTransform.moveSpeed = 3f;
BackgroundTransform.moveSpeed = 3f;
}
(十二)给游戏添加背景音效:我们需要点击鼠标左键时给小鸟添加翅膀扇动的声音,撞击柱子和得分时也添加音效,由于小鸟穿过柱子时可能会同时点击鼠标左键则同时产生翅膀扇动和得分的音效,为了不发生音效调用冲突我们把得分的音效设在
ColliserScore代码中,首先
需要给小鸟添加一个Audio Source组件,然后在Bird和ColliserScore代码的相应位置添加相应代码,添加新代码后的脚本如下:
using UnityEngine;
using System.Collections;
using UnityEngine.UI;
using UnityEngine.SceneManagement;
public class Bird : MonoBehaviour {
private Rigidbody2D birdRig; //获取Rigidbody2D组件
public float upSpeed = 5; //定义点击时给小鸟的向上的力的大小
//用来获取小鸟要播放的音效,记得从文件夹中拖入相关的音频,使用时对应修改索引
public AudioClip[] birdAudio;
private AudioSource birdAudioSource; //用来获取小鸟身上的声音源
// Use this for initialization
void Start () {
birdRig = GetComponent<Rigidbody2D>();
birdAudioSource = GetComponent<AudioSource>();
}
// Update is called once per frame
void Update () {
//当按下空格键时
if (Input.GetKeyDown(KeyCode.Space)||Input.GetMouseButtonDown(0))
{
//给小鸟添加一个向上的速度
birdRig.velocity = Vector2.up * upSpeed;
//当点击空格时播放sfx_wing音效
birdAudioSource.clip = birdAudio[0];
birdAudioSource.Play();
}
}
//进入触发器时,通俗的讲就是当小鸟碰撞到障碍中间的空碰撞器时
void OnTriggerEnter2D(Collider2D other)
{
//如果碰撞到的物体的tag是collider_score,用来判断碰撞到的是不是collider_score
if (other.tag == "collider_score")
{
Debug.Log (other.name);
other.SendMessage ("playScoreAudio");
//给碰撞到的物体发送一个消息,调用addScore方法
other.SendMessage("addScore");
}
if (other.tag == "obstacle")
{
Debug.Log ("2");
//当碰撞到障碍或地板时播放sfx_hit音效
birdAudioSource.clip = birdAudio[1];
birdAudioSource.Play();
GameObject.Find("bird").GetComponent<Bird>().enabled = false;
//GameObject.Find("bird").GetComponent<AudioSource>().enabled = false;
PipeTransform.moveSpeed = 0f;
BackgroundTransform.moveSpeed = 0f;
GameObject.Find ("GameOver").GetComponent<Image> ().enabled = true;
Invoke ("ReStart", 5);
}
}
}
由于一个对象只能有一个Audio Source组件而可以承载不同的声音,因此我们需要在Inspector面板的Bird脚本的size处改为2,并把相应的音频文件拖拽至相应的元素中如下图:
此时游戏制作完成。
(笔者声明:本人是unity初学者,这篇文章是我的学习笔记,可能该笔记做得不够详尽,有什么问题希望大家多多指导和纠正,谢谢~)