從零開(kāi)始獨(dú)立游戲開(kāi)發(fā)學(xué)習(xí)筆記(二十一)Unity學(xué)習(xí)筆記(九)M_Studio教程2D入門 二

繼續(xù)小狐貍,這個(gè)教程挺有趣的。
1. 動(dòng)畫
在 asset panel 里新建一個(gè) Animation 文件夾用于儲(chǔ)存之后的動(dòng)畫。
給小狐貍添加一個(gè) Animator 組件
在文件夾里新建一個(gè) Animation Conroller,拖動(dòng)到小狐貍的組件里。
打開(kāi) window -> Animation -> Animation 窗口。
1.1 創(chuàng)建閑置動(dòng)畫
選中小狐貍的情況下,在 Animation 窗口里,可以看到提示說(shuō)沒(méi)有 Animation Clip,附一個(gè) create 按鈕,點(diǎn)擊后會(huì)打開(kāi)資源管理器,給我們的動(dòng)畫命名,我們先要?jiǎng)?chuàng)建一個(gè)閑置動(dòng)畫,于是命名為 idle。
找到動(dòng)畫素材,全選,一起拖動(dòng)到 timeline 上,動(dòng)畫就已經(jīng)附上了,不過(guò)現(xiàn)在有一個(gè)問(wèn)題,動(dòng)畫太快了。
方式很簡(jiǎn)單,拖動(dòng)它就可以調(diào)整動(dòng)畫快慢。
1.2 創(chuàng)建跑動(dòng)動(dòng)畫
打開(kāi) window -> Animation -> Animator,選中 player,或者直接雙擊上一步創(chuàng)建的 controller,便可以看到剛剛創(chuàng)建的動(dòng)畫。(第一種方式就不用特意換文件夾去找 controller 了)
回到 Animation 窗口,創(chuàng)建一個(gè)新的 Animation Clip,命名為 run,剩下的操作和上一步一樣。
創(chuàng)建完后去到 controller 看會(huì)發(fā)現(xiàn)兩個(gè)動(dòng)畫都有了,只不過(guò) run 動(dòng)畫沒(méi)有連上來(lái)。
在 controller 里右鍵 idle,選擇 make transition,拖到 run,反之亦然。
左邊添加一個(gè) bool 參數(shù) IsRunning。
將兩個(gè) transition 的 has exit time 取消勾選,并將 transition duration 設(shè)置為 0。
對(duì)兩個(gè) transition 設(shè)置 condition,表示什么時(shí)候觸發(fā) transition,這里自然是設(shè)置成 IsRunning 是否為真。

接下來(lái)就是要在腳本里改變這個(gè)參數(shù)從而改變動(dòng)畫狀態(tài)了。
還是之前那個(gè)腳本,方法很簡(jiǎn)單,直接暴露一個(gè)參數(shù)把 Animator 往里拖就行了。然后使用 SetBool 來(lái)更改參數(shù)值,注意這里沒(méi)法直接用 . 語(yǔ)法獲取。

1.3 創(chuàng)建跳躍動(dòng)畫
跳躍動(dòng)畫有點(diǎn)不一樣,因?yàn)榉痔饋?lái)和落下兩個(gè),所以要?jiǎng)?chuàng)建兩個(gè)動(dòng)畫。
創(chuàng)建動(dòng)畫邏輯。通過(guò)參數(shù)的更改,進(jìn)行動(dòng)畫的切換。
給代碼里加上兩個(gè) public 屬性,類型分別為 Collider2D 和 LayerMask。給后者命名為 ground,之后我們要把 tilemap 的 layer 設(shè)置為 Ground。用于檢測(cè)碰撞。(這里可以學(xué)到,如果是死板的把 tilemap 本身作為參數(shù)引入,那么之后需要添加其他的地面就不好辦了,用 layer 的話新加的東西只要改變 layer 即可)
代碼中判斷跳躍和下落以及碰撞時(shí)機(jī),更改 animator 的參數(shù)。

2. 修復(fù)移動(dòng)錯(cuò)誤以及一些優(yōu)化
如果是跟著教程做到現(xiàn)在的話,肯定早就發(fā)現(xiàn)一堆 bug。
2.1 走著走著突然卡住
主要是我們現(xiàn)在用的 collider 非常簡(jiǎn)單,player 只是一個(gè)方塊。而移動(dòng)的時(shí)候,方塊的兩個(gè)角可能會(huì)跟地面卡住,由于我們之前設(shè)置了 z 軸不滾動(dòng),因此表現(xiàn)為卡住,如果讓 z 軸滾動(dòng)恢復(fù),其實(shí)會(huì)發(fā)現(xiàn)之前會(huì)卡住的時(shí)候變成了人物亂滾。
這個(gè)問(wèn)題會(huì)在之后游戲完成度高的時(shí)候被解決掉,不過(guò)現(xiàn)在可以先調(diào)整一下:
首先把之前的 box collider 縮小到頭部位置。
再添加一個(gè) circle collider,作為下半身的 collider,這樣我們就有了兩個(gè) collider。下半身因?yàn)槭菆A形的,也不會(huì)被絆倒了。
把下落碰撞的物體改成這個(gè)圓形 collider,結(jié)束。
這兩個(gè) collider 會(huì)在后面起到別的重要作用,這個(gè)就等到時(shí)候再講了。
2.2 沒(méi)必要作為 public 的參數(shù)
我們現(xiàn)在的腳本里引用組件的方式是 public 出來(lái)然后拖拽。如果像是 collider 這種可能有多個(gè)并且會(huì)更改的組件還好。像是 rigidbody,animator 這種只會(huì)有一個(gè)的組件且之后不會(huì)再更改肯定是這個(gè)組件。沒(méi)必要專門 public 出來(lái)占地方。我們可以直接在腳本內(nèi)部引用,且不聲明為 public 屬性。

