前言
Unity官方教程 2D Roguelike 英文原版視頻教程地址 ——> 傳送門
由于官方視頻使用的Unity版本較老,部分方法已經不再使用窍霞,本文已經采用較新的Unity版本和對應的替代方法熊痴。另外為了更方便理解踢俄,文章講述的順序和官方視頻會有少許出入(結果是一致的)。
電腦環(huán)境:Windows10
Unity版本:2017.2.0f3
腳本/代碼編輯器:MonoDevelop 5.9.6
目標游戲理解
在開始一個項目之前层扶,需要清楚即將要制作的是什么樣的一個游戲箫章,這樣才能更容易地理解官方代碼。簡單來說镜会,2D Roguelike 是一個基于回合和瓷磚的地牢探險類游戲檬寂,玩家控制大胡子(角色)移動,進行拾取食物戳表、躲避敵人等操作以便更好地通關進入下一個關卡桶至,直到耗盡生命游戲結束。它具備以下內容:
- 每次嘗試移動(比如鍵盤按一次方向鍵)都會扣除生命匾旭。
- 拾取食物可以恢復定量生命镣屹。
- 可以攻擊打碎障礙墻從而開辟路線。
- 大胡子需要避開怪物价涝,以免被攻擊減少生命女蜈。
- 越后面的關卡,怪物數(shù)量越多色瘩。
一個規(guī)則比較簡單的2D游戲伪窖,OK,摩拳擦掌居兆,開始吧覆山!?(???)?
本節(jié)你將學會什么?
- 如何給GameObject添加動畫Animation
- 如何重寫動畫控制器
- 對Tag/Layer/Sorting Layer有基本的了解
一泥栖、新建一個項目Project
如何創(chuàng)建項目不再贅述簇宽,有需要的朋友可以查看Unity官方教程 2D UFO(上)的內容了解一下勋篓。本次新項目的名稱為2D Roguelike(可自定義),記得是選2D晦毙!
二生巡、在Asset Store中下載素材
Ctrl+9(或菜單Window->Asset Store)打開Asset Store商店,在最上方搜索欄輸入我們想要查找的游戲資源名稱见妒。本例是2D Roguelike,回車之后第一個結果就是我們想要的甸陌。
點擊該資源须揣,在頁面找到Download按鈕,下載完成之后即可導入Import钱豁。(已下載過了就只有Import按鈕)
點擊Import之后耻卡,會彈出導入資源列表選項。在這里一定要確保所有資源都勾選了(默認情況下是全部勾選)牲尺,保險起見也可以點擊All按鈕選中全部資源卵酪,然后便可以點擊Import按鈕來進行導入操作了。
導入成功之后谤碳,我們可以看到在Project窗口的Assets文件夾下多出了很多資源文件溃卡。
Audio:存放音樂、音效文件
Fonts:存放字體文件
Sprites:存放精靈圖
刪除2個無用的文件夾_Complete-Game蜒简、TutorialInfo瘸羡,新增以下四個資源文件夾。
- Animations 包含AnimationControllers和Animations文件夾搓茬,分別存放動畫管理器和動畫
- Prefabs 存放預制件文件
- Scenes 存放場景文件
- Scripts 存放腳本文件
合理分類資源文件犹赖,以便查找和管理,是個非常必要的好習慣卷仑。
三峻村、保存場景
在保存場景之前先調整下Unity編輯器的窗口布局,根據(jù)游戲界面和自己的工作習慣锡凝。編輯器右上角的Layout按鈕點擊打開進行選擇即可改變布局粘昨,在這里我們推薦選擇Default布局,也是官方推薦使用的私爷。
保存場景的方法在之前Unity官方教程 2D UFO(上)有提到雾棺,不再贅述。場景保存在Scenes文件夾衬浑,名字依舊是Main捌浩。
四、創(chuàng)建角色動畫和預制件
大胡子有三種動畫狀態(tài)需要添加:空閑idle工秩、劈砍chop尸饺、受擊hit进统。默認情況下大胡子處于idle狀態(tài),當大胡子擊打障礙墻的時候需要切換到chop狀態(tài)浪听,被怪物攻擊的時候播放hit動畫螟碎。為了讓大胡子動起來,并且和其他對象進行互動比如碰撞迹栓,還需要給大胡子添加剛體和碰撞器掉分。
第1步:大胡子添加idle動畫(空閑)
通過菜單GameObject->Create Empty(快捷鍵Ctrl+Shift+N)添加一個空白游戲對象,重置Transform克伊,命名為Player酥郭。
創(chuàng)建游戲對象之后,良好的習慣是先重置Transform和改名愿吹。
打開Sprites文件夾不从,點擊里面精靈圖的右側小三角打開圖片集,同時選中前六張犁跪,鼠標左鍵拖著它們移動到Player再松開椿息。
這時候會彈出存放動畫的窗口,默認是Sprites文件夾坷衍,我們改一下寝优,把它保存在之前已經創(chuàng)建好的文件夾Animations下的子文件夾Animations內,命名為PlayerIdle惫叛。
我們可以看到倡勇,Animations文件夾下自動生成了一個動畫控制器Player,它控制大胡子當前播放哪個動畫嘉涌。把它拖到AnimationControllers文件夾妻熊,這里專門存放動畫管理器文件。
與此同時仑最,因為Player添加了第一個動畫扔役,所以自動增加了兩個組件。Sprite Renderer警医,精靈渲染器亿胸,管理圖像的顯示;Animator预皇,控制是否播放動畫侈玄。
第一個動畫添加好了,讓我們運行游戲測試一下吧吟温!
有點擔心序仙,大胡子一副抽搐的樣子,給人下一秒就要暈厥倒下的感覺 (鲁豪;′д`)ゞ潘悼。
好吧不開玩笑律秃,其實這是由于動畫播放速度較快導致的。打開AnimationControllers文件夾治唤,雙擊Player棒动,打開Animator窗口。
選中PlayerIdle狀態(tài)宾添,在右側的Inspector窗口中修改Speed選項為0.5船惨。這時候再運行游戲,就可以看到大胡子已經平靜下來了缕陕。不錯的開端掷漱!
第2步:大胡子添加chop、hit動畫
添加chop和hit動畫的操作其實是和添加idle動畫一樣的榄檬,只不過選擇的圖片不同。(不需要改這兩個動畫的速度?(?????)?)
chop動畫保存命名為PlayerChop衔统,Hit動畫保存命名為PlayerHit。
我們會發(fā)現(xiàn),添加后面2個動畫的時候周荐,并不會再新增動畫控制器形用,而是在動畫控制器內添加了兩種動畫狀態(tài)。
在后續(xù)的內容會提到如何在這三種動畫狀態(tài)中進行切換险掀。
第3步:大胡子添加剛體和碰撞器組件
剛體能讓大胡子受物理引擎控制沪袭,實現(xiàn)真實的物理表現(xiàn)效果比如移動。而沒有碰撞器組件的話樟氢,兩個物體之間也無法檢測碰撞冈绊。
在Player的Inspector窗口點擊最下方的Add Component按鈕,搜索Rigidbody 2D添加埠啃。
繼續(xù)搜索Box Collider 2D添加碰撞器組件死宣。
為了避免在相鄰空間進行碰撞,我們把大胡子的碰撞尺寸縮小成0.9碴开。
第4步:制作Player預制件
關于為什么要制作預制件毅该,之前在Unity官方教程 2D UFO(下)有詳細說明,這里就不再細說了潦牛。
在制作Prefab之前眶掌,我們還需要對Player配置3個地方。
- Tag:選擇Player巴碗。tag是Unity引擎里面的標簽朴爬,一般用來對單一的GameObject進行標識。(對良价,有“Player”這個tag的GameObject就是大胡子沒錯了G夼埂)
- Layer:選擇BlockingLayer蒿叠。Layer就在Tag的右側,是Unity引擎里面的層蚣常,作用和tag很相似也是對GameObject進行標識市咽。但是他們的不同在于Layer常用于一組的GameObject,而Tag是單個抵蚊。
3.Sorting Layer:選擇Units施绎。不知道大家思考過沒有,當多個圖片資源比如大胡子贞绳、食物谷醉、墻壁都在同一個坐標的時候,我們會看到什么冈闭?是大胡子在最上面覆蓋了其他俱尼,還是食物,抑或墻壁萎攒?是什么控制了它們的渲染層級順序遇八?這其中的奧義就是Sorting Layer了!越上方的渲染層級越低耍休,比如floor層就相當于背景刃永,Units層級最高,優(yōu)先看到的是Units層的圖片羊精,在此例中斯够,大胡子和怪物都是Units層。
配置完畢喧锦,我們先運行游戲確保沒問題再制作Prefab吧读规!
啊咧?裸违!!!!∑(?Д?ノ) 大胡子直直地掉下來了掖桦!
前面提過,剛體可以讓物體受物理引擎作用供汛,所以不難判斷出這是大胡子受到重力影響所以掉下來了枪汪。由于我們后續(xù)是通過變化大胡子的transform的位置來進行移動,并不依賴任何物理作用力怔昨,所以我們可以通過修改Body Type為Kinematic來解決這個問題雀久。
Kinematic:開啟運動學,開啟后不再受力的影響趁舀,只能通過Transform屬性來操作赖捌。
運行游戲,沒問題了吧?(????)?"""把Player往下拖到Prefabs文件夾即可生成預制件越庇。
五罩锐、創(chuàng)建怪物動畫和預制件
創(chuàng)建怪物的動畫和預制件的流程和角色是差不多的,只不過資源不一樣卤唉。怪物只有兩種動畫:空閑idle涩惑、攻擊attack。默認情況下怪物處于idle狀態(tài)桑驱,當大胡子在隔壁格子并且輪到怪物回合的時候它會觸發(fā)攻擊操作播放attack動畫竭恬。當然,怪物也有移動和碰撞熬的,所以同樣需要添加剛體和碰撞器痊硕。
第1步:怪物1添加idle、attack動畫
刪除Hierarchy窗口下的Player押框,通過菜單GameObject->Create Empty(快捷鍵Ctrl+Shift+N)添加一個空白游戲對象岔绸,重置Transform,命名為Enemy1橡伞。
找到第一只怪物的idle動畫幀圖片亭螟,拖到Enemy1游戲對象上。
依然是保存在Animations下的子文件夾Animations內骑歹,命名為Enemy1Idle。把生成的Enemy1控制器轉移到AnimationControllers文件夾墨微。
對資源進行合理分類保存是非常重要的習慣道媚。
運行游戲看看添加是否正常。
動畫正常播放翘县,速度也可以最域。OK,接下來就是找到怪物1的攻擊動畫幀圖片锈麸,和前面一樣添加到Enemy1身上镀脂,保存為Enemy1Attack。
第2步:怪物1添加Rigidbody 2D和Box Collider 2D
怪物和角色一樣忘伞,都會在關卡內走來走去薄翅,并且和其他元素(外墻、障礙墻氓奈、角色)均會發(fā)生碰撞翘魄。而這些都需要剛體和碰撞器的組件支持。添加這兩個組件的方法在上面已經介紹舀奶,在這里只提一下暑竟,Box Collider 2D的Size選項均是1,Rigidbody 2D的Body Type選項為Kinematic育勺。
第3步:制作怪物1的預制件
在制作預制件之前但荤,記得把Inspector窗口下的tag選擇Enemy罗岖,Sorting Layer選擇Units,Layer選擇BlockingLayer腹躁。
Layer桑包,角色、怪物潜慎、外墻捡多、障礙墻都會標識為BlockingLayer,這是因為此例中檢測碰撞的方法是使用射線檢測(后面腳本會寫這方面內容)铐炫,射線判斷前方空間是否存在攜帶這個標識的碰撞體并且返回結果垒手。(BlockingLayer是之前導入資源的時候預設好的,朋友們也可以自己添加新的Layer倒信,然后在這一層檢測碰撞)
最后科贬,左鍵按住Enemy1不動往下拖到Prefabs文件夾,即可生成Enemy1預制件了鳖悠。
第4步:怪物2重寫動畫控制器
通過上面的操作榜掌,我們學到了給GameObject添加動畫的一種方法,而接下來會接觸到另外一個知識點:重寫動畫控制器乘综。
由于怪物1和怪物2除了樣子(圖片資源)不同憎账,其他機制均是一樣。為了節(jié)省時間卡辰,我們把Enemy1游戲對象的名字修改成Enemy2胞皱。
然后和之前一樣,分別制作Enemy2Idle和Enemy2Attack動畫九妈。
這時候打開AnimationControllers文件夾反砌,雙擊Enemy1控制器打開動畫狀態(tài)機Animator,會看到四種動畫都已經作為狀態(tài)添加在里面萌朱。
由于還是原來的GameObject宴树,只是修改了名字,所以并沒有生成另外的動畫控制器晶疼。
動畫狀態(tài)機Animator的功能是在不同的動畫狀態(tài)里添加轉換邏輯酒贬,比如idle和attack之間是怎么轉換,什么樣的條件下會進行轉換翠霍,過度耗時是多少秒等等同衣。對于怪物1和怪物2來說,它們都擁有同樣的狀態(tài)和邏輯壶运,區(qū)別僅僅是美術資源不同而已耐齐。那有什么辦法可以節(jié)省人工,使用同一個動畫狀態(tài)機和同一個腳本控制,但是又可以播放不同的動畫埠况?機智的Unity提供了一個辦法:動畫重寫控制器耸携。讓我們來看看是怎么實現(xiàn)的。
首先把Enemy1的Animator里的Enemy2Idle辕翰、Enemy2Attack狀態(tài)刪除夺衍。選中它們,右鍵菜單選中Delete確認刪除喜命。
在AnimationControllers文件夾內空白處右鍵沟沙,依次選擇Create->Animator Override Controller,創(chuàng)建了一個動畫重寫控制器壁榕,我們命名為Enemy2矛紫。
可以看到這個重寫控制器右側Inspector窗口內有個Controller選項,可以選擇繼承哪個動畫控制器牌里。在這里颊咬,我們可以把Enemy1直接拖入到輸入框,或者點擊輸入框右側的小圓圈選擇Enemy1牡辽。
繼承Enemy1的動畫控制器后喳篇,還需要把美術資源也替換掉。Enemy1Attack改寫成Enemy2Attack态辛,Enemy1Idle改寫成Enemy2Idle麸澜,這樣重寫控制器就配置好了。
這時候奏黑,怪物2的Animator組件使用的控制器還是Enemy1痰憎。選擇Enemy2游戲對象,在Animator組件的Controller選項點擊右側小圓圈攀涵,在彈出的窗口中選擇Enemy2即可。
這時候運行游戲洽沟,可以看到怪物2的動畫正常以故。
通過這樣重寫控制器,以后在怪物1的動畫控制器添加邏輯的時候裆操,怪物2自動繼承怒详,不需要再額外給怪物2添加一樣的邏輯。我們這個項目才2個小怪踪区,如果怪物類型或者動畫類型再多一點昆烁,重寫控制器就非常有必要。而且修改起來也只需要改一個地方即可缎岗,非常方便静尼。其實個人覺得和Prefab預制件有點相似。
由于動畫狀態(tài)的轉換邏輯和后面的移動碰撞內容有關聯(lián),我們會放到后面講到角色怪物腳本的時候再添加鼠渺。
把Enemy2游戲對象往下一拖鸭巴,怪物2的預制件也做好啦!
六拦盹、制作素材的預制件
回到文章最開頭看游戲動畫鹃祖,我們可以看到游戲的每個關卡除了大胡子和怪物,還包含6個元素:地板floor普舆、外墻outerWall恬口、障礙墻/內墻wall、食物food沼侣、蘇打水soda祖能、離開exit。所以我們接下來把這些資源預制件都做出來华临,便于后面生成關卡的時候使用芯杀。
第1步:Floor
柿子先挑軟的捏!作為構成關卡地板的floor是最簡單的了雅潭,又不碰撞又不和其他元素互動揭厚。首先我們把上集殘留的Enemy2刪掉,再新建GameObject扶供,改名為Floor1筛圆。(為了每次隨機生成關卡的時候顯示沒那么單調,地磚一共8個樣式)
創(chuàng)建新的GameObject的時候椿浓,重置transform和改名兩個操作可以避免一些異常問題產生太援。
給Floor1添加組件Sprite Renderer,精靈渲染器扳碍,可以控制圖像的顯示提岔。
組件的Sprite選項,點擊小圓圈在彈出的面板內選擇文件名末尾數(shù)字是32的瓷磚圖片笋敞。
前面提過渲染層級里面碱蒙,地板是最底層的,因此我們把Sorting Layer設置為Floor夯巷。
把Floor1拖到Prafabs文件夾赛惩,第一張地板預制件就做好了。
按照以上流程趁餐,我們把其他Floor預制件都做好喷兼。Floor2-8(直接改名,不需要創(chuàng)建新的空白對象)后雷,選Sprite(33-39)季惯,往下一拖即可吠各。
第2步:Exit
Exit的作用是,大胡子移動到這個格子的時候會進入下一個關卡星瘾。
把Floor8更名為Exit走孽,Sprite換成20號。
要判斷角色是否移動到這里琳状,需要添加一個Box Collider 2D來檢測碰撞磕瓷。但我們并非真的想阻止角色移動到這里,只是想知道角色是否到了這個格子念逞,所以需要把Is Trigger選項選中困食。
Is Trigger,觸發(fā)器翎承,選中之后就沒有碰撞效果硕盹,但可以在腳本代碼里使用OnTriggerEnter等方法執(zhí)行檢測到碰撞之后的操作。
為了讓大胡子識別碰撞到的是Exit叨咖,需要把Tag設置成Exit瘩例。Exit的圖片渲染層級比地板高,但是又比角色低甸各,所以Sorting Layer選擇Items垛贤。把Exit拖到Prafabs文件夾,Exit預制件完成趣倾。
第3步:Food
角色移動到Food格的時候聘惦,F(xiàn)ood消失,同時角色增加一定數(shù)量的生命儒恋。因此Food和Exit一樣需要添加Box Collider 2D來檢測碰撞善绎,而且也是激活觸發(fā)器Is Trigger。渲染層級是Items,Tag是Food诫尽。
所以很簡單禀酱,把Exit更名成Food,Sprite Renderer的Sprite更換成19號圖牧嫉,Tag改成Food剂跟,往下一拖,F(xiàn)ood預制件就做好了驹止。
第4步:Soda
Soda作用同F(xiàn)ood,差別在于增加的生命數(shù)值可以不同观蜗。把Food更名成Soda臊恋,Sprite Renderer的Sprite更換成18號圖,Tag改成Soda墓捻,往下一拖抖仅。
第5步:OuterWall
關卡最外圍的一圈墻坊夫,阻礙玩家和怪物移動到關卡外面。避免單調撤卢,一共3張不同的外墻圖片环凿。
把Soda改名成OuterWall1,Sprite換成25號(特點是石頭多)放吩。
外墻需要碰撞器來阻礙角色和怪物進入到它的空間智听,所以把Is Trigger取消選中。
Layer選擇Blocking Layer渡紫,這樣角色和怪物在進行射線檢測是否存在這個標記的碰撞體的時候才能檢測到它到推。
Sorting Layer選擇Floor。(雖然其實選什么都沒什么影響惕澎,其他資源正常情況下不會和它在同一個位置莉测,但是嚴謹點好。)
Tag選擇Untagged唧喉,不需要標簽捣卤。
把OuterWall1拖到Prefabs文件夾生成預制件。按上述步驟把OuterWall2八孝、OuterWall3的預制件也做了(改名董朝、換Sprite、拖)唆阿,三個外墻的圖片序號是25益涧、26、28哦驯鳖,不要選錯了|???ω??)???闲询。
第6步:Wall
每個關卡隨機生成障礙墻在不同位置,能阻礙角色和怪物通行浅辙,同時角色可以劈砍這些障礙墻來開辟道路扭弧。
把OuterWall3改名為Wall1,Sprite換成21號(特點是像荊棘记舆、灌木叢)鸽捻。
把Sorting Layer改成Items(層級比floor高,這樣才能顯示在上面)泽腮。
其他維持不變御蒲,生成預制件之后把其他7個的預制件也做出來。Sprite序號是21诊赊、22厚满、23、24碧磅、27碘箍、29遵馆、30、31丰榴。
這些資源都準備好了货邓,接下來可以進入新的環(huán)節(jié)——制作關卡?(?????)?