Unity官方教程 2D UFO(下)

2D UFO 游戲

前言

Unity官方教程 2D UFO(上)中,我們學(xué)會了:

  • 新建一個項目Project
  • 從資源商店下載素材包
  • 新建一個GameObject
  • 給UFO添加剛體組件(Rigidbody 2D)和腳本(Script),讓我們通過方向鍵或者WASD來控制UFO移動

我們會看到一個問題,UFO隨便移動幾步就會從平臺掉下去,看也看不見追也追不著。我們可以給平臺添加一圈圍墻來防止這種情況的產(chǎn)生。那么這一節(jié)我們將學(xué)會以下內(nèi)容:

你將學(xué)會操作什么?

  • 如何制作圍墻防止UFO從平臺掉下去
  • 如何讓攝像機跟隨UFO移動
  • 添加“旋轉(zhuǎn)小馬達(dá)”——金幣
  • 制作預(yù)制件Prefab
  • 實現(xiàn)UFO吃掉金幣
  • 添加計分板和游戲結(jié)束提示
  • 如何發(fā)布游戲到本地

一、添加圍墻防止UFO掉出平臺

代入到現(xiàn)實生活里面,人和圍墻之間會發(fā)生什么使得人不能直接穿越圍墻到外面去?機智的A同學(xué)可能想到了:物理碰撞。Unity里要想擁有類似圍墻的效果,其實可以通過給BackgroundPlayer分別添加碰撞器來實現(xiàn)。

把目光放回到Scene窗口,可以看到Background整個平臺四條邊的格子是特殊顏色和材質(zhì),這個意味著把墻設(shè)置在這4個區(qū)域是比較合適的。那么我們先來添加第一面墻吧!

選中Background,通過Add Component-->Physics 2D-->Box Collider 2D,就可以給平臺添加一個碰撞器組件(墻是方形的所以選擇Box)。

Box Collider 2D

碰撞器默認(rèn)是包裹在Background外圍,在Scene窗口可以看到一圈原諒色在平臺邊緣。把Box Collider 2D組件的Offset內(nèi)的X設(shè)置為-14.26,SizeX改為3.3,可以看到綠色碰撞器區(qū)域變成是在平臺最左側(cè)一列格子,這一面墻就添加好了。

碰撞器設(shè)置

有兩種辦法添加其余三面墻:

  • 新增法:和添加第一面那樣,Add Component-->Physics 2D-->Box Collider 2D
  • 復(fù)制法:在已有的Box Collider 2D組件的右上角小齒輪里選擇Copy Component,然后再點開一次,選擇Paste Components As New
復(fù)制組件

參考數(shù)值:

  • 右:Offset,X為14.26,Y為0;Size,X為3.3,Y為31.64
  • 上:Offset,X為0,Y為14.26;Size,X為31.64,Y為3.3
  • 下:Offset,X為0,Y為-14.26;Size,X為31.64,Y為3.3
四面墻添加完畢

最后一步,給Player添加碰撞器Circle Collider 2D。添加之后雙擊Player可以快速定位到UFO,清晰地看到UFO外面那一圈原諒色。

Circle Collider 2D

修改Circle Collider 2D里面的Radius值可以調(diào)整碰撞區(qū)域,在這里設(shè)置為2.15是比較合適的。
這些都完成之后,運行游戲看看,現(xiàn)在UFO不會再飛出去了吧?(o?▽?)o

二、讓攝像機跟隨UFO移動

有豐富游戲經(jīng)驗的同學(xué)都知道,在游戲里面,主角總是處于畫面中心的,換句話說就是攝像機應(yīng)該是跟隨主角移動,保持主角萬眾矚目狀態(tài)。很好,那怎么樣才能讓攝像機跟隨UFO走起來呢?可能機智的A同學(xué)又想到了:把攝像機變成UFO的小弟(子對象),這樣UFO移動,攝像機也會跟著變化。就聽你一次,來試試看

把攝像機拖動到Player下面變成它的子對象

然后運行游戲看看效果怎么樣:

大家來轉(zhuǎn)圈圈

A同學(xué)????
的確,攝像機是跟隨UFO移動了,但是變動地不止是位置,它的角度也跟隨UFO變化了,所以就會如圖一樣出現(xiàn)天旋地轉(zhuǎn)的情況。我們想要的效果只是想讓攝像機的位置跟隨UFO移動,不需要角度變化。這條路走不通,那么只能通過腳本了。

先把Main Camera從Player移出去,然后給攝像機添加一個腳本CameraController,腳本語言是C Sharp。