3. 鏡頭跟蹤
3.1 腳本跟蹤
想讓鏡頭跟蹤小狐貍,本來(lái)想直接父子物體關(guān)系的,結(jié)果發(fā)現(xiàn)每次人物轉(zhuǎn)向的時(shí)候鏡頭也會(huì)轉(zhuǎn)向。這是因?yàn)槲覀兏淖內(nèi)宋锍虻臅r(shí)候改變了 scale,而父子物體的話鏡頭也會(huì)遵循這個(gè)改變。所以想要達(dá)到目的我們還是得用腳本。
這次我們的腳本是加在鏡頭上的。
代碼如下:

可以發(fā)現(xiàn)并不是單純的讓兩個(gè) position 相等,有這么幾個(gè)原因:
我們不想讓 y 軸跟著人物移動(dòng),不然鏡頭會(huì)看到場(chǎng)景上下方的空白。
z 軸設(shè)置和人物一樣的話就看不見(jiàn)人物了,這是很合理的,camera 要是和人物重合了肯定是看不見(jiàn)人物的。
3.2 cinimachine
unity 也提供了這么一個(gè)工具,比我們的腳本更好用。首先要在 package manager 里安裝這個(gè)包。按抓個(gè)完后在 gameobject -> cinimachine 里可以找到我們的工具。這里我們點(diǎn)擊創(chuàng)建一個(gè) 2D Camrea。
然后會(huì)發(fā)現(xiàn) main camera 會(huì)被這個(gè)改寫,之前寫的跟隨腳本已經(jīng)沒(méi)有效果了。這時(shí)候我們只要調(diào)整新添加的這個(gè) camera 即可。
將 player 拖動(dòng)到 follow 屬性里。游玩一下游戲會(huì)發(fā)現(xiàn)此時(shí)鏡頭跟隨就已經(jīng)有了,而且會(huì)有一點(diǎn)緩沖,效果非常好。
點(diǎn)開(kāi) body 屬性,會(huì)發(fā)現(xiàn) game panel 出現(xiàn)一些紫色藍(lán)色的提示框,有利于我們調(diào)參。
嘗試增大 dead zone x 和 y,會(huì)拉出一個(gè)小框框。人物在這個(gè)框里移動(dòng)的時(shí)候鏡頭是不會(huì)變化的,只有當(dāng)移動(dòng)出這個(gè)框的范圍時(shí),鏡頭才會(huì)跟著移動(dòng)。人物判定點(diǎn)就是那個(gè)小黃點(diǎn)。
改變 screen x 和 y,可以調(diào)整人物在鏡頭中的位置,比如有些游戲人物不一定固定在中間,而是最左邊。
3.3 背景加長(zhǎng)
可以讓背景跟隨鏡頭移動(dòng),但是如果背景不移動(dòng)的話很出戲。所以這里我們復(fù)制背景手動(dòng)加長(zhǎng)。這時(shí)左邊 hierachy pannel 里的東西有點(diǎn)多,我們可以整理一下。新建一個(gè) empty object,重命名一下,然后把剛剛復(fù)制的物體拖進(jìn)來(lái)即可。

3.4 邊界處理
背景加長(zhǎng)了,但是邊界處理也是很重要的。比如說(shuō)人物走到左邊和右邊的末端的時(shí)候,鏡頭就不應(yīng)該像之前那樣跟隨了,不然會(huì)看到空白。跳躍同理,往上跳的時(shí)候鏡頭可以跟隨一下,但是任務(wù)要是太靠近天空,鏡頭就應(yīng)該停止往上了。
解決這個(gè)的方案 unity 也提供了,在剛剛創(chuàng)建的 2D camera 里有一個(gè) extension,這里添加一個(gè) CinemachineConfiner2D(教程里用的是 CinemachineConfiner 再選 2D mode,我用的是新版本新增的功能,官方更推薦)
想讓其工作需要一個(gè) collider,于是我們給 background 添加一個(gè) polygon collider,手動(dòng) edit 一下邊界。(2021 版本刪除操作的單位是線不是點(diǎn),想要?jiǎng)h除某條線的時(shí)候,按住 ctrl,鼠標(biāo)移動(dòng)到上面的時(shí)候線會(huì)變紅,這時(shí)候點(diǎn)一下線就會(huì)被刪除)。
編輯的時(shí)候應(yīng)該會(huì)發(fā)現(xiàn)人物會(huì)被邊界擠壓出去,這個(gè)時(shí)候我們只要選中 isTrigger 即可。因?yàn)檫@個(gè) collider 不是用來(lái)做碰撞的,只是用于被 cinemacchine 利用。
然后回到 cinemachine,把 confiner 連上這個(gè) collider。運(yùn)行游戲,一切完美。
