Unity快速入门之傻瓜小鸟“Flappy Bird”(三)

目的:掌握基本2D游戏开发技巧

知识点:

1.学习UI界面的开发(UGUI)
2.循环往复简单算法
3.脚本之间的常用数据传值
4.2D游戏开发环境
5.2D精灵动画与层的设置

开发步骤

建立良好的目录结构,然后导入贴图与音频资源

搭建场景,为了更好地发布手机,分辨率使用600*800

开始界面,精灵的界面分割(背景界面、小鸟)

(开始场景)小鸟飞行、不断后退的陆地脚本编写

(开始场景)的UI界面

(开始场景)的准备游戏UI界面

正式开始游戏中,碰撞体道具的设置

增加管道,管道必须在“陆地”的后面,所以需要建立“Sorting Layer”.(HeroLayer,LandLayer,BGLayer)
测试静态管道的后退移动。(静态管道专门有自己的移动算法,与业务逻辑)
给主角增加2D碰撞体与2D刚体,管道、地面增加2D碰撞体
主角增加向上的升力

编写游戏碰撞检测控制脚本

定义“管道”循环运行脚本
完善脚本,且测试游戏基本玩法
定义Hero碰撞检测后,游戏结束逻辑处理

游戏的音频处理

资源导入与场景设置

新建2D项目Flappy Bird,注意:存储路径不要有中文,存储文件夹应为空,建议新建一个空文件夹用以存储项目。
建立合理项目文件夹,并将文件资源放入文件夹,
文件资源链接:https://pan.baidu.com/s/1MQY6jWkDKSX3Xyqa2jhFMA?pwd=793p
提取码:793p
放置好以后,如下图所示
在这里插入图片描述
在Game视图中,点击Free Aspect下拉框,将屏幕宽高比例选择自定义600*800,如下图所示
在这里插入图片描述
新建Sprite资源,(GameObject→2D Object→Sprite),将Textures文件夹中的bg背景图拉入Sprite属性栏中的Sprite属性中,并调整大小,如下图所示
在这里插入图片描述

小鸟飞行特效实现

贴图分割

点击资源包中的bird贴图,将其属性栏中的Sprite Mode属性改成Multiple,点击Apply按钮应用以后,点击Sprite Editor按钮,弹出设置框,选择Slice下拉框后点击Sclice按钮,然后点击Apply按钮应用该设置。
点击贴图的右三角,会发现贴图成了三个,全选并拖入层级视图,此时会弹出一个新建动画的提示,修改动画名字后选择保存。调整贴图大小,如下图所示。
注:这里会有可能出现小鸟被压在了背景图的后面,可以调整属性栏中Additional setting下的Orderin Layer的数值,在Layer层类相同的情况下,0数值默认最底层,数字越大,越在上层。
在这里插入图片描述
新建Sprite,将该属性栏中的Sprite设置为资源包中的back贴图,调整大小,如下图所示
在这里插入图片描述

陆地脚本编辑

新建脚本LandMoving.cs,将脚本挂载在陆地贴图控件上。代码如下

/***
 * 
 * “傻瓜小鸟”
 * 
 * Title:陆地移动
 * 
 * 功能:陆地的移动处理
 */
using UnityEngine;

public class LandMoving : MonoBehaviour
{
    
    
    public float floMovingSpeed = 1f;                       //陆地移动的速度
    private Vector2 _VecOriginalPosition;                    //陆地原始位置
    void Start()
    {
    
    
        //保存陆地的原始二维坐标
        _VecOriginalPosition = this.gameObject.transform.position;
    }
    void Update()
    {
    
    
        //循环陆地,如果陆地坐标达到这个坐标,则返回原点,造成视觉魔术,坐标点视个人设置的数值而定
        if (this.gameObject.transform.position.x < -28)
        {
    
    
            this.gameObject.transform.position = _VecOriginalPosition;
        }
        //移动陆地
        this.gameObject.transform.Translate(Vector2.left*Time.deltaTime* floMovingSpeed);
    }
}