添加腳本之后記得先把腳本移動到Scripts文件夾,好習(xí)慣盡早養(yǎng)成。

腳本代碼如下:

CameraController

簡單解讀下代碼含義:

  • 首先定義了一個public的GameObject變量player,這個變量是用來告訴程序,攝像機會跟隨哪個GameObject來移動
  • 然后定義一個private的Vector3變量offset,這個變量用來記錄游戲初始化的時候,攝像機和UFO之間的距離
  • Start方法中,攝像機和UFO的位置差賦值給offset變量,有了這個固定值才能在后續(xù)UFO移動的過程中,UFO和攝像機的距離保持不變
  • 最后在LateUpdate方法中,把攝像機的新位置變更為球體的新位置加上固定的offset偏移位置

保存腳本,回到Unity編輯器頁面,我們會發(fā)現(xiàn)攝像機的腳本組件中,多了一個Player屬性。

Player

這就是剛才我們在腳本內(nèi)定義的public屬性player。

在Unity腳本里,public屬性會在編輯器內(nèi)顯示,需要填充內(nèi)容才可正常運行。

把UFO拖動到Player屬性中,如圖:

Player

運行游戲,現(xiàn)在再撞墻,攝像機也不會翻跟斗了。

拖好的樣子

三、添加“旋轉(zhuǎn)小馬達(dá)”——金幣(Pickup)

萬事俱備,就只差一些金幣讓我們的主角UFO去碰撞和拾取了。為了讓金幣更加耀眼,為了UFO能看見,我們讓金幣可以自動旋轉(zhuǎn)起來。
首先我們把Sprites內(nèi)的Pickup拖到Hierarchy窗口,添加一個新的GameObject——Pickup。把Pickup的Sorting Layer改成Pickups之后,因為UFO的Player層級比較高,他倆都在同一個位置(原點),所以我們看不見新增的金幣。為了方便查看金幣,我們可以暫時把UFO隱藏起來。

隱藏Player

在這里因為Pickup的名字和位置都剛好不需要修改,所以我沒提到雙標(biāo)動作,但是一般添加GameObject之后最好是要改名和重置Transform的。

之后我們給這個金幣添加一個自動旋轉(zhuǎn)的腳本(記得放到Scripts文件夾),腳本名稱為Rotator,腳本內(nèi)容就一句代碼,如下圖:

Rotator

簡單地說,就是調(diào)用transform下的Rotate方法按指定的角度(圍繞Z軸旋轉(zhuǎn)45°)旋轉(zhuǎn)一個物體。

放在Update()函數(shù)中的代碼是以幀來執(zhí)行的,因為我們需要金幣的旋轉(zhuǎn)是以秒來執(zhí)行,所以需要乘以Time.deltaTime增量時間。

保存腳本,運行游戲,可以看到金幣變成“旋轉(zhuǎn)小馬達(dá)”了(??ˇ?ˇ?)~

四、制作預(yù)制件Prefab

為了豐富游戲,我們可以做多個金幣讓UFO拾取。這個可以通過制作預(yù)制件(Prefab)來實現(xiàn)。那什么是Prefab呢?舉個可能不是太貼切的例子,就是我們生活中的樣本,比如某輛車的A系列的模型,根據(jù)這個模型可以生產(chǎn)出很多一模一樣的車輛(金幣)。然后只要修改這個模型的參數(shù),那么這個修改就會作用到所有由該模型生產(chǎn)出來的車輛上。

由上可以總結(jié)出預(yù)制件的好處主要是:

一處修改,全部生效:修改Prefab的屬性之后,所有使用這個Prefab的對象的屬性也會跟著變化。

炒雞方便的好嗎?
制作Prefab的方法也很簡單。不過根據(jù)資源管理原則,我們先做兩件事

  • 在Assets文件夾創(chuàng)建Prefabs文件夾來存放Prefab文件
  • 在Hierarchy窗口下,通過Create-->Create Empty創(chuàng)建一個空的GameObject對象,重命名為Pickups,reset Transform,然后把Pickup拖到Pickups下成為它的子對象。后續(xù)新增的金幣對象都放在其下,好方便管理。
Pickups

Pickup拖到Prefabs文件夾,一個預(yù)制件就做好了??梢钥吹?strong>Pickup這個對象的名字也變成藍(lán)色了。

制作Prefab
做好的Prefab

接下來有2個辦法可以通過預(yù)制件制作其他金幣。

  • 選中Pickup對象,按CTRL+D可以復(fù)制出一個金幣對象,按多少次就復(fù)制多少個(推薦這個方法)
  • 把Prefabs文件夾里面的Pickup預(yù)制件拖到Pickups下就可以生成一個金幣對象

