Unity實(shí)現(xiàn)Flappy Bird游戲開發(fā)實(shí)戰(zhàn)
本文實(shí)例為大家分享了Unity實(shí)現(xiàn)Flappy Bird游戲的具體代碼,供大家參考,具體內(nèi)容如下
參考:騰訊課程(零基礎(chǔ)制作像素鳥)
環(huán)境:Unity2017.2.0f3
主界面(Main)的制作
沒有什么技巧性
注意點(diǎn):
1.寫好Button的點(diǎn)擊效果,并在UI上添加效果
2.切換界面的實(shí)現(xiàn)不需要通過load,直接設(shè)置SetActive()true or false 來的更快更效率
// 比如:當(dāng)點(diǎn)擊打開解釋說明的按鈕時(shí)候 public void clickOpenExplainScene() { if (!explainScene.activeSelf) { explainScene.SetActive (true); } if (startScene.activeSelf) { startScene.SetActive (false); } }
2.因?yàn)椴还苁悄膫€(gè)場(chǎng)景,背景音樂都只有一個(gè)。所以背景音樂通過單例模式實(shí)現(xiàn)
// 實(shí)現(xiàn)背景音樂播放的單例類 using System.Collections; using System.Collections.Generic; using UnityEngine; public class BGSingleton : MonoBehaviour { private static BGSingleton instance = null; public AudioSource audioSource = null; public static BGSingleton getSingleton() { if (instance == null) { instance = new BGSingleton (); } return instance; } void Awake () { if (instance != null && instance != this) { Destroy (this.gameObject); } else { instance = this; Debug.Log ("create"); } DontDestroyOnLoad (this.gameObject); } //通過主界面上的開關(guān)button控制是否靜音 public void IsPlay(bool isPlay) { if (isPlay == true) { audioSource.mute = false; Debug.Log ("play background music"); } else { audioSource.mute = true; } } }
游戲主場(chǎng)景
1 場(chǎng)景的來回切換
通過2個(gè)場(chǎng)景,來回播放實(shí)現(xiàn)
前一個(gè)場(chǎng)景完全移除屏幕后,立刻重新設(shè)置坐標(biāo),并且讓柱子的位置隨機(jī)出現(xiàn)
// mapMove.cs using System.Collections; using System.Collections.Generic; using UnityEngine; public class mapMove : MonoBehaviour { public float speed = 300f; public RectTransform tube1; public RectTransform tube2; private RectTransform transform; // Use this for initialization void Awake () { transform = GetComponent<RectTransform>(); } // Update is called once per frame void Update () { // Translate:Moves the transform in the direction and distance of translation. // If you add or subtract to a value every frame chances are you should multiply with Time.deltaTime. // When you multiply with Time.deltaTime you essentially express: // I want to move this object 10 meters per second instead of 10 meters per frame. transform.Translate (Vector3.left * Time.deltaTime * speed); // 如果前一個(gè)地圖移到-764以外的地方,重放到764 if (transform.anchoredPosition.x <= -764) { transform.anchoredPosition = new Vector2 (764, 0); // 設(shè)置水管的位置為隨機(jī)出現(xiàn),x不變,y隨機(jī)出現(xiàn) tube1.anchoredPosition = new Vector2 (tube1.anchoredPosition.x, Random.Range (-110, 200)); tube2.anchoredPosition = new Vector2 (tube2.anchoredPosition.x, Random.Range (-110, 200)); } } }
2 主要是鳥和柱子接觸后產(chǎn)生的碰撞檢測(cè),首先需要設(shè)置鳥和柱子都為is Trigger觸發(fā)器,因?yàn)檫@里不需要物理的碰撞效果
提前給所有柱子和上下面設(shè)置好tag,通過tag檢測(cè)碰撞,停止移動(dòng)地圖并銷毀鳥
// 碰撞檢測(cè) void OnTriggerEnter2D (Collider2D other) { // 如果鳥碰到柱子 if (other.gameObject.CompareTag("tube")) { if (!gameOver.activeSelf) { gameOver.SetActive (true); audioManager.singer.setAudio (audioClipType.hit); } // 通過地圖的名字獲取到地圖移動(dòng)腳本 mapMove map1 = GameObject.Find ("map1").GetComponent<mapMove> (); map1.enabled = false; mapMove map2 = GameObject.Find ("map2").GetComponent<mapMove> (); map2.enabled = false; Rigidbody2D playerRigidBody2D = GameObject.Find ("player").GetComponent<Rigidbody2D> (); Destroy (playerRigidBody2D); } }
3 音效設(shè)置和鳥的朝向問題
因?yàn)轼B震動(dòng)翅膀的聲音需要和其他音效不是一個(gè)線程,所以只能單獨(dú)領(lǐng)出來寫
// playerController.cs using System.Collections; using System.Collections.Generic; using UnityEngine; public class playerController : MonoBehaviour { private Rigidbody2D player; public AudioSource playerAudio; public float speed; // Use this for initialization void Start () { player = GetComponent<Rigidbody2D>(); // 重置分?jǐn)?shù) gameSingleton.getSingleton ().score = 0; } // Update is called once per frame void Update () { // 如果鳥被銷毀游戲結(jié)束了,直接返回 if (player == null) { return; } // 當(dāng)點(diǎn)擊鼠標(biāo),給鳥一個(gè)向上的速度 if (Input.GetMouseButtonDown (0)) { player.velocity = new Vector2(0, speed); // audioManager.singer.setAudio (audioClipType.wing); // 因?yàn)槌岚虻穆曇艉瓦^柱子的聲音,不能是同個(gè)線程的 if (!gameSingleton.getSingleton ().isMute) { playerAudio.Play(); } } // 通過判斷鳥的速度正負(fù)設(shè)計(jì)鳥的頭的轉(zhuǎn)向, if (player.velocity.y > 0) { transform.eulerAngles = new Vector3 (0, 0, 45); } else { transform.eulerAngles = new Vector3 (0, 0, -45); } } }
4 分?jǐn)?shù)的計(jì)算
這里需要再次用到觸碰檢測(cè),給柱子之間空隙加個(gè)透明的檢測(cè)器,每次一過柱子就加一分
用單例類存儲(chǔ)分?jǐn)?shù)等數(shù)據(jù):
// gameSingleton.cs using System.Collections; using System.Collections.Generic; using UnityEngine; public class gameSingleton { // 使用單例模式記錄分?jǐn)?shù) // 顯然單例模式的要點(diǎn)有三個(gè);一是某個(gè)類只能有一個(gè)實(shí)例; // 二是它必須自行創(chuàng)建這個(gè)實(shí)例;三是它必須自行向整個(gè)系統(tǒng)提供這個(gè)實(shí)例。 // 從具體實(shí)現(xiàn)角度來說,就是以下三點(diǎn):一是單例模式的類只提供私有的構(gòu)造函數(shù), // 二是類定義中含有一個(gè)該類的靜態(tài)私有對(duì)象,三是該類提供了一個(gè)靜態(tài)的公有的函數(shù)用于創(chuàng)建或獲取它本身的靜態(tài)私有對(duì)象。 public float score; public float bestScore; public bool isMute; // 用來控制音效 // public bool isFirstToPlay; // 含有一個(gè)靜態(tài)私有對(duì)象,這也是唯一一個(gè)對(duì)象 private static gameSingleton singer; // 私有的構(gòu)造函數(shù) private gameSingleton () { score = 0; bestScore = 0; isMute = false; // isFirstToPlay = true; } // 提供一個(gè)靜態(tài)的公有函數(shù) 用于創(chuàng)建或獲取本身的靜態(tài)私有對(duì)象 public static gameSingleton getSingleton() { if (singer == null) { singer = new gameSingleton (); } return singer; } public void setBestScore() { if (score > bestScore) { bestScore = score; } } }
5 最后的gameover界面的動(dòng)畫效果,可以通過Unity的Animation窗口制作
導(dǎo)入到iOS設(shè)備上
File- BuildSetting - 加入所有場(chǎng)景,- iOS - build
會(huì)產(chǎn)生xcode的項(xiàng)目文件
在xcode中打開,在General里設(shè)置下證書(網(wǎng)上教程很多,不需要99刀也能真機(jī)測(cè)試)
主要遇到的問題
- 為了設(shè)置分辨率需要調(diào)出Game窗口
- 類中的變量,需要提前初始化好,不然就為空?qǐng)?bào)錯(cuò)。要么從UI上吧對(duì)應(yīng)的組件拖下來,要么寫一句getComponent
- BGM需要拖出來自立個(gè)類寫,因?yàn)樗浑S場(chǎng)景變化而消失或者重復(fù)創(chuàng)建
- 真機(jī)測(cè)試的時(shí)候,Bundle ldentifier不能亂寫,假如出現(xiàn)security問題,需要在手機(jī)-通用-描述文件與設(shè)備管理中,點(diǎn)擊信任你的蘋果賬號(hào)。
以上就是本文的全部內(nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
C# MeasureString測(cè)量字符串函數(shù)的使用方法
這篇文章主要介紹了C# MeasureString測(cè)量字符串函數(shù)的使用方法,需要的朋友可以參考下2014-10-10C#實(shí)現(xiàn)簡單過濾非法字符實(shí)例
這篇文章主要介紹了C#實(shí)現(xiàn)簡單過濾非法字符的方法,涉及C#針對(duì)字符串遍歷與判斷的相關(guān)技巧,非常簡單實(shí)用,需要的朋友可以參考下2015-11-11C# 實(shí)現(xiàn)對(duì)PPT文檔加密、解密及重置密碼的操作方法
這篇文章主要介紹了C# 實(shí)現(xiàn)對(duì)PPT文檔加密、解密及重置密碼的操作方法,非常不錯(cuò),具有參考借鑒價(jià)值,需要的朋友可以參考下2017-11-11C#事件中的兩個(gè)參數(shù)詳解(object sender,EventArgs e)
這篇文章主要介紹了C#事件中的兩個(gè)參數(shù)詳解(object sender,EventArgs e),具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-09-09C#?winform實(shí)現(xiàn)中英文切換功能的四種方式
這篇文章主要介紹了在C#?winform應(yīng)用程序中實(shí)現(xiàn)中英文切換功能的四種方式,資源文件(Resources),本地化(Localization),動(dòng)態(tài)設(shè)置控件字體和切換語言環(huán)境這四種方式,下面將詳細(xì)介紹每種方式及其具體實(shí)現(xiàn),并討論它們的優(yōu)缺點(diǎn),需要的朋友可以參考下2024-04-04