本文實(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 來的更快更效率
1
2
3
4
5
6
7
8
9
|
// 比如:當(dāng)點(diǎn)擊打開解釋說明的按鈕時(shí)候 public void clickopenexplainscene() { if (!explainscene.activeself) { explainscene.setactive ( true ); } if (startscene.activeself) { startscene.setactive ( false ); } } |
2.因?yàn)椴还苁悄膫€(gè)場景,背景音樂都只有一個(gè)。所以背景音樂通過單例模式實(shí)現(xiàn)
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
|
// 實(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 ; } } } |
游戲主場景
1 場景的來回切換
通過2個(gè)場景,來回播放實(shí)現(xiàn)
前一個(gè)場景完全移除屏幕后,立刻重新設(shè)置坐標(biāo),并且讓柱子的位置隨機(jī)出現(xiàn)
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
|
// 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)生的碰撞檢測,首先需要設(shè)置鳥和柱子都為is trigger觸發(fā)器,因?yàn)檫@里不需要物理的碰撞效果
提前給所有柱子和上下面設(shè)置好tag,通過tag檢測碰撞,停止移動(dòng)地圖并銷毀鳥
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
// 碰撞檢測 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)出來寫
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
|
// 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ì)算
這里需要再次用到觸碰檢測,給柱子之間空隙加個(gè)透明的檢測器,每次一過柱子就加一分
用單例類存儲(chǔ)分?jǐn)?shù)等數(shù)據(jù):
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
|
// 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)私有對象,三是該類提供了一個(gè)靜態(tài)的公有的函數(shù)用于創(chuàng)建或獲取它本身的靜態(tài)私有對象。 public float score; public float bestscore; public bool ismute; // 用來控制音效 // public bool isfirsttoplay; // 含有一個(gè)靜態(tài)私有對象,這也是唯一一個(gè)對象 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)私有對象 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 - 加入所有場景,- ios - build
會(huì)產(chǎn)生xcode的項(xiàng)目文件
在xcode中打開,在general里設(shè)置下證書(網(wǎng)上教程很多,不需要99刀也能真機(jī)測試)
主要遇到的問題
- 為了設(shè)置分辨率需要調(diào)出game窗口
- 類中的變量,需要提前初始化好,不然就為空報(bào)錯(cuò)。要么從ui上吧對應(yīng)的組件拖下來,要么寫一句getcomponent
- bgm需要拖出來自立個(gè)類寫,因?yàn)樗浑S場景變化而消失或者重復(fù)創(chuàng)建
- 真機(jī)測試的時(shí)候,bundle ldentifier不能亂寫,假如出現(xiàn)security問題,需要在手機(jī)-通用-描述文件與設(shè)備管理中,點(diǎn)擊信任你的蘋果賬號(hào)。
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持服務(wù)器之家。
原文鏈接:https://blog.csdn.net/amy260231120/article/details/78532481