在Scene窗口,鼠標(biāo)左鍵拖動這些金幣可以把它們隨意放到自己覺得合適的地方。

金幣群

我一共放了13個金幣,中間位置留給UFO,同學(xué)可以把UFO顯示出來了~

五、UFO拾取金幣

接下來要實現(xiàn)UFO碰到金幣的時候就拾取這個功能。關(guān)鍵詞是“碰到”、“拾取”,那么它們分別意味著什么?

  • 碰到,也就是碰撞檢測(兩者都存在碰撞組件才能進(jìn)行檢測)
  • 拾取,UFO發(fā)現(xiàn)自己碰撞的是金幣而不是墻的時候,讓金幣消失或者不顯示就可以了。

很好,理清了思路,接下來就來看看怎么實現(xiàn)吧。

第1步:金幣Pickup添加碰撞器

選中Pickups下的任意一個對象比如Pickup,通過Add Component-->Physics 2D-->Circle Collider 2D添加好碰撞器,然后雙擊Pickup定位放大,可以很清楚地看到金幣周圍的一圈綠色。

Pickup的碰撞器區(qū)域

放大的情況下好調(diào)整碰撞器區(qū)域大小。在這里把Radius值設(shè)置為0.93是比較合理的,如果有強迫癥的同學(xué)可以調(diào)整Offset值來調(diào)整中心點。

合身的綠衣服

這樣就給一個金幣添加好了碰撞器了,可是我們還有12個金幣也需要添加碰撞器怎么辦?在這個添加好碰撞器的金幣對象的Inspector窗口右上角有一個Apply按鈕,點一下就可以把這個金幣的設(shè)置同步到其他金幣和預(yù)制件了。

Apply很方便,這就是預(yù)制件的好處,容易管理

第2步:編寫腳本實現(xiàn)拾取功能

通過查官方API手冊我們可以查到有個名為OnTriggerEnter的方法可以在UFO碰到金幣的時候調(diào)用。另外前面也提到了,UFO是要判斷碰撞到的東西的,因為不能什么東西都拾取,所以需要給拾取的金幣添加一個標(biāo)記(Tag)。
添加Tag的方法:

  • 一共13個金幣,每個金幣都添加是很麻煩的事情,這時候可以直接修改預(yù)制件Prefab就可以全部生效了。
  • 選中Prefabs內(nèi)的Pickup,然后在Inspector的Tag里面選Add Tag,命名為PickUp(如果列表有PickUp那就無需再加了)
Add Tag
點加號輸入新Tag名
  • 然后將預(yù)制件Pickup的Tag設(shè)置為“PickUp
Tag設(shè)置為“PickUp”

接下來就是編寫腳本來實現(xiàn)拾取功能。打開UFO的PlayerController腳本,新增以下代碼:

拾取代碼
  • OnTriggerEnter方法是檢測物理發(fā)生碰撞的時候調(diào)用執(zhí)行里面的代碼,參數(shù)other變量表示UFO碰到的其他2D碰撞器
  • 先調(diào)用CompareTag方法判斷碰到的這個對象是否被標(biāo)記了Tag"PickUp",如果是的話則調(diào)用SetActive把這個對象設(shè)置為未激活狀態(tài)(不顯示),也就是false。

編寫完畢,保存腳本,回到Unity編輯器頁面,運行游戲看看。

......機智的A同學(xué)大喊:哈哈哈哈,還是碰撞了,并沒撿起來!

(尷尬.jpg)這是因為,我們沒有把金幣設(shè)置成碰撞觸發(fā)器(Is Trigger)。把金幣設(shè)置成觸發(fā)器之后,在碰撞的時候才會執(zhí)行腳本里面的OnTriggerEnter等方法。在預(yù)制件上勾選之后,再運行游戲,現(xiàn)在可以正常拾取金幣了。

Is Trigger

第3步:優(yōu)化性能

現(xiàn)在看起來一切正常,好像并沒有什么問題。但,實際上真的如此么?

  • 在Unity的物理引擎中,靜態(tài)的碰撞體(沒有剛體)會被單獨進(jìn)行運算并保存在緩存中,節(jié)約計算資源優(yōu)化性能。
  • 所以如果我們移動或者旋轉(zhuǎn)一個不帶剛體的碰撞體(金幣)的話,這個緩存會被重新計算生成,這會耗費一定的資源。
  • 所以我們最好給金幣添加上剛體(變成動態(tài)碰撞體),那么它的旋轉(zhuǎn)不會導(dǎo)致緩存在每一幀都被刷新,一定程度上可以達(dá)到節(jié)約資源的目的。