在陆地贴图sprite控件上再添加一个Sprite控件,将属性栏中的Sprite放置为back贴图,调整其大小位置,如下图所示
在这里插入图片描述

游戏UI界面开发

由于游戏元素开始变多,故新建一个空物体取名Eviroments,将环境元素拉入归成其子物体。如下图所示
在这里插入图片描述
新建三个Image控件(GameObject→UI→Image),分别命名为ImgGameTitle,ImgRate,ImgOther,一个Button控件(GameObject→UI→Button),命名为BtnStart,将资源包中的贴图分别放入Imgage控件和Button控件属性栏中的Source Image中,其中ImgOther的贴图,使用上文所述的贴图分割,将menu贴图切割,并将排名的贴图拖至Source Image属性中即可,效果如下图所示
在这里插入图片描述
新建Panel控件(GameObject→UI→Panel),命名为MainUI,将Image控件和Button控件设置为其子物体,如下图所示
在这里插入图片描述
将MainUI属性栏中的左上角的勾去掉,UI界面隐藏,如图所示
在这里插入图片描述
新建Panel,命名为PrepareUI,在下面添加Button控件,将其Source Image属性设置为tap贴图,如下图所示
在这里插入图片描述

游戏UI界面切换处理

创建脚本GameMgr.cs,将其挂在新建空物体_GameMgr上,设置MainUI显示,PrepareUI不显示,
代码如下

/***
 * 
 * "傻瓜小鸟"
 * 
 * Title:游戏管理器
 * 
 * 
 * 功能:管理游戏的UI界面
 * 
 */
using UnityEngine; 
public class GameMgr : MonoBehaviour
{
    
    
    public GameObject goMainGameUI;                         //游戏的主UI
    public GameObject goGameTipsUI;                         //游戏玩法提示

    #region 游戏UI界面控制

