Unity小遊戲教學最後一章
這篇要講使用者介面(UI),並完成遊戲
這次的程式會比較多,建議先看過前面三篇
本篇分成4個小節:
1. 製作計分板
2. 開始畫面和GAME OVER畫面
3. RESTART和QUIT的按鈕
4. 產生遊戲執行檔
1. 製作計分板
先製作計分板
首先,點一下Hierarchy裡的Main Camera
把Size調到4
然後選Game的畫面,左上角有一個下拉選單,可以選擇main camera比例
選單裡沒有我們要的比例,所以按"+"新增比例
Type選Aspect Ratio
Width & Height 分別是3和4
這樣我們就能選自訂的比例了
我們可以看到選擇正確的比例,畫面旁邊的藍色就會不見了
我們也可以看到Scene裡,Main Camera的外框跟背景一樣大
等一下我們在設定UI的時候,會自動依照這個大小來產生Canvas(畫布)
先來製作分數的文字
在Hierarchy裡點滑鼠右鍵,選UI → Text(文字)
然後會自動產生Canvas和EventSystem
可以看到新增的Text在Canvas底下,遊戲上所有的UI元件都會在Canvas底下
點一下Canvas,設定Canvas Scaler
UI Scale Mode選Scale With Screen Size
Reference Resolution設 X: 600、Y: 800,和背景一樣大
Match是不同螢幕解析度時,依照寬度或高度來改變UI比例
預設是選寬度,剛好是我們需要的,所以不需要改變
Canvas(畫布)是遠大於我們的遊戲畫面的
點兩下Canvas,畫面會自動調整到整個Canvas的大小
左下角的黑色小方塊就是我們原本的遊戲場景(圖中紅色箭頭)
先把Text的名稱改成ScoreText
然後按位置的方塊(圖中紅框)
然後按Alt畫面會變成這樣
選 靠下(圖中紅框)
1. 文字內容 Score: 0
2. 文字大小 Font Size 改 24
3. Alignment 都選置中
Horizontal overflow和Vertical Overflow都選Overflow
4. 顏色選白色
我們可以在Scene這邊看到 Score: 0在螢幕的下方
對應到Game的畫面
我們可以看到畫布上的文字和我們的遊戲場景結合在一起了
從這邊開始Scene和Game會分成兩個畫面來對照
這樣比較容易看UI和遊戲畫面合在一起的樣子
打開GameFunction.cs
最上面加入一行
using UnityEngine.UI; //使用UI
然後宣告
public Text ScoreText; //宣告一個ScoreText的text
public int Score = 0; // 宣告一整數 Score
public static GameFunction Instance; // 設定Instance,讓其他程式能讀取GameFunction裡的東西
在Start()底下加入
Instance = this; //指定Instance這個程式
在最後面加入一個記分的function
public void AddScore()
{
Score += 10; //分數+10
ScoreText.text = "Score: " + Score; // 更改ScoreText的內容
}
打開Invader的程式描述
在碰撞觸發底下加入
GameFunction.Instance.AddScore(); //呼叫GameFunction底下的AddScore()
也就是,當碰撞觸發就會去做加分的動作
在Background的Inspector裡
把ScoreText拉到GameFunction底下的Score Text空格裡
存檔後執行
看看計分有沒有正常運作
2. 開始畫面和GAME OVER畫面
接著製作遊戲開始的畫面
先加入兩個Text
注意,在加入的時候不要點選到其他Text,不然會變成新增在那個Text底下
改名為GameTitle和GameOverTitle
設定GameTitle
1. 位置 X = 0, Y = 100
2. 內容 Space Invader
3. 文字大小 40
4. 置中 置中 Overflow Overflow
5. 顏色白
設定完後,應該會如下圖顯示
GameOverTitle也做相同的設定
只是文字改成GAME OVER!
因為兩個Text的位置相同,所以重疊在一起
不過他們出場的時機不同
接著做開始遊戲的按鈕
Hierarchy點右鍵,加入UI → Button
我們會看到新增了一個Button,底下含有一個Text
名稱改成PlayButton
位置 X = 0, Y = 25
點底下的Text,把內文改成PLAY
在GameFunction底下加入
public GameObject GameTitle; //宣告GameTitle物件
public GameObject GameOverTitle; //宣告GameOverTitle物件
public GameObject PlayButton; //宣告PlayButton物件
public bool IsPlaying = false; // 宣告IsPlaying 的布林資料,並設定初始值false
在void Start ()以下增加
GGameTitle.SetActive(true); //設定GameTitle顯示
GameOverTitle.SetActive(false); //設定GameOverTitle不顯示
// 後的都是備註,備註內容不影響程式執行。備註可以幫助程式理解
把原來的if (time>0.5f) 改成 if(time>0.5f && IsPlaying == true)
也就是時間和IsPlaying兩個條件都滿足的時候才會產生敵人
&&代表兩個條件都要成立,才會執行
加入一個GameStart的Function
public void GameStart()
{
IsPlaying = true; //設定IsPlaying為true,代表遊戲正在進行中
GameTitle.SetActive (false); //不顯示GameTitle
PlayButton.SetActive (false); //不顯示PlayButton
}
設定PlayButton按下去的功能
1. 選PlayButton
2. 按 "+" 新增
3. 把Background物件拖到On Click()的空格裡,我們要的功能在Background底下
選GameFunction底下的GameStart()
點一下Background物件
把GameTitle、GameOverTitle和PlayButton拖曳到GameFunction底下對應的空格
讓GameFunction可以控制這些物件要不要顯示
存檔後執行
應該會看到下面的畫面
測試PlayButton是否正常工作
接著來寫GameOver的畫面,在GameFunction底下加入
public void GameOver() //GameOver的Function
{
IsPlaying = false; //IsPlaying設定成false,停止產生外星人
GameOverTitle.SetActive(true); //設定為ture,顯示GameOverTitle
}
在Invader的底下,碰撞到太空船時,呼叫GameOver()
在if (col.tag == "Ship")底下加入
GameFunction.Instance.GameOver();
存檔後執行
看會不會出現GAME OVER!
3. REASTART和QUIT的按鈕
接著我們要增加REASTART和QUIT的按鈕
加入兩個按鈕
改名成RestartButton和QuitButton
RestartButton位置 X = 0 , Y = 25
QuitButton位置 X = 0, Y = -25
RestartButton底下的Text,改成RESTART
QuitButton底下的Text,改成QUIT
在GameFunction裡加入
public GameObject RestartButton; //宣告RestartButto的物件
public GameObject QuitButton; //宣告QuitButton的物件
在Start()底下加入
RestartButton.SetActive(false); //RestartButton設定成不顯示
所以開始畫面就留下GameTitle、PlayButton和QuitButton
在遊戲進行時不顯示任何UI
GameStart()以下加入
QuitButton.SetActive (false); //QuitButton設定成不顯示
然後在GameOver時顯示GameOverTitle、RestartButton和QuitButton
GameOver()底下加入
RestartButton.SetActive(true); //RestartButton設定成顯示
QuitButton.SetActive(true); //QuitButton設定成顯示
最後是RestartButton和QuitButton的功能
public void ResetGame() //RestartButton的功能
{
Application.LoadLevel (Application.loadedLevel); //讀取關卡(已讀取的關卡)
}
public void QuitGame() //QuitButton的功能
{
Application.Quit(); //離開應用程式
}
設定RestartButton的功能
1. 點RestartButton
2. 按 "+" 新增
3. 把Background物件拖到On Click()的空格裡
4. 選GameFunction底下的ResetGame()
同樣地,設定QuitButton的功能
1. 點QuitButton
2. 按 "+" 新增
3. 把Background物件拖到On Click()的空格裡
4. 選GameFunction底下的QuitGame()
點Background
把RestartButton和QuitButton拖曳到GameFunction底下對應的空格
存檔後執行
看GameOver畫面有沒有多RESTART和QUIT的按鈕
並測試按鈕功能是否正常
QUIT可能會沒作用,要輸出成執行檔才會有作用
4. 產生遊戲執行檔
遊戲終於完成了!
輸出成可以執行的檔案吧!
左上角File → Build Settings...
1. Add Open Scenes
2. 選Space,注意你要Build的Scene,不要選錯
3. 選PC, Mac & Linux Standalone
4. 按Build
選擇存檔位置
設定遊戲畫面,享受你的遊戲!
把這個遊戲輸出到android手機上,請參考 Unity教學 2D小遊戲製作 part 5
想要了解程式的觀念,請參考 初學者如何建立程式的觀念(Scratch教學)
參考教學:

我在IsPlaying為false時,Play按下去沒反應 也就是說遊戲無法開始 須自己將IsPlaying設定為true,才可以按Play執行gamestart事件 此外Restart、Quit無反應,該怎麼處理呢 我的是Unity3D 5.2.0f3,謝謝。
感謝你的回應,已修改內文 如果你是按GameObject → UI → Text 就不會自動產生EventSystem喔
後來發現是我建立text時沒有自動產生EventSystem 在Canvas新增了EventSystem就可以了 感謝你的教學,對初學者來說很實用
謝謝!很高興對你有幫助 ^_^
您好,我已完成所有步驟、語法也無誤,可是我起始畫面原本就有PLAY還多一個QUIT的按鈕,把他從Hier那裏點取消顯示,是變回正常只有PLAY這個按鈕,可是PLAY點下去後,敵人物件自己在中間的時候會撞到看不見的物件自己自行增加分數,請問這要怎麼解決呢?
遊戲開始時有QUIT按鈕是對的 如果你不想要 就在start()加一行 QuitButton.SetActive (false);
敵人物件自己在中間的時候會撞到看不見的物件自己自行增加分數 應該說我發現敵人物件撞上敵人物件也會自行增加分數,這個地方要怎麼解決呢??
對不起,我剛剛有點解決物件撞物件會增加分數的情況了,我只剩下QUIT的問題 不好意思,問題很多,謝謝
您好:想請問,如果遊戲完成後,想要將它放到網路上如網頁遊戲,或是放到手機變成app,這樣要如何操作呢?
在最後的Build Settings選Web player或Android即可
謝謝大大的文章教學!!!! 非常仔細!!! Unity 5.2.1f1 完美成功 !!!
很高興對你有幫助 ^_^
您好,請問如果想令敵人碰到Bottom Side,主角也會爆炸,去GameOver的畫面,可以怎樣寫呢? 另外,也十分感謝你的教學,十分實用:-P
在Bottom Side加入主角爆炸和呼叫GAMEOVER就可以囉 很高興對你有幫助 ^_^
請問為什麼我做到標題那邊戰鬥機就變成無法射擊了呢@@ 拜託大大解答
有錯誤訊息嗎?
你好~~~ 我想要輸出到網頁玩~~ 但是有依照選項輸出~~點了以後好像說沒有這個APP 所以我要怎麼輸出可以變成網頁遊戲呢?
可用IE試試,CHROME應該是不支援
您好 請問一下要如何做成被撞到之後有 幾秒的閃爍時間(不會被碰撞到) 我做出來三次生命 可是會連續被撞到三次
在碰撞條件加上一個時間條件囉
您好我想請問一下 如何能讓開始畫面的主角消失或不能動呢
主角消失:物件SetActive(false) 主角不能動:在移動操控那邊加上IsPlaying = ture這個條件
您好,我想請問 如果希望遊戲開始前不顯示 Sorce: 0 字串 開始後再顯示的話要怎麼做呢?? 同樣的 SourceText 無法同時宣告為 Object 與 Text... OTZ
把內文改成空白字元試試
如何去除啟動動畫
應該是沒辦法,因為免費的
您好,我想請問一下 我在Game視窗底下可以正常執行 但是Build成執行檔後按空白鍵卻沒有動靜 也沒有錯誤訊息 是哪裡出問題了呢?
考倒我了~ 換個鍵試試
回#15 我也跟你一樣的問題 我換了鍵 但是Build後一樣不能執行 可是... 死過一次之後就恢復正常了0.0 哈哈哈哈哈哈 最後謝謝版主 你讓我開始入口第一個小遊戲 雖然很陽春 可是寫得很開心!!!
也許是Unity新版本的問題 很高興對你有幫助囉 ^_^
對第一次寫遊戲真的是獲益良多! 我有照著步驟成功寫出來了! 我想問的,如果想要繼續精進有哪些學習資源呢? (像是該去哪裡學Unity或C#? 沒有的話也可以提供需要學習哪種語言或是平台) *對了對了,之前文章裡面的Enemy好像拼錯了
Unity官方網站就有很多學習資源囉 中文資源可以去魔方網 http://www.mofang.com.tw/unity/
那您是怎麼學的呢! 官網的影片我持續看一個星期了,有點難消化(講的不很細)
直接寫一個遊戲,要什麼功能就去找官網怎麼用 Unity更新很快,很多東西一直在變 有了基本概念後,就可以直接開始寫了
假如在死掉時,GameOver已經跑出來了,有沒有辦法可以讓外星人消失或是讓她不要動,不然這樣看起來好像BUG,而且有時候會擋到GameOver的字。 研究了好久在哪邊加Destory都無法,不知道要怎麼把已經產生的外星人消除。
在外星人底下加入一個條件 if(IsPlaying == false) Destory外星人
跟著做,花了一兩小時就做好 :D 真的非常感謝, 之前有學過unity3d 一些 不過都已經是一年前的事, 所以很快就上手
很高興對你有幫助 :)
版主解釋的真的好詳細~ 一 學就會 最近開始學習unity 看到您的貼文 受益良多阿!! 期待之後新的教學:) 可以教一些 用UNITY3D介面做的教學嗎?! 另外,想請問想給遊戲加入時間倒數可以怎麼做
http://wordpress-tw.marcpov.com/unitycount-down-timer-based-on-audio-length.htm
請問程式碼沒有錯誤卻還是跑不出來GAME OVER 是哪裡出錯了? 該怎麼解決呢?
可能在背景後面,確認一下圖層順序(part1教學)
版主你好,其實我原本是打算什麼都不說就直接完成的(?) 但偏偏在輸出時遇到了瓶頸,我的unity不知道什麼原因似乎PC Mac的這東西,顯示無法使用,且有一個下載點,進入是unity的官網,但他又顯示了無檔案,我到底該怎麼辦? 附註:如果我問到非常基本,或者說非常無用的問題還請板主大見諒新手的愚笨。
我沒遇過這樣的問題耶,重新安裝Unity試試?
版主你好,經過您的推薦,再重新安裝後我發現到了問題癥結點:似乎我當初在裝設unity時將所有的附帶元件都取消下載了,僅有下載了unity的本體,才會導致我現在發生的事。 非常謝謝版主的幫忙。
不用客氣 ^_^
可以麻煩大大新增個暫停的按鈕嗎? 覺得這樣比較方便!
版主好!我在PlayButtin那便選擇小圈圈後,裏頭沒有所謂的Background的程式碼請問要怎麼解決?
存檔後重開Unity試試
大大你好,在 設定PlayButton按下去的功能 1. 選PlayButton 2. 按 "+" 新增 3. 點小圈圈,選Background,我們要的功能在Background底下 選GameFunction底下的GameStart() 這裡的GameStart找不到,但是前面除了爆炸和音樂以外的地方都有做到,請問要怎麼做才會讓GameStart出現呢?
存檔後重開Unity試試
大大您好,我做完part3的步驟之後在試玩時出現三種情況 1.給予LaserObject Audio Source 賦予它Audio Clip音效後,射出的子彈變成一個音效的圖示。 2.給予ExplodeObject Audio Source賦予它Audio Clip音效後,物件的動畫顯示不見了,也一樣變成一個音效的圖示。 3.給予Background Audio Source賦予它Audio Clip音效後,遊戲場景中間就有一個音效圖式該怎麼讓它消失不要擋住遊戲場景畫面。 ※如果大大看不太懂我的敘述我可以把我Run Paly的畫面寄給您
版主請問一下 我現在在做類似的專題研究 如果我想要扣分而有很多不同加分扣分的物品(不適只有單一物品加分) 我該怎麼去寫
版主請問一下 我現在在做類似的專題研究 如果我想要扣分而有很多不同加分扣分的物品(不適只有單一物品加分) 我該怎麼去寫
就是用不同的tag去分類囉 撞到什麼tag加分、撞到什麼tag扣分
版主您好 首先先謝謝您的教學 讓小弟受用無窮 小弟本身完全沒接觸過任何的程式語言 照著版主您的教學弄出了一個射擊遊戲感覺非常的開心 不過遇到了一些小小的問題 就是遊戲結束之後還是有殘餘的敵人落下 雖然已經不會再產生新的敵人了 不過那個剩餘的敵人就是非常礙眼 請問該怎麼修改程式碼讓些殘餘的敵人直接消失呢?
很高興對你有幫助 ^_^ 這個我也不會耶,要再研究
版主你好,你的教學真的很詳細也易懂。太感謝你啦! 但我想開發在android平台上面玩, 請問需要更改哪些部分程式碼呢?
很高興對你有幫助 ^_^ 請參考part 5
可能講得不夠清楚,我想改成用手機觸控按著自動射擊,觸控按著左右移動 要怎麼更改呢? 謝謝你
請問 每次重新開unity 按開始的時候就看不到飛機 事什麼原因呢??
可能是飛機跑道背景後面了,要設定sorting layer
請問如何隨著分數增加提高外星人的下墜速度以提高難度? 大大的教學讓完全不會C的我也做了一個遊戲呢 算是入門的好方法吧
很高興對你有幫助 ^_^ 增加難度要寫程式控制
為什麼 那個飛碟一碰到TOPSIDE就彈出了 GAMEOVER 而且子彈怎麼搞到會飛出場外
請問一下為什麼我在Hierarchy裡的ScoreText不能拉到GameFunction底下的Score Text空格裡..
嗯...我也想不到為什麼
請問分數一直自動增加要怎麼辦= = 我幾乎完成整個遊戲 就是分數那裡找不到解決方法 我沒射外星人 他還是會一直+分 感謝你的教學 我真的做到了 謝謝
應該是AddScore()放錯位置了
不好意思我想請問一下,rigid body是給予物件剛體,也就是讓物件受物理作用引響,但是這則教程裡的物件好像都不需要物理作用,為什麼要用rigid body呢?
Rigidbody才會觸發碰撞的Trigger,記得好像是這樣
Game Over 會是鏡像翻轉?
抱歉,不太懂你的意思
Application.LoadLevel 指令已經在新版廢棄了, 要改成以下 SceneManager.LoadScene(SceneManager.GetActiveScene().buildIndex);
感謝告知! 雖然舊指令已過時,但是目前還能用 另外寫SceneManager.LoadScene("Space"); 也是可以,會簡單點
您好:想請問一下,跟著做後遊戲都正常,但一開始PLAY時,會有一個自動爆炸,自動加十分,不知道為何?謝謝~
可能是有一個雷射或外星人留在場景裡
不好意思請問一下 我的檔案在unity裡的時候外星人還有爆炸特效 可是一輸出出來就沒了 想請問要如何解決 謝謝
可能輸出時,選錯Scene了
不好意思請問一下 我照著教學做我但按開始分數會一直自動加10分要怎麼修改,打到敵人也會加10分
應該是AddScore()的位置放錯囉
請問3d遊戲也可以用這套方法嗎? 如果我是想讓子彈打到物體會計分的話,請問計分程式碼要放在哪裡?謝謝
非常感謝你的教學~~ 讓非本科生即使沒學過Unity也可以完成小遊戲 Coding也解釋得很詳細 總共花三小時完成
請高興對你有幫助 ^_^
你好,我有一個問題想請教~ 玩家每次發射出攻擊後(按space),他本身不知道為甚麼會往下移動,最後會移到遊戲介面外,BottomSide沒有限制助玩家的移動範圍(不過敵人碰到確實會消失) 操作應該都和上面教學是一樣的,可是不知道是哪裡出了差錯? 我在想問跟Canvas(畫布)有沒關係或者其他可能的原因 想請問要如何解決 謝謝~
這是因為子彈撞到飛機了,所以飛機會往後退 可能是你的圖片比較大,所以距離0.6不夠,多加一點就可以了 不好意思,是改版失誤 在part 2那邊有講解,我不小心把文字設定成黑色的 所以講解被隱藏了 QwQ 現在改回來了
你好,我在做到 "測試PlayButton是否正常工作" 時發現會報錯說我的GameTitle未定義,但是我把隱藏遊戲標題那行複製到 "void Start()" 卻發現是可以執行的,代表GameTitle是有定義成功的才對,請問這問題要怎麼解呢?
寫得非常非常清楚 謝謝
很高興對你有幫助 ^_^
你好,我已經完成遊戲了,在按撥放鍵測試時也正常,但是輸出後就發生所有物件都不會碰撞的問題(例如:子彈打不到敵人、子彈和敵人到邊界不會消失、飛機撞不到敵人),不知道這是什麼問題?
可能輸出時,選錯Scene了
想問版主為什麼程式碼沒有錯誤,但ˋ是子彈一碰到敵人就顯示Gameover呢?我該怎麼修正?
應該是外星人的程式碼裡,GameOver的位置放錯了
版主您好,我的Application.Loadlevel那邊系統顯示已過時,請摁該怎麼解決
雖然舊指令已過時,但是目前還能用,不用在意
大大您好,請問在敵人碰到button side的時候讓飛機爆炸的話要怎麼寫
要把功能移到GameFunction底下,碰撞時,像AddScore那樣去呼叫那個功能
我是打算寫在bottom side 的funtion裏面,可是貌似行不通,那請問大大的方法是把爆炸的程式移到game function嗎
版主你好,先謝謝你上一次的回應,問題立即解決了,在幾經辛苦終於到了PART4,但我又卡住了哈哈,我多次重新檢視了game function的cs 及 invader的cs 都沒有打錯,但為何我回到unity還是沒有出現ScoreText的放置位? 我深信一定是我弄錯了什麼,但找不出來,希望版主為我指路
嗨版主,我已經解決了上一次的問題了,但現在卡在了最後,為什麼我的遊戲BUILD出後的 UI 都變得比例奇怪了,完全不同?
我在part4的文章中新增了Canvas Scale的設定,應該可以解決這個問題
版主你好,這裡的教學十分有用,但我有幾個地方有問題 第一是我在build的那邊沒有space這個選擇 第二是我寫了一個if 的statement 比如當x=3時,但if(x==1)和if(x==3)同時執行了,我做了很多嘗試比如改數字但也是同步執行了,我能確定那是x=3因為我用的是 public int x,所以在inspector看到他的x是=3,這問題一直解決不了我想不到為什麼會這樣QQ,code的話我放在下一個留言 謝謝版主熱心教導
void Start() { life = 4; onelife.SetActive(false); threelife.SetActive(true); } // Update is called once per frame void Update() { } void OnTriggerEnter2D(Collider2D col) { if (col.tag == "emeny") { life-= 1; Destroy(col.gameObject); } if (life == 3) { threelife.SetActive(false); twolife.SetActive(true); } if (life == 2) { twolife.SetActive(false); onelife.SetActive(true); } if (life == 1) ; { onelife.SetActive(false); } } }
if (life == 1) ; 這邊多了一個 ";"
看見有人未能把ScoreText拉入GameFunction的Script,我也遇上了同樣問題,原來一定要在Background裏的GameFunction在能拉入,不能直接選擇Asset中的GameFunction. 希望我的留言能幫到遇上同樣問題的網友們 :)
ScoreText的問題~ using UnityEngine.UI; 改成: using TMPro; public Text ScoreText; 改成: public TextMeshProUGUI ScoreText;
版主您好,如果我今天想要把戰鬥機改成不是只有上面能發射子彈,而是上下左右都可以發射子彈(戰鬥機也是上下左右都可以移動),請問這樣要怎麼寫??