摘?要:Unity3D是當(dāng)前國(guó)內(nèi)外廣泛使用的游戲開(kāi)發(fā)軟件,其所開(kāi)發(fā)出的塔防游戲自游戲發(fā)展以來(lái)就十分盛行。該項(xiàng)目基于Unity3D開(kāi)發(fā)了一款塔防游戲。其主要功能包括防御塔放置、敵人孵化、關(guān)卡管理、音效控制、UI界面以及最后的積分管理。該項(xiàng)目摒棄了傳統(tǒng)關(guān)卡設(shè)計(jì),通過(guò)關(guān)卡內(nèi)的難度上升而達(dá)到提升游戲難度的目的。通過(guò)該項(xiàng)目,可以讓玩家體驗(yàn)到難度層層遞增、挑戰(zhàn)性極強(qiáng)的塔防游戲。
關(guān)鍵詞:Unity3D;C#;塔防
中圖分類(lèi)號(hào):TP311? ? ? 文獻(xiàn)標(biāo)識(shí)碼:A? ? 文章編號(hào):2096-4706(2021)07-0071-04
Design and Implementation of 2D Tower Defense Game Based on Unity3D
ZHANG Baobao
(School of Computer and Software,Jincheng College of Sichuan University,Chengdu? 611731,China)
Abstract:Unity3D is game development software that is widely used at home and abroad at present. Tower defense games developed by it are extremely popular since the development of games. This project develops a tower defense game based on Unity3D. Its main functions include defense tower placement,enemy hatching,gate management,sound effect control,UI interface,and the final points management. Instead of traditional gate design,this project aims to increase the difficulty of the game by increasing the difficulty within the gate. Through this project,players can experience the tower defense game with increasing difficulty and strong challenge.
Keywords:Unity3D;C#;tower defense
收稿日期:2021-03-10
0? 引? 言
隨著電子產(chǎn)品的普及和發(fā)展,游戲技術(shù)也隨之得到了很大的提升。在游戲引擎和玩法方面,目前的游戲行業(yè)水平都達(dá)到了空前的高度。其中塔防類(lèi)游戲得到了很多玩家的喜愛(ài),不管是自身還是敵人都可以隨著關(guān)卡的進(jìn)行得到能力的提升。
1? 開(kāi)發(fā)工具及技術(shù)
Unity3D是由Unity公司設(shè)計(jì)的一款游戲引擎,在其中可以進(jìn)行2D及3D游戲的設(shè)計(jì)與開(kāi)發(fā)。該平臺(tái)同時(shí)支持主機(jī)、手機(jī)、PC等設(shè)備的游戲開(kāi)發(fā)。目前國(guó)內(nèi)外有相當(dāng)多的游戲制作組使用Unity開(kāi)發(fā)了很多優(yōu)秀游戲。本項(xiàng)目游戲腳本開(kāi)發(fā)采用C#語(yǔ)言,使用VS2019版本,設(shè)計(jì)了一款基于Unity3D的塔防游戲,實(shí)現(xiàn)了怪物AI、防御塔攻擊算法的設(shè)計(jì)以及眾多特效等。
2? 游戲策劃
本項(xiàng)目的塔防游戲擁有以下幾個(gè)規(guī)則:
(1)玩家可以使用金幣在建筑方塊上建造防御塔,但是每建造一次,金幣的消耗便會(huì)隨之增加。
(2)怪物會(huì)從不同的方向生成,并且會(huì)通過(guò)不同的路徑走向玩家的核心。怪物每生成一次,其攻擊力、防御力及每次的個(gè)數(shù)都會(huì)有所提升。
(3)玩家每擊殺一個(gè)怪物則會(huì)獲得金幣和血量的獎(jiǎng)勵(lì),但是此獎(jiǎng)勵(lì)會(huì)逐漸減少。
(4)怪物一旦碰到核心便會(huì)對(duì)其造成傷害,核心血量達(dá)到0,游戲便結(jié)束。
游戲流程如圖1所示。
3? 游戲主要功能模塊詳細(xì)設(shè)計(jì)與實(shí)現(xiàn)
3.1? 場(chǎng)景搭建及功能設(shè)計(jì)
本項(xiàng)目使用Unity中的TileMap功能進(jìn)行場(chǎng)景的繪制。此功能也是Unity為2D游戲提供的一個(gè)便于繪圖的功能。我們把將要使用的方塊素材放置到一個(gè)類(lèi)似于“顏料板”的窗口后,便可以使用筆刷蘸取不同的方塊素材在畫(huà)布上進(jìn)行繪制。這樣繪制出來(lái)的地圖會(huì)成為一個(gè)整體。主要分為整體系統(tǒng)的設(shè)計(jì)、防御塔的設(shè)計(jì)和怪物的設(shè)計(jì)三大類(lèi)。游戲功能如圖2所示。
3.2? 炮塔的設(shè)計(jì)
3.2.1? 加農(nóng)炮的設(shè)計(jì)
加農(nóng)炮是游戲里常見(jiàn)的一種大炮類(lèi)型,在項(xiàng)目里面的加農(nóng)炮分為了上下兩個(gè)部分,一個(gè)底座一個(gè)炮管,之所以要這么設(shè)計(jì),是為了在實(shí)現(xiàn)炮管旋轉(zhuǎn)時(shí)能夠更加真實(shí)。我們需要在炮管上設(shè)置一個(gè)圓圈形的觸發(fā)器,這代表著防御塔的攻擊范圍,在代碼里面要設(shè)置一個(gè)OnTriggerEnter2D的函數(shù),用來(lái)捕捉到進(jìn)入觸發(fā)器的對(duì)象,如果為敵人則將記錄敵人數(shù)量的參數(shù)加1。在2D游戲中,無(wú)法使用transform.lookat的方法,為了讓炮管能夠始終朝向敵人,則需要設(shè)置OnTriggerStay2D函數(shù),在這個(gè)函數(shù)中獲取敵人和炮管的位置差值,利用差值算出炮管和敵人之間夾角的正切值,然后再利用這個(gè)正切值使炮管能夠旋轉(zhuǎn)。主要代碼為:
Vector2 direction=collision.transform.position-transform.position;
float angle=Mathf.Atan2(direction.y,direction.x)*Mathf.Rad2Deg;
transform.rotation=Quaternion.AngleAxis(angle,Vector3.forward);
當(dāng)敵人離開(kāi)觸發(fā)器范圍時(shí),在OnTriggerExit函數(shù)中使記錄敵人數(shù)量的參數(shù)減1。同時(shí)為了讓炮管能夠發(fā)射子彈,則為發(fā)射子彈功能建立一個(gè)協(xié)程函數(shù),便于控制射擊的調(diào)用和時(shí)間間隔。協(xié)程函數(shù)代碼為:
IEnumeratorfireCor()
{while (true)
{yieldreturnnewWaitForSeconds(0.5f);Instantiate(bullet, shotpoint.transform.position, gameObject.transform.rotation);}}
并且在Update中檢測(cè)敵人數(shù)量來(lái)開(kāi)啟、關(guān)閉協(xié)程。子彈本身會(huì)朝著自身的X軸移動(dòng),一旦發(fā)射出來(lái)便會(huì)向著炮管瞄準(zhǔn)的方向射擊。只要子彈碰撞到敵人,則會(huì)調(diào)用敵人身上的受傷函數(shù)。
3.2.2? 火塔的設(shè)計(jì)
火塔在游戲中是一個(gè)能夠造成持續(xù)傷害的防御塔?;鹚噍^于加農(nóng)炮多了一個(gè)火焰特效的設(shè)計(jì)。將不同火焰燃燒的圖片建立為動(dòng)畫(huà)的不同關(guān)鍵幀,在播放的時(shí)候就會(huì)形成火焰燃燒的效果。在火塔中也需要一個(gè)圓形觸發(fā)器,同樣也是作為火塔的攻擊范圍。在腳本中利用OnTirggerStay2D函數(shù)來(lái)進(jìn)行敵人對(duì)象的捕捉和檢測(cè)。一旦檢測(cè)到敵人便會(huì)調(diào)用敵人身上的受傷函數(shù)。動(dòng)畫(huà)制作如圖3所示。
3.3? 核心的設(shè)計(jì)
本游戲的核心設(shè)計(jì)為一顆心臟樣子,首先要為其添加動(dòng)畫(huà)。在動(dòng)畫(huà)中的不同關(guān)鍵幀上使心臟對(duì)象的大小有所調(diào)整,這樣就會(huì)形成一顆心臟跳動(dòng)的效果。然后為其添加觸發(fā)器,使得心臟能夠和敵人發(fā)生碰撞。
3.4? 敵人控制
3.4.1? 敵人的設(shè)計(jì)
在敵人的身上也有類(lèi)似于核心的動(dòng)畫(huà)設(shè)計(jì),使其運(yùn)動(dòng)時(shí)看起來(lái)更加逼真。在敵人的身上有一個(gè)受傷函數(shù),函數(shù)的參數(shù)則為受到的傷害,敵人會(huì)根據(jù)防御值和傷害來(lái)計(jì)算出實(shí)際受到的傷害。敵人如圖4所示。
3.4.2? 敵人的孵化
在需要敵人孵化的點(diǎn)處放置空對(duì)象并且編輯腳本。在腳本中需要?jiǎng)?chuàng)建兩個(gè)計(jì)時(shí)器,第一個(gè)計(jì)時(shí)器用來(lái)計(jì)算一次內(nèi)怪物的孵化間隔,如果到了孵化間隔,則生成怪物到指定的位置,將怪物生成計(jì)數(shù)加1,并且將計(jì)時(shí)器復(fù)原。第二個(gè)計(jì)時(shí)器則是用來(lái)計(jì)算每一次怪物生成的間隔,如果第二個(gè)計(jì)時(shí)器大于等于每次間隔,則使其復(fù)原,將每次敵人數(shù)量增加,并且利用全局變量改變敵人的防御值。主要代碼為:
time2+=Time.deltaTime;
if (time2 {time+=Time.deltaTime; if(time>rate) {Instantiate(Enemy,gameObject.transform.position-new Vector3(-8.80f,2.34f),Quaternion.identity);count++;time-=rate;}} if(time2>=timeofEachWave) {time2=0;maxene+=2;count=0;GlobalValue.instance.enemydefence+=0.1f;AudioManager.instance.PlaySound(next); } 3.4.3? 敵人的自動(dòng)尋路 為了使敵人能夠按照一定的路徑走向核心,在游戲中采用了路徑點(diǎn)的辦法,先用一個(gè)Transform類(lèi)型的數(shù)組來(lái)存放路徑點(diǎn)組,在腳本中創(chuàng)建一個(gè)MoveToThePoints()函數(shù)來(lái)實(shí)現(xiàn)怪物的移動(dòng),代碼為: Vector2 temp=Vector2.MoveTowards(transform.position, theWayPoints[index].position,speed* Time.deltaTime); GetComponent 在Update函數(shù)中判斷是否達(dá)到了目標(biāo)路徑點(diǎn)的位置如果沒(méi)有則調(diào)用MoveToThePoints函數(shù),如果到了則將目標(biāo)路徑點(diǎn)設(shè)置為下一個(gè)。 在游戲中存在一種迅捷怪物,這種怪物采用了另外一種尋路方式,它是利用A*PathFind插件來(lái)實(shí)現(xiàn)的。首先要在移動(dòng)路徑兩旁放置對(duì)象,然后在A*PathFind插件中來(lái)檢測(cè)可以行動(dòng)的范圍,在迅捷怪物上添加插件中的移動(dòng)腳本,并且將目標(biāo)設(shè)置為核心,這樣怪物就會(huì)通過(guò)最近的路徑移動(dòng)到核心,從而加大游戲的難度。 3.4.4? 敵人的血量及死亡 不管是火塔攻擊還是子彈的碰撞都會(huì)調(diào)用敵人腳本中的受傷函數(shù),敵人在受到傷害時(shí)會(huì)進(jìn)行一定的防御計(jì)算,如:health -= (dam / GlobalValue.instance.enemydefence);。如果敵人的生命值小于等于0,則會(huì)觸發(fā)音效、摧毀敵人并提供獎(jiǎng)勵(lì)。在OnTriggerEnter2D中如果碰撞到了核心則會(huì)使玩家受傷,并且會(huì)讓加農(nóng)炮的敵人記錄數(shù)減少。代碼為: if (collision.gameObject.transform.CompareTag("Player")) {GlobalValue.instance.hurt(damage); Cannon.instance.enenumcost(); Destroy(gameObject);} 3.5? 游戲UI、音效及管理 3.5.1? 游戲場(chǎng)景切換 當(dāng)打開(kāi)游戲時(shí)并不會(huì)直接開(kāi)始游戲,首先會(huì)有一個(gè)開(kāi)始的場(chǎng)景,有游戲的名稱(chēng),并且有開(kāi)始按鈕、幫助按鈕等。玩家可以點(diǎn)擊不同的按鈕切換到不同的場(chǎng)景。當(dāng)按下幫助按鈕后,會(huì)切換到游戲規(guī)則講解場(chǎng)景,也可以點(diǎn)擊返回按鈕返回。當(dāng)點(diǎn)擊開(kāi)始后,會(huì)進(jìn)入到關(guān)卡選擇場(chǎng)景。游戲的場(chǎng)景采用的是不斷解鎖的方式,當(dāng)玩家一個(gè)關(guān)卡玩到一定的分?jǐn)?shù)后,會(huì)解鎖下一個(gè)關(guān)卡。當(dāng)玩家點(diǎn)擊關(guān)卡按鈕后則會(huì)進(jìn)入關(guān)卡開(kāi)始游戲。 3.5.2? 游戲UI 在游戲進(jìn)行的時(shí)候,游戲會(huì)顯示當(dāng)前的金幣數(shù)量和建造不同防御塔所需的花費(fèi)。同時(shí)玩家的生命值會(huì)以進(jìn)度條的方式顯示在頂部。在右上角還有一個(gè)暫停按鈕,但是由于游戲機(jī)制的設(shè)定,玩家需要花費(fèi)500金幣來(lái)暫停游戲。游戲UI如圖5所示。 3.5.3? 游戲數(shù)據(jù)管理 在整個(gè)項(xiàng)目中,使用了一個(gè)GlobalValue腳本來(lái)管理不同的數(shù)據(jù),包括建造塔的花費(fèi)函數(shù)等。將所有的數(shù)據(jù)存放于一個(gè)腳本中,便不會(huì)出現(xiàn)不同對(duì)象使用腳本時(shí),因?yàn)閿?shù)據(jù)更改而出現(xiàn)的錯(cuò)誤,同時(shí)也更加方便管理。 3.5.4? 游戲音效 在游戲中,建造防御塔,擊殺怪物,每一波怪物生成都有不同的音效。首先要在項(xiàng)目中添加一個(gè)AudioManager腳本用以管理整體的音效播放。在其中建立音效播放函數(shù)(其參數(shù)為需要播放的聲音),然后在需要音效的地方調(diào)用此函數(shù)。并且在攝像機(jī)上添加一個(gè)AudioSource組件用來(lái)播放游戲的BGM。 3.6? 游戲腳本 在本項(xiàng)目中,主要使用了游戲管理腳本,全局值腳本,防御塔建造腳本,敵人控制腳本,敵人孵化腳本,敵人尋路腳本,炮塔控制腳本,火塔控制腳本,音效控制腳本,關(guān)卡切換腳本等。其中較為重要的是防御塔建造腳本,主要是利用射線檢測(cè)來(lái)判斷鼠標(biāo)點(diǎn)擊的方塊是否可建造。再根據(jù)判斷點(diǎn)擊左右鍵來(lái)建造不同的防御塔。 4? 測(cè)試 4.1? 測(cè)試環(huán)境 本游戲制作使用的Unity3D為2018.3.9f1版本,C#腳本由VisualStudio2019進(jìn)行編寫(xiě)。游戲在顯卡GTX970、CPU為i5,內(nèi)存8 GB的環(huán)境下進(jìn)行測(cè)試。 4.2? 測(cè)試內(nèi)容 游戲測(cè)試內(nèi)容主要為,讓不同玩家通過(guò)不同配置的電腦及不同分辨率來(lái)進(jìn)行游戲,查看游戲的UI是否錯(cuò)位,其次通過(guò)玩家的反饋來(lái)進(jìn)行游戲難度的調(diào)整,讓玩家能夠體驗(yàn)到游戲難度的坡度上升,并且可以在其中找到樂(lè)趣。最后在對(duì)比不同玩家得到的分?jǐn)?shù),來(lái)完善最終分?jǐn)?shù)的計(jì)算方式。游戲功能如圖6所示。 5? 結(jié)? 論 本項(xiàng)目是基于Unity3D開(kāi)發(fā)的一款塔防游戲。主要功能包括防御塔的放置、敵人的孵化和尋路、關(guān)卡設(shè)計(jì)與管理、音效控制、UI界面及最后的積分系統(tǒng)。通過(guò)本項(xiàng)目,可以讓玩家體驗(yàn)到難度遞增的塔防游戲,并且可以通過(guò)此游戲得到一個(gè)良好的體驗(yàn)。 游戲已經(jīng)達(dá)到了可以暢玩的基本要求,但是仍然還有很多需要改進(jìn)的地方。在未來(lái)還需要優(yōu)化游戲的代碼,使其能夠在大量怪物和防御塔存在時(shí),能夠使運(yùn)行更加流暢。其次是增加怪物和防御塔的種類(lèi),創(chuàng)作更多新的關(guān)卡地圖。 參考文獻(xiàn): [1] 胡靜,胡欣宇.基于Unity3D引擎的游戲設(shè)計(jì)與開(kāi)發(fā) [J].電子元器件與信息技術(shù),2021,5(2):138-140+154. [2] 王艷,華唯辰.基于Unity3D的ARPG游戲設(shè)計(jì)與實(shí)現(xiàn) [J].電腦知識(shí)與技術(shù),2020,16(29):199-201. [3] 周正,司占軍,秦雷.開(kāi)放世界類(lèi)型游戲的設(shè)計(jì)與制作 [J].電腦知識(shí)與技術(shù),2020,16(22):1-2+7. [4] 周正,司占軍.基于Unity3D的冒險(xiǎn)闖關(guān)類(lèi)游戲的設(shè)計(jì)與實(shí)現(xiàn) [J].電腦知識(shí)與技術(shù),2020,16(21):90-91. [5] 岳書(shū)丹,陳雪榮.基于Unity3D塔防游戲的設(shè)計(jì)與實(shí)現(xiàn) [J].電子測(cè)試,2020(13):124-126. 作者簡(jiǎn)介:張寶寶(2000—)男,漢族,四川宜賓人,本科在讀,研究方向:VR與游戲開(kāi)發(fā)。