那好,我們給Prefab Pickup 加上Rigidbody 2D,然后運行游戲試試。

給金幣預(yù)制件添加剛體

就像天上掉下很多金色餃子一樣,金幣都受到了重力掉下來了。的確可以和之前UFO一樣,把Rigidbody 2D的Gravity Scale改成0就不會掉下來,但這只能解決部分問題。我們希望的是金幣不僅僅不受重力影響,也不受其他物理作用力的影響。而這可以通過修改Rigidbody 2D組件的Body TypeKinematic來實現(xiàn)。

Kinematic

Kinematic:開啟運動學(xué),開啟后不再受力的影響,只能通過Transform屬性來操作。

六、添加計分板和結(jié)束提示

第1步:添加計分板

游戲完成了基本玩法了,但是我們還需要做一個計分板來鼓勵玩家多多拾取金塊。關(guān)鍵詞,“分”和“計分板”,也就是說我們需要做兩個事情:

  • 定義一個變量來保存玩家的分?jǐn)?shù)(撿取的金幣數(shù)量)
  • 把這個分?jǐn)?shù)顯示在UI上

那么我們來修改下PlayerController腳本,內(nèi)容如下:

分?jǐn)?shù)count

三行代碼:定義一個變量count用來保存分?jǐn)?shù),在Start方法里count值初始化為0,最后拾取金幣的時候,count數(shù)量+1。

count++是一種簡寫,效果等同于 count +=1,也等同于count = count +1

分?jǐn)?shù)有了,還需要一個UI展示給玩家。保存腳本,回到Unity編輯器,創(chuàng)建一個UI Text。

UI Text

改名為Count Text,重置下Transform,雙擊Count Text定位放大,鼠標(biāo)左鍵把它拖到合適的位置,比如屏幕左上角。

Count Text

Inspector的Text組件內(nèi)的屬性可以修改UI的展現(xiàn)。Text是默認(rèn)文字內(nèi)容,F(xiàn)ont Size是字體大小,Color是字體顏色,可以自己試著修改。

接下來再次修改PlayerController

計分板UI代碼
  • 最上面的命名空間,我們需要引入UnityEngine.UI,這樣后面代碼才會識別Text類型的變量
  • 定義countText變量來保存UI Count Text
  • 接著我們在Start方法中調(diào)用setCountText方法,來更新countText的內(nèi)容
  • 然后我們在每次UFO拾取金幣的時候,也更新countText的內(nèi)容
  • 最后是我們定義的setCountText方法,里面調(diào)用的ToString方法是讓int類型的count轉(zhuǎn)換成字符串

保存腳本,回到Unity,把Count Text UI 拖入到Player里面的Count Text屬性框里面。

計分板

做完這些運行游戲看看效果!

第2步:添加游戲結(jié)束提示

為了讓游戲更加友好,在玩家拾取完畢所有金幣之后,應(yīng)該提示玩家通關(guān)了。首先我們也需要先創(chuàng)建一個文本UI(Win Text),字體18號,黃色,位置在UFO上方,這應(yīng)該是個不錯的選擇。

Win Text

回到PlayerController添加代碼:

Win Text代碼
  • 定義winText變量來保存UI Win Text
  • 接著我們在Start方法中初始化winText為空字符串,因為游戲開始的時候這個內(nèi)容是不顯示的
  • 最后我們在setCountText方法里面,判斷當(dāng)分?jǐn)?shù)大于等于13的時候,就更新winText的內(nèi)容為“You win !”

這個13是因為我的金幣數(shù)量最多是13,同學(xué)可以根據(jù)自己的金幣數(shù)量來修改這個數(shù)字。

保存腳本,回到Unity,把Win Text UI 拖入到Player里面的Win Text屬性框里面,再運行游戲就可以看到效果了。

七、本地發(fā)布游戲

游戲制作完畢,可以發(fā)布游戲到本地了。呼(?>?<)☆不容易啊,不過最后一步最簡單......保存場景,通過菜單欄File-->Build Settings打開發(fā)布頁面。

Build Settings
  • Platform選擇第一項,PC,Mac&Linux Standalone
  • 點擊Add Open Scenes按鈕,把當(dāng)前場景添加進(jìn)去并且勾選
  • 點擊Build按鈕,選擇存放路徑,就可以完成發(fā)布了
    找到保存路徑下的exe文件雙擊運行就可以開始撿錢了!ヾ(?°?°?)??
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容