    /// <summary>
    /// 显示游戏主UI界面
    /// </summary>
    public void DisplayMainUI()
    {
    
    
        //SetActive方法,控制控件显示与不显示
        goMainGameUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏主UI界面
    /// </summary>
    public void CloseMainUI()
    {
    
    
        goMainGameUI.SetActive(false);
    }
    /// <summary>
    /// 显示游戏玩法提示UI界面
    /// </summary>
    public void DisplayTipsUI()
    {
    
    
        goGameTipsUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏玩法提示UI界面
    /// </summary>
    public void CloseTipsUI()
    {
    
    
        goGameTipsUI.SetActive(false);
    }

    #endregion
 
}

在BtnStart的属性界面On Click()中添加方法,如图所示
在这里插入图片描述

设置2D游戏的SortingLayer技术

新建空物体,命名为Pipes,在此空物体上增加六个2D->Sprite,分别命名为Pipe1,Pipe2,Pipe3,Pipe4,Pipe5,将其Sprite属性设置为资源包中的pipe贴图,调整其位置,选择属性栏中的Sorting Layer下拉框,选择Add Sorting Layer,点击+,依次创建Background,Pipes,LandHeroBrids,并将Pieo系列控件的Sorting Layer修改成Pipes层,将BG背景图Sorting Layer修改成Background层,
Lands控件贴图的Sorting Layer修改为Land层,HeroBirds控件的Sorting Layer修改成HeroBirds层。
注:Sorting Layer越往下面,优先级越高,即越优先显示。
如下图所示:
在这里插入图片描述

管道道具移动控制处理

新建脚本PipeMoving.cs,将其脚本拖至Pipes上即可
代码如下(未完善)

/***
 * 
 * “傻瓜小鸟”
 * 
 * Title:管道移动
 * 
 * 功能:控制所有管道道具的移动处理
 */
using UnityEngine;

public class PipeMoving : MonoBehaviour
{
    
    
{
    
    
    public float floCirclePosition=-5f;                         //转换节点
    public float floMovingSpeed = 1f;                       //管道移动的速度
    private Vector2 _VecOriginalPosition;                    //管道原始位置
    private bool _IsStartGame = false;                       //是否开始游戏
    void Start()
    {
    
    
        //保存管道的原始二维坐标
        _VecOriginalPosition = this.gameObject.transform.position;
    }

    void Update()
    {
    
    
        //控制游戏是否开始的标志
        if (_IsStartGame)
        {
    
    
            //循环管道,如果管道坐标达到这个坐标,则返回原点,造成视觉魔术,坐标点视个人设置的数值而定
            if (this.gameObject.transform.position.x < floCirclePosition)
            {
    
    
                this.gameObject.transform.position = _VecOriginalPosition;
            }
            //移动管道
            this.gameObject.transform.Translate(Vector2.left * Time.deltaTime * floMovingSpeed);
        }
        
    }
    /// <summary>
    /// 游戏开始
    /// </summary>
    public void GameStart()
    {
    
    
        //表明开始管道移动
        _IsStartGame = true;
    }
    /// <summary>
    /// 游戏结束
    /// </summary>
    public void GameOver()
    {
    
    
        //表明停止管道移动
        _IsStartGame = false;
        ResetPipesPostion();
    }
    /// <summary>
    /// 管道回到原始方位
    /// </summary>
    private void ResetPipesPostion()
    {
    
    
        this.gameObject.transform.position = _VecOriginalPosition;
    }
}
}

给小鸟添加向上的升力

选择HeroBird,给其增加一个2D碰撞器(打开属性栏→Add Component→Circle Collider 2D),再增加一个2D刚体(打开属性栏→Add Component→Rigibody 2D),创建脚本HeroControl.cs,代码如下

/***
 * 
 * “傻瓜小鸟”
 * 
 * Title:小鸟的控制
 * 
 * 功能:控制小鸟上下移动,本质是给小鸟一个向上的“力”
 * 
 */
using UnityEngine;

public class HeroControl : MonoBehaviour
{
    
    
    public float floUpPower = 3F;                           //向上的升力
    private Rigidbody2D rd2D;                               //2D刚体
    void Start()
    {
    
    
        rd2D = this.gameObject.GetComponent<Rigidbody2D>();
    }
    void Update()
    {
    
    
        if(Input.GetKey(KeyCode.Mouse0))                    //鼠标左键
        {
    
    
            rd2D.velocity = Vector2.up*floUpPower;          //给一个向上的力
        }
    }
}

给管道与地面添加2D碰撞体组件

在Pipe1、Pipe2、Pipe3、Pipe4、Pipe5、Pipe6、Lands、Land的属性栏中都添加一个2D碰撞器(Box Colloder 2D)。适当调整碰撞器大小。

游戏界面完善与调试

修改HeroBird属性栏中Constraints栏中的Freeze Rotation的Z打勾,小鸟碰撞时就不会再翻滚了。把Rigibody中的Is Kinematic打勾(2017版本前)或将Rigibody 2D中的Body Type属性改成Kinematic,即不受重力影响,将挂在的脚本Hero Control.cs的勾去掉,开局先不运行,继续完善GameMgr.cs
,PipeMoving.cs,将HeroBird的Tag属性改成Player,更改后的代码如下:

/***
 * 
 * "傻瓜小鸟"
 * 
 * Title:游戏管理器
 * 
 * 
 * 功能:管理游戏的UI界面
 * 
 */

using UnityEngine;        

public class GameMgr : MonoBehaviour
{
    
    
    
    public GameObject goMainGameUI;                         //游戏的主UI
    public GameObject goGameTipsUI;                         //游戏玩法提示
    private  GameObject _goHeroBird;                           //主角小鸟

    void Start()
    {
    
    
        //查找“主角”,
        _goHeroBird = GameObject.FindGameObjectWithTag("Player");  
    }
    #region 游戏UI界面控制

    /// <summary>
    /// 显示游戏主UI界面
    /// </summary>
    public void DisplayMainUI()
    {
    
    
        //SetActive方法,控制控件显示与不显示
        goMainGameUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏主UI界面
    /// </summary>
    public void CloseMainUI()
    {
    
    
        goMainGameUI.SetActive(false);
    }
    /// <summary>
    /// 显示游戏玩法提示UI界面
    /// </summary>
    public void DisplayTipsUI()
    {
    
    
        goGameTipsUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏玩法提示UI界面
    /// </summary>
    public void CloseTipsUI()
    {
    
    
        goGameTipsUI.SetActive(false);
    }

    #endregion
 
    /// <summary>
    /// 游戏开始
    /// </summary>
    public void StartGame()
    {
    
    
        //道具管道开始
        PipeMoving.Instance.GameStart();
        //去除“小鸟”的一些属性
        _goHeroBird.GetComponent<Rigidbody2D>().isKinematic = false;
        _goHeroBird.GetComponent<HeroControl>().enabled = true;
    }
    /// <summary>
    /// 游戏结束
    /// </summary>
    public void GameOver()
    {
    
    

    }
}
/***
 * 
 * “傻瓜小鸟”
 * 
 * Title:管道移动
 * 
 * 功能:控制所有管道道具的移动处理
 */
using UnityEngine;

public class PipeMoving : MonoBehaviour
{
    
    
    public static PipeMoving Instance;                      //脚本实例
    public float floCirclePosition=-16f;                         //转换节点
    public float floMovingSpeed = 1f;                       //管道移动的速度
    private Vector2 _VecOriginalPosition;                    //管道原始位置
    private bool _IsStartGame = false;                       //是否开始游戏
    void Awake()
    {
    
    
        Instance = this;
    }
    void Start()
    {
    
    
        //保存管道的原始二维坐标
        _VecOriginalPosition = this.gameObject.transform.position;
    }

    void Update()
    {
    
    
        //控制游戏是否开始的标志
        if (_IsStartGame)
        {
    
    
            //循环管道,如果管道坐标达到这个坐标,则返回原点,造成视觉魔术,坐标点视个人设置的数值而定
            if (this.gameObject.transform.position.x < floCirclePosition)
            {
    
    
                this.gameObject.transform.position = _VecOriginalPosition;
            }
            //移动管道
            this.gameObject.transform.Translate(Vector2.left * Time.deltaTime * floMovingSpeed);
        }
        
    }
    /// <summary>
    /// 游戏开始
    /// </summary>
    public void GameStart()
    {
    
    
        //表明开始管道移动
        _IsStartGame = true;
    }
    /// <summary>
    /// 游戏结束
    /// </summary>
    public void GameOver()
    {
    
    
        //表明停止管道移动
        _IsStartGame = false;
        ResetPipesPostion();
    }
    /// <summary>
    /// 管道回到原始方位
    /// </summary>
    private void ResetPipesPostion()
    {
    
    
        this.gameObject.transform.position = _VecOriginalPosition;
    }
}

在PrepareUI中的StartGame按钮上,添加两个Onclick事件,将GameMgr脚本方StartGame和ClosseTipsUI方法挂上去,如下图所示

在这里插入图片描述

道具碰撞检测与游戏结束逻辑处理

添加脚本Pipe.cs,将脚本挂在Pipe1,Pipe2,Pipe3,Pipe4,Pipe5,Pipe6上去
代码如下:

/***
 * 
 * “傻瓜小鸟”
 * 
 * Title:道具:管道
 * 
 * 功能:做“碰撞”检测
 * 如果主角触碰本道具,则游戏Game Over
 */
using UnityEngine;

public class Pipe : MonoBehaviour
{
    
    
    /// <summary>
    /// 2D碰撞检测
    /// </summary>
    /// <param name="col"></param>
    void OnCollisionEnter2D(Collision2D col)
    {
    
    
        //如果检测
        if (col.gameObject.tag=="Player")
        {
    
    
            //道具停止移动
            PipeMoving.Instance.GameOver();
            //显示游戏“提示”界面,主角复位
            GameMgr.Instance.GameOver();
        }
    }
}

完善GameMgr.cs代码,如下

/***
 * 
 * "傻瓜小鸟"
 * 
 * Title:游戏管理器
 * 
 * 
 * 功能:管理游戏的UI界面
 * 
 */

using UnityEngine;        

public class GameMgr : MonoBehaviour
{
    
    
    public static GameMgr Instance;                         //本脚本实例
    public GameObject goMainGameUI;                         //游戏的主UI
    public GameObject goGameTipsUI;                         //游戏玩法提示
    private  GameObject _goHeroBird;                           //主角小鸟
    private Vector2 vecHeroOriginalPosition;                //小鸟初始位置
    void Awake()
    {
    
    
        Instance = this;
    }
    void Start()
    {
    
    
        //查找“主角”,
        _goHeroBird = GameObject.FindGameObjectWithTag("Player");
        //记录小鸟初始访问
        vecHeroOriginalPosition = _goHeroBird.transform.position;
    }
    #region 游戏UI界面控制

    /// <summary>
    /// 显示游戏主UI界面
    /// </summary>
    public void DisplayMainUI()
    {
    
    
        //SetActive方法,控制控件显示与不显示
        goMainGameUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏主UI界面
    /// </summary>
    public void CloseMainUI()
    {
    
    
        goMainGameUI.SetActive(false);
    }
    /// <summary>
    /// 显示游戏玩法提示UI界面
    /// </summary>
    public void DisplayTipsUI()
    {
    
    
        goGameTipsUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏玩法提示UI界面
    /// </summary>
    public void CloseTipsUI()
    {
    
    
        goGameTipsUI.SetActive(false);
    }

    #endregion
 
    /// <summary>
    /// 游戏开始
    /// </summary>
    public void StartGame()
    {
    
    
        //道具管道开始
        PipeMoving.Instance.GameStart();
        //去除“小鸟”的一些属性
        _goHeroBird.GetComponent<Rigidbody2D>().isKinematic = false;
        _goHeroBird.GetComponent<HeroControl>().enabled = true;
    }
    /// <summary>
    /// 游戏结束
    /// </summary>
    public void GameOver()
    {
    
    
        //显示游戏“提示界面”
        DisplayTipsUI();
        //主角(小鸟复位)
        _goHeroBird.transform.position= vecHeroOriginalPosition;
        //处理主角小鸟的属性
        _goHeroBird.GetComponent<Rigidbody2D>().isKinematic = true;
        _goHeroBird.GetComponent<HeroControl>().enabled = false;
    }
}

游戏音频处理

导入资源包音频插件脚本AudioManager.cs,建立一个空物体,命名为AudioMgr,将脚本AudioManager.cs挂在在空物体上面,在空物体上增加组件Audio Listener,将Main Camera中的Audio Listen控件弃用,增加三个Audio Source控件,将其中的Play On Awake勾选去掉,在Audio Clip Array中写4,将音频资源中的四个音频拉进去,修改GameMgr.cs,HeroControl.cs,Pipe.cs,代码如下

/***
 * 
 * "傻瓜小鸟"
 * 
 * Title:游戏管理器
 * 
 * 
 * 功能:管理游戏的UI界面
 * 
 */

using UnityEngine;        

public class GameMgr : MonoBehaviour
{
    
    
    public static GameMgr Instance;                         //本脚本实例
    public GameObject goMainGameUI;                         //游戏的主UI
    public GameObject goGameTipsUI;                         //游戏玩法提示
    private  GameObject _goHeroBird;                           //主角小鸟
    private Vector2 vecHeroOriginalPosition;                //小鸟初始位置
    void Awake()
    {
    
    
        Instance = this;
    }
    void Start()
    {
    
    
        //定义音频的音量
        AudioManager.SetAudioBackgroundVolumns(0.7F);
        AudioManager.SetAudioEffectVolumns(1F);
        //查找“主角”,
        _goHeroBird = GameObject.FindGameObjectWithTag("Player");
        //记录小鸟初始访问
        vecHeroOriginalPosition = _goHeroBird.transform.position;
    }
    #region 游戏UI界面控制

    /// <summary>
    /// 显示游戏主UI界面
    /// </summary>
    public void DisplayMainUI()
    {
    
    
        //SetActive方法,控制控件显示与不显示
        goMainGameUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏主UI界面
    /// </summary>
    public void CloseMainUI()
    {
    
    
        goMainGameUI.SetActive(false);
    }
    /// <summary>
    /// 显示游戏玩法提示UI界面
    /// </summary>
    public void DisplayTipsUI()
    {
    
    
        goGameTipsUI.SetActive(true);
    }
    /// <summary>
    /// 关闭(不显示)游戏玩法提示UI界面
    /// </summary>
    public void CloseTipsUI()
    {
    
    
        goGameTipsUI.SetActive(false);
    }

    #endregion
 
    /// <summary>
    /// 游戏开始
    /// </summary>
    public void StartGame()
    {
    
    
        AudioManager.PlayAudioEffectA("Hurt");
        //道具管道开始
        PipeMoving.Instance.GameStart();
        //去除“小鸟”的一些属性
        _goHeroBird.GetComponent<Rigidbody2D>().isKinematic = false;
        _goHeroBird.GetComponent<HeroControl>().enabled = true;
    }
    /// <summary>
    /// 游戏结束
    /// </summary>
    public void GameOver()
    {
    
    
        //显示游戏“提示界面”
        DisplayTipsUI();
        //主角(小鸟复位)
        _goHeroBird.transform.position= vecHeroOriginalPosition;
        //处理主角小鸟的属性
        _goHeroBird.GetComponent<Rigidbody2D>().isKinematic = true;
        _goHeroBird.GetComponent<HeroControl>().enabled = false;
    }
}
/***
 * 
 * “傻瓜小鸟”
 * 
 * Title:小鸟的控制
 * 
 * 功能:控制小鸟上下移动,本质是给小鸟一个向上的“力”
 * 
 */
using UnityEngine;

public class HeroControl : MonoBehaviour
{
    
    
    public float floUpPower = 3F;                           //向上的升力
    private Rigidbody2D rd2D;                               //2D刚体
    void Start()
    {
    
    
        rd2D = this.gameObject.GetComponent<Rigidbody2D>();
    }
    void Update()
    {
    
    
        if(Input.GetKey(KeyCode.Mouse0))                    //鼠标左键
        {
    
    
            AudioManager.PlayAudioEffectA("Fly");
            rd2D.velocity = Vector2.up*floUpPower;          //给一个向上的力
        }
    }
}
/***
 * 
 * “傻瓜小鸟”
 * 
 * Title:道具:管道
 * 
 * 功能:做“碰撞”检测
 * 如果主角触碰本道具,则游戏Game Over
 */
using UnityEngine;

public class Pipe : MonoBehaviour
{
    
    
    /// <summary>
    /// 2D碰撞检测
    /// </summary>
    /// <param name="col"></param>
    void OnCollisionEnter2D(Collision2D col)
    {
    
    
        AudioManager.PlayAudioEffectA("Dead");
        //如果检测
        if (col.gameObject.tag=="Player")
        {
    
    
            //道具停止移动
            PipeMoving.Instance.GameOver();
            //显示游戏“提示”界面,主角复位
            GameMgr.Instance.GameOver();
        }
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_49251429/article/details/124714514