Unity 寶塔對(duì)戰教程

simaoshid1 2018-06-22

Unity 寶塔對(duì)戰教程

這(zhè)個(gè)教程詳細介紹了(le)如何在unity中制作一個(gè)漂亮的(de)小的(de)寶塔對(duì)戰遊戲。我們會一步步介紹使得(de)每個(gè)人(rén)都可(kě)以理(lǐ)解。

序言

教程中我們會用(yòng)完全***的(de)圖像風格來(lái)創建一個(gè)小的(de)三維寶塔對(duì)戰遊戲。這(zhè)個(gè)遊戲很容易做(zuò),不需要任何三維建模技巧,沒有動畫(huà),且沒有任何複雜(zá)的(de)。很簡單,我們所需要的(de)是90行代碼。

必要條件

知識

我們的(de)教程不需要任何特殊的(de)技巧。如果你之前了(le)解unity并聽(tīng)過Gameobjects(遊戲主體),Prefabs(預設)以及轉變,然後你就可(kě)以準備開始了(le)。如果你沒有,不用(yòng)太擔心。

去閱讀我們簡單的(de)教程比如Unity2D乒乓球遊戲來(lái)學會使用(yòng)這(zhè)個(gè)引擎。

不用(yòng)擔心,沒有恐怖的(de)數學!

Unity 版本

我們的(de)寶塔對(duì)戰遊戲是用(yòng)Unity 5.3.1f1制作完成。新的(de)版本應該可(kě)以,老的(de)版本有的(de)可(kě)以,有的(de)不行。

我們不需要任何***的(de)***,因此Unity的(de)免費版本就可(kě)以了(le)

遊戲機制

對(duì)于那些從來(lái)沒聽(tīng)過寶塔對(duì)戰的(de)人(rén),這(zhè)兒(ér)有些基本常識:

怪獸每幾秒孵化(huà)的(de)地方是個(gè)點

怪獸跑遍整個(gè)世界向著(zhe)它們想摧毀的(de)城(chéng)堡

玩家可(kě)以建立城(chéng)堡來(lái)攻擊怪獸

另外,我們用(yòng)Buildplaces.Buildplaces是在地圖上預先設置好的(de)地方,那裏玩家可(kě)以建立寶塔。我們會用(yòng)到它們。因爲它會使得(de)我們更容易活下(xià)來(lái)(作爲對(duì)比,在地圖上到處可(kě)以建立寶塔)

藝術風格

我們有兩個(gè)操作:我們可(kě)以找現實主義的(de)東西,會耗費幾百個(gè)高(gāo)質量的(de)3D模型,紋理(lǐ)和(hé)著(zhe)色器,或者我們可(kě)以找些簡單但***的(de)東西。

我們的(de)格言是跟我談談,比如我很厲害!因此我們不用(yòng)深入到CAD工具的(de)世界裏來(lái)創建現實主義的(de)3D模型。相反,我們會用(yòng)到一個(gè)完全抽象的(de)風格,會省去我們的(de)許多(duō)工作,但看起來(lái)很有趣。我們會使用(yòng)Unity的(de)原件(立方體,球形,圓柱體,...)與僅有的(de)一些顔色結合(大(dà)部分(fēn)是綠色,黃(huáng)色和(hé)灰色)。

這(zhè)種藝術風格的(de)好處是每個(gè)人(rén)都可(kě)以在少于一個(gè)小時(shí)的(de)時(shí)間内創建它沒有任何3D建模或動畫(huà)知識。

項目建立

Unity 寶塔對(duì)戰教程

我們命名爲towerdefense,選擇任意位置比如C:\,選擇3D并點擊創建項目:

Unity 寶塔對(duì)戰教程

如果我在Hierarchy中選擇Main Camera,然後我們可(kě)以設置背景色爲黑(hēi)色,調整位置和(hé)旋轉如下(xià)圖所示:

Unity 寶塔對(duì)戰教程

注意,這(zhè)會使照(zhào)相機以45度角向下(xià)俯視整個(gè)遊戲場(chǎng)景。

燈光(guāng)

我們爲遊戲添加些燈光(guāng),以***于場(chǎng)景不***于太黑(hēi)暗。我們通(tōng)過選擇GameObject->light->Directional Light來(lái)添加光(guāng)源在頂部菜單中。我們可(kě)以用(yòng)下(xià)面的(de)設置來(lái)确保燈光(guāng)在我們的(de)場(chǎng)景中處于一個(gè)更好的(de)角度:

Unity 寶塔對(duì)戰教程

注意:我們基本可(kě)以用(yòng)任何我們想要的(de)設置,但上面那個(gè)看著(zhe)比較好。

地面

我們需要某種地面使得(de)怪獸能夠行走。我們通(tōng)過從頂部菜單來(lái)選擇GameObject->3D Object->Plane來(lái)添加平面。我們命名爲Ground并在Inspector中設置爲如圖所示的(de)位置(Position)和(hé)大(dà)小(Scale).

Unity 寶塔對(duì)戰教程

注意,這(zhè)個(gè)大(dà)小是***合适的(de)大(dà)小,适合于所有的(de)Buildplaces和(hé)城(chéng)堡.

我們打開我們選擇的(de)繪畫(huà)工具并創建一個(gè)小的(de)有基本綠色色調的(de)40*40px的(de)紋理(lǐ)。通(tōng)過用(yòng)基本色來(lái)填充來(lái)創建你自己的(de)紋理(lǐ),然後用(yòng)稍微明(míng)亮或暗沉的(de)綠色調來(lái)繪制一些随意的(de)線條。這(zhè)是我們得(de)到的(de)

Unity 寶塔對(duì)戰教程

注意:右擊這(zhè)個(gè)圖片,選擇Save As...,導航到項目的(de)Assets文件夾并保存它到新的(de)紋理(lǐ)文件夾。

現在我們可(kě)以從項目區(qū)域的(de)紋理(lǐ)文件夾内拖動紋理(lǐ)到地面(Ground):

Unity 寶塔對(duì)戰教程

如果我們現在靠近看地面,我們可(kě)以看到紋理(lǐ)看起來(lái)是多(duō)麽光(guāng)滑

Unity 寶塔對(duì)戰教程

對(duì)大(dà)多(duō)數遊戲來(lái)說是好的(de),但對(duì)我們的(de)寶塔對(duì)戰教程,我們想紋理(lǐ)看起來(lái)像素化(huà)來(lái)獲得(de)一個(gè)更***的(de)風格。我們在Project Area中選擇紋理(lǐ)并在Inspector中改變Import Settings如下(xià)圖所示:

Unity 寶塔對(duì)戰教程

現在看起來(lái)完全像素化(huà)了(le):

Unity 寶塔對(duì)戰教程

注意:我們在遊戲中會對(duì)所有的(de)紋理(lǐ)使用(yòng)這(zhè)個(gè)風格。

地點

立方體地點

好了(le),我們需要一些地方用(yòng)來(lái)給玩家建立寶塔(與其在整個(gè)場(chǎng)景中到處建造它,那樣會更複雜(zá))。我們會通(tōng)過創建一個(gè)地點來(lái)開始然後複制它幾個(gè)以***于我們能用(yòng)地點來(lái)設計一些怪獸行走的(de)迷宮。

我們選擇GameObject->3D Object->立方體從頂部菜單。我們放置它于(-14,0.5,-14)并命名爲Buildplace:

Unity 寶塔對(duì)戰教程

注意:x,z坐(zuò)标應該是四舍五入爲整數比如14(而不是13.99)。Y的(de)位置是0.5,以***于立方體能準确待在地面上,而不是嵌入到地面中。

看起來(lái)場(chǎng)景是這(zhè)樣的(de):

Unity 寶塔對(duì)戰教程

Buildplace的(de)紋理(lǐ)

我們畫(huà)一個(gè)簡單的(de)8*8像素的(de)紋理(lǐ),我們可(kě)以穿上它:

tex_buildplace.png

注意:右擊鏈接,選擇Save as...保存它到項目的(de)assets/textures文件夾

我們用(yòng)下(xià)面的(de)導入設置:

畢竟我們可(kě)以從項目區(qū)域拖動它到Buildplace以***于紋理(lǐ)看起來(lái)更漂亮:

Unity 寶塔對(duì)戰教程

Buildplace 腳本

我們想在用(yòng)戶點擊Buildplace的(de)時(shí)候就建立寶塔。這(zhè)種行爲總是用(yòng)腳本來(lái)繼承。我們通(tōng)過在Inspector中選擇Add Component->New Script來(lái)創建新的(de)腳本。我們命名爲Buildplace并選擇CSharp作爲語言:

Unity 寶塔對(duì)戰教程

現在我們的(de)Buildplace有一個(gè)腳本:

Unity 寶塔對(duì)戰教程

我們在項目區(qū)域創建一個(gè)新的(de)腳本文件夾并移動腳本到文件夾中,以***于看起來(lái)幹淨整潔:

Unity 寶塔對(duì)戰教程

然後我們雙擊項目區(qū)域裏的(de)腳本并打開:

[C#] 純文本查看 複制代碼

?

0102030405060708091011121314using UnityEngine;using System.Collections;public class Buildplace : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { }}

首先,我們不需要Start或Update方法,因此我們移除它們:

[C#] 純文本查看 複制代碼

?

12345using UnityEngine;using System.Collections;public class Buildplace : MonoBehaviour {}

我們将需要一些公共的(de)變量來(lái)具體化(huà)将要建立的(de)寶塔:

[C#] 純文本查看 複制代碼

?

1234567using UnityEngine;using System.Collections;public class Buildplace : MonoBehaviour { // The Tower that should be built public GameObject towerPrefab;}

注意:因爲towerPrefab變量是公共的(de),我們一會兒(ér)可(kě)以在Inspector中具體化(huà)它。

下(xià)一步是點擊Buildplace後,用(yòng)Instantiate函數來(lái)建立寶塔。通(tōng)常,Unity使得(de)我們的(de)生活更同意因爲已經提供了(le)OnMouseUpAsButton函數,我們可(kě)以用(yòng):

[C#] 純文本查看 複制代碼

?

01020304050607080910using UnityEngine;using System.Collections;public class Buildplace : MonoBehaviour { // The Tower that should be built public GameObject towerPrefab; void OnMouseUpAsButton() { // TODO build stuff... }}

現在我們能做(zuò)的(de)就是在Buildplace上面建立Tower:

[C#] 純文本查看 複制代碼

?

1234void OnMouseUpAsButton() { // Build Tower above Buildplace GameObject g = (GameObject)Instantiate(towerPrefab); g.transform.position = transform.position + Vector3.up;}

注意:首先我們通(tōng)過使用(yòng)Instantiate來(lái)導入towerPrefab到遊戲中。然後我們修改位置成爲現在Buildplace's的(de)位置往上移一個(gè)單位。

如果我們保存腳本并觀察Inspector,我們也(yě)可(kě)以看到TowerPrefab 槽,那兒(ér)我們可(kě)以拖動寶塔到裏面:

Unity 寶塔對(duì)戰教程

創建更多(duō)的(de)Buildplaces

既然一個(gè)Buildplace已經完成,我們右擊Hierarchy并選擇Duplicate:

Unity 寶塔對(duì)戰教程

然後我們放置它到(-13,0.4,-14)以***于準确與之前那個(gè)相鄰:

Unity 寶塔對(duì)戰教程

我們重複這(zhè)個(gè)過程幾次爲了(le)給怪獸創建行走的(de)迷宮。我們在城(chéng)堡頂部留一個(gè)空白的(de)區(qū)域:

Unity 寶塔對(duì)戰教程

城(chéng)堡

城(chéng)堡立方體

對(duì)了(le),我們創建一個(gè)城(chéng)堡以緻于怪獸有可(kě)以攻擊的(de)地方。我們通(tōng)過從頂部菜單選擇GameObject->3D Object->Cube開始。我們命名爲城(chéng)堡(Castle),放置它到我們迷宮的(de)空的(de)區(qū)域并通(tōng)過縮放,使它變大(dà)點:

城(chéng)堡紋理(lǐ)

我們再創建一個(gè)簡單的(de)16*16像素的(de)紋理(lǐ):

Unity 寶塔對(duì)戰教程

注意:右擊圖片,選擇Save As..并保存它到項目的(de)Assets/Textures文件夾

這(zhè)兒(ér)有我們城(chéng)堡紋理(lǐ)的(de)導入設置:

Unity 寶塔對(duì)戰教程

我們從項目區(qū)域中拖動紋理(lǐ)到城(chéng)堡并收到一個(gè)很簡單但***的(de)視角:

Unity 寶塔對(duì)戰教程

健康值條柱

好了(le),我們在城(chéng)堡上添加健康值條柱。有許多(duō)種不同的(de)方法來(lái)做(zuò),我們選個(gè)簡單的(de)做(zuò)。我們爲城(chéng)堡添加一個(gè)3D紋理(lǐ),它包括文字比如‘-’是1個(gè)健康值,‘--’是2個(gè)健康值,‘---’是3個(gè)健康值等等。

我們通(tōng)過右擊Hierarchy并選擇創建空的(de)并添加3D紋理(lǐ)到城(chéng)堡:

Unity 寶塔對(duì)戰教程

然後我們重命名新的(de)遊戲主體到健康柱并在Inspector選擇Add Component->Mesh->TextMesh;

Unity 寶塔對(duì)戰教程

我們放置它在城(chéng)堡上方一個(gè)單位,然後修改TextMesh 組件來(lái)獲得(de)更好的(de)結果:

Unity 寶塔對(duì)戰教程

注意:Text屬性已經包含了(le)7x'-',相當于7個(gè)健康值。其他(tā)屬性大(dà)部分(fēn)被改變了(le),來(lái)改變字體大(dà)小和(hé)尖銳性。放置Arial到字體屬性很重要。我們通(tōng)過點擊字體屬性右邊的(de)小圈來(lái)做(zuò)這(zhè)個(gè)。然後Unity展現目前可(kě)用(yòng)的(de)字體列表,我們從列表中可(kě)以選擇一個(gè)。

場(chǎng)景看起來(lái)是這(zhè)樣的(de):

Unity 寶塔對(duì)戰教程

很簡單。現在我們需要一個(gè)健康簡本準确得(de)做(zuò)三個(gè)事情:

通(tōng)過數‘-’來(lái)返回現在的(de)健康值

通(tōng)過移除‘-’來(lái)減少現在的(de)健康

一直使得(de)TextMesh面對(duì)照(zhào)相機

我們想TextMesh來(lái)面對(duì)照(zhào)相機爲了(le)避免奇怪的(de)角度比如這(zhè)個(gè):

對(duì)了(le),我們選擇Add Component->New Script,命名爲Health并選擇CSharp。我們移動它到項目區(qū)域的(de)腳本文件夾并打開它:

[C#] 純文本查看 複制代碼

?

12345678using UnityEngine;using System.Collections;public class Health : MonoBehaviour { // Use this for initialization void Start () { }

[C#] 純文本查看 複制代碼

?

1234 // Update is called once per frame void Update () { }}

首先我們需要獲得(de)TextMesh組件:

[C#] 純文本查看 複制代碼

?

0102030405060708091011121314using UnityEngine;using System.Collections;public class Health : MonoBehaviour { // The TextMesh Component TextMesh tm; // Use this for initialization void Start () { tm = GetComponent(); } // Update is called once per frame void Update () {[/align][align=left]}

現在我們用(yòng)Update功能,使它一直面對(duì)計算(suàn)機:

[C#] 純文本查看 複制代碼

?

0102030405060708091011121314151617using UnityEngine;using System.Collections;public class Health : MonoBehaviour { // The TextMesh Component TextMesh tm; // Use this for initialization void Start () { tm = GetComponent(); } // Update is called once per frame void Update () { // Face the Camera transform.forward = Camera.main.transform.forward; }}

注意:沒有複雜(zá)的(de)數學。我們能做(zuò)的(de)是使得(de)我們的(de)遊戲主體進入準确的(de)照(zhào)相機對(duì)著(zhe)的(de)方位。

現在我們添加current()和(hé)decrease()函數:

[C#] 純文本查看 複制代碼

?

0102030405060708091011// Return the current Health by counting the '-'public int current() { return tm.text.Length;}// Decrease the current Health by removing one '-'public void decrease() { if (current() > 1) tm.text = tm.text.Remove(tm.text.Length - 1); else Destroy(transform.parent.gameObject);}

注意,這(zhè)是***一件看著(zhe)有點奇怪的(de)事情。通(tōng)常我們有些整型變量來(lái)表展現我們現在的(de)健康值。相反,我們利用(yòng)包含這(zhè)些‘-’的(de)字符串的(de)TextMesh的(de)文字。我們自動摧毀健康柱的(de)父對(duì)象(這(zhè)個(gè)是城(chéng)堡)直到健康值變爲0。我們使得(de)這(zhè)些函數公共以緻于其他(tā)腳本能用(yòng)它們。

是的(de),我們遊戲***簡單的(de)健康柱。好事是我們也(yě)能夠爲怪獸用(yòng)。

怪獸

我們爲我們的(de)遊戲添加怪獸。通(tōng)常我們需要用(yòng)CAD工具比如blender,maya或3dsmax來(lái)創建怪獸。但因爲我們想把事情簡單化(huà),我們會用(yòng)Unity原件來(lái)創建看起來(lái)像怪獸的(de)圓柱體。

我們從頂部菜單選擇GameObject->3D Object->Cube開始。我們命名爲Monster并檢查碰撞器的(de)Is Trigger 操作以***于 怪獸之後不會互相碰撞:

Unity 寶塔對(duì)戰教程

我們繪制很小的(de)8*8的(de)紋理(lǐ)來(lái)給它賦予顔色:

tex_monster.png

注意:右擊鏈接,選擇Save As..保存到項目的(de)Assets/Textures文件夾

我們用(yòng)下(xià)面的(de)Import Settings來(lái)設置:

Unity 寶塔對(duì)戰教程

從項目區(qū)域(Project Area)中拖拽到怪獸上,看起來(lái)是這(zhè)個(gè)樣子的(de):

Unity 寶塔對(duì)戰教程

詳情頁

我們在Hierarchy中右擊怪獸并選擇3D Object->Cube。我們命名新的(de)立方體爲Eye,放置它到立方體的(de)左中心并使它變小以***于看起來(lái)像個(gè)眼睛。我們再檢查下(xià)IsTrigger:

Unity 寶塔對(duì)戰教程

這(zhè)是場(chǎng)景中看起來(lái)的(de)樣子:

Unity 寶塔對(duì)戰教程

我們爲眼睛畫(huà)一個(gè)簡單的(de)白色的(de)紋理(lǐ):

-tex_eye.png

注意:右擊鏈接并選擇Save As..并保存到項目的(de)Assets/Textures文件夾。

我們用(yòng)下(xià)面的(de)導入設置(Import Settings):

然後拖拽它到我們的(de)EyeGameObject上。

我們重複這(zhè)個(gè)步驟制作另一個(gè)眼睛,像這(zhè)樣:

Unity 寶塔對(duì)戰教程

像你所想的(de)那樣爲怪獸添加更多(duō)細節。我們簡單地添加兩隻腳:

Unity 寶塔對(duì)戰教程

怪獸物(wù)理(lǐ)

我們的(de)怪獸已經有了(le)一個(gè)碰撞器,使得(de)它已經成爲了(le)物(wù)理(lǐ)世界。還(hái)有一件事需要添加。假設通(tōng)過物(wù)理(lǐ)世界的(de)每個(gè)東西需要有一個(gè)剛體賦予它。剛體擁有引力,速度和(hé)其他(tā)力使得(de)物(wù)體移動。

我們首先選擇怪獸遊戲主體(不是眼睛也(yě)不是腳)來(lái)添加剛體,然後點擊AddComponent->Physics->Rigidbody 在Inspector中。我們使用(yòng)下(xià)面的(de)設置:

Unity 寶塔對(duì)戰教程

注意:我們使用(yòng)默認設置。

路徑尋找

我們想要怪獸能夠通(tōng)過迷宮并進入城(chéng)堡。我們不得(de)不做(zuò)兩件事來(lái)實現它:

烘焙一個(gè)導航網格(來(lái)告訴Unity哪個(gè)區(qū)域是可(kě)走的(de))

添加導航網格代理(lǐ)給怪獸

我們告訴Unity那些部分(fēn)是可(kě)走的(de)來(lái)開始。好消息是Unity實際上自己繪制出來(lái)了(le)。我們不得(de)不做(zuò)的(de)事情是告訴Unity我們哪部分(fēn)世界是靜态的(de)(例如::絕不移動)

我們選擇地面(Ground)和(hé)所有的(de)BuildPlaces在Hierarchy中然後使得(de)檢查器中的(de)Static(靜态) 屬性可(kě)用(yòng):

Unity 寶塔對(duì)戰教程

現在unity知道這(zhè)些東西絕不能移動,因此會用(yòng)它們來(lái)計算(suàn)可(kě)移動的(de)區(qū)域。

現在我們從頂部菜單選擇Window->Navigation并使用(yòng)下(xià)面的(de)屬性:

Unity 寶塔對(duì)戰教程

然後我們點擊底部的(de)Bake按鈕。幾秒之後,我們能看到Unity怎麽計算(suàn)場(chǎng)景中的(de)可(kě)移動區(qū)域:

Unity 寶塔對(duì)戰教程

注意:***重要的(de)部分(fēn)是通(tōng)過迷宮的(de)路徑。Unity也(yě)認爲Buildplaces是可(kě)移動的(de),但因爲沒有爲怪獸提供階梯來(lái)爬,所以沒關系的(de)。

對(duì)了(le),我們現在再次選擇怪獸并點擊AddComponent->Navigation->Nav Mesh Agent.這(zhè)個(gè)組件被所有的(de)東西所需要,通(tōng)過我們剛剛我們烘焙過的(de)的(de)導航網格。我們爲我們的(de)代理(lǐ)使用(yòng)下(xià)面的(de)設置:

Unity 寶塔對(duì)戰教程

注意:我們僅僅修改了(le)移動的(de)速度和(hé)大(dà)小使其适合我們的(de)怪獸。如果你對(duì)設置還(hái)不滿意還(hái)可(kě)以修改。

既然我們的(de)導航網格被烘焙并且怪獸有個(gè)導航網格代理(lǐ),我們能做(zuò)的(de)就是使它移動到一個(gè)地方比如:

[C#] 純文本查看 複制代碼

?


GetComponent.destination =new Vector3(1, 2, 3);

注意:當我們之後創建怪獸腳本的(de)時(shí)候我們來(lái)做(zuò)這(zhè)個(gè)。

健康柱

我們添加一個(gè)健康柱到怪獸,以***于寶塔可(kě)以攻擊它。我們用(yòng)準确相同的(de)工作流,我們爲我們城(chéng)堡的(de)健康柱用(yòng)的(de),一些不同的(de)設置使得(de)它更小并變紅:

Unity 寶塔對(duì)戰教程

注意:我們改變Text屬性爲4x"-"以***于怪獸僅能攻擊4個(gè)寶塔。

這(zhè)個(gè)是怪獸的(de)健康柱在場(chǎng)景中看起來(lái)的(de)樣子:

Unity 寶塔對(duì)戰教程

怪獸腳本

好了(le)正如前面我們提到的(de),我們想要創建怪獸腳本,使它移動到城(chéng)堡然後當它到達城(chéng)堡後就受到一點的(de)傷害。

我們在Hierarchy中選擇怪獸,然後點擊Add Component->New Script,命名爲怪獸(Monster)并選擇C#作爲編程語言。我們移動它到腳本文件夾并打開:

[C#] 純文本查看 複制代碼

?

12345678using UnityEngine;using System.Collections;public class Monster : MonoBehaviour { // Use this for initialization void Start () { }[/align][align=left]

[C#] 純文本查看 複制代碼

?

1234 // Update is called once per frame void Update () { }}

我們移除Update方法因爲我們不需要它:

[C#] 純文本查看 複制代碼

?

123456789using UnityEngine;using System.Collections;public class Monster : MonoBehaviour { // Use this for initialization void Start () { }}

我們用(yòng)Start函數來(lái)找到場(chǎng)景中的(de)城(chéng)堡遊戲主體,然後使用(yòng)怪獸的(de)導航網格代理(lǐ)來(lái)移動它:

[C#] 純文本查看 複制代碼

?

123456// Use this for initializationvoid Start () { // Navigate to Castle GameObject castle = GameObject.Find("Castle"); if (castle) GetComponent().destination = castle.transform.position;}

像這(zhè)樣簡單。

現在我們想要怪獸走近城(chéng)堡的(de)時(shí)候就減少城(chéng)堡的(de)健康值。我們怪獸的(de)碰撞器有IsTrigger可(kě)用(yòng),意味著(zhe)Unity自動通(tōng)知我們OnTriggerEnter函數中有多(duō)種碰撞器。我們所能做(zuò)的(de)是找出我們碰撞的(de)是不是城(chéng)堡,然後減少它的(de)健康柱:

[C#] 純文本查看 複制代碼

?

12345void OnTriggerEnter(Collider co) { // If castle then deal Damage if (co.name == "Castle") { co.GetComponentInChildren().decrease(); }}

當它處理(lǐ)完城(chéng)堡的(de)傷害值後就不再需要怪獸了(le),然後我們來(lái)摧毀怪獸:

[C#] 純文本查看 複制代碼

?

123456void OnTriggerEnter(Collider co) { // If castle then deal Damage, destroy self if (co.name == "Castle") { co.GetComponentInChildren().decrease(); Destroy(gameObject); }}

這(zhè)是我們的(de)怪獸腳本,Unity使得(de)我們的(de)生活更簡單。

注意,别忘了(le)保存腳本。

怪獸預設

現在從開始我們在遊戲中不需要怪獸了(le)。相反我們想要保存它爲預設以***于我們可(kě)以導入它到遊戲中,在我們想的(de)任何時(shí)候。

我們所能做(zuò)的(de)是創建一個(gè)預設,從Hierarchy中拖動我們的(de)怪獸到新的(de)項目區(qū)域的(de)預設文件夾中:

Unity 寶塔對(duì)戰教程

現在我們任何時(shí)間就可(kě)以導入它到場(chǎng)景中,我們可(kě)以從項目區(qū)域中拖它到場(chǎng)景或者在腳本中使用(yòng)實例化(huà)(Instatiate)函數(我們馬上就做(zuò))。

因爲我們現在有預設,我們在Hierarchy中右擊怪獸并選擇删除(Delete)。

産生器

好了(le),我們創建一個(gè)産生器每幾秒就導入新的(de)怪獸到遊戲中。我們從頂部菜單選擇GameObject->CreateEmpty開始。我們重新命名爲産生器(Spawn)并放置它到迷宮入口處:

Unity 寶塔對(duì)戰教程

我們看下(xià)Inspector并選擇一個(gè)Gizmo:

Unity 寶塔對(duì)戰教程

注意:A Gizmo是一個(gè)可(kě)視化(huà)指示器。能被空的(de)遊戲主體使用(yòng)以***于他(tā)們看起來(lái)容易點。Gizmo隻在場(chǎng)景視圖中出現,不在***後的(de)遊戲中。

現在産生器能被輕易看到:

Unity 寶塔對(duì)戰教程

我們選擇Add Component->New Scrupt,命名爲Spawn并選擇C#編程語言。我們移動它到我們的(de)項目區(qū)域腳本文件夾中并打開:

[C#] 純文本查看 複制代碼

?

0102030405060708091011121314using UnityEngine;using System.Collections;public class Spawn : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { }}

我們不需要Update方法,所以我們移除它:

[C#] 純文本查看 複制代碼

?

123456789using UnityEngine;using System.Collections;public class Spawn : MonoBehaviour { // Use this for initialization void Start () { }}

現在我們可(kě)以添加一個(gè)公共的(de)MonsterPrefab變量以***于我們能具體化(huà)可(kě)以産生的(de)怪獸:

[C#] 純文本查看 複制代碼

?

0102030405060708091011using UnityEngine;using System.Collections;public class Spawn : MonoBehaviour { // The Monster that should be spawned public GameObject monsterPrefab; // Use this for initialization void Start () { }}

我們爲interval添加另一個(gè)變量,用(yòng)來(lái)表示産生怪獸之間的(de)延遲:

[C#] 純文本查看 複制代碼

?

0102030405060708091011121314using UnityEngine;using System.Collections;public class Spawn : MonoBehaviour { // The Monster that should be spawned public GameObject monsterPrefab; // Spawn Delay in seconds public float interval = 3; // Use this for initialization void Start () { }}

現在我們能做(zuò)的(de)是創建一個(gè)函數,用(yòng)來(lái)産生一個(gè)新的(de)怪獸,然後用(yòng)InvokeRepeating每幾秒來(lái)調用(yòng)函數:

[C#] 純文本查看 複制代碼

?

010203040506070809101112131415161718using UnityEngine;using System.Collections;public class Spawn : MonoBehaviour { // The Monster that should be spawned public GameObject monsterPrefab; // Spawn Delay in seconds public float interval = 3; // Use this for initialization void Start() { InvokeRepeating("SpawnNext", interval, interval); } void SpawnNext() { Instantiate(monsterPrefab, transform.position, Quaternion.identity); }}

很容易。我們保存腳本并觀察Inspector,我們從項目區(qū)域中拖動我們的(de)怪獸預設到腳本的(de)怪獸預設槽:

Unity 寶塔對(duì)戰教程

如果我們點擊Play,然後我們現在看到一個(gè)新的(de)怪獸是怎麽每隔3秒産生的(de)。怪獸向著(zhe)城(chéng)堡前進:

Unity 寶塔對(duì)戰教程

子彈

我們創建一個(gè)簡單的(de)子彈預設,以***于之後我們創建一個(gè)寶塔。我們通(tōng)過頂部菜單選擇GameObject->3Dobject->Cube來(lái)開始。我們命名爲子彈,縮放它小點并使得(de)IsTrigger可(kě)用(yòng):

Unity 寶塔對(duì)戰教程

注意:我們使得(de)IsTrigger可(kě)用(yòng)以***于子彈能夠穿透牆并擊中怪獸。

我們畫(huà)一個(gè)簡單的(de)8*8像素的(de)紋理(lǐ),我們用(yòng)來(lái)賦予子彈:

tex_bullet.png

注意:右擊鏈接,選擇Save As并保存到項目的(de)Assets/Textures文件夾

我們用(yòng)下(xià)面的(de)導入設置:

Unity 寶塔對(duì)戰教程

然後我們從項目區(qū)域中拖動紋理(lǐ)到我們的(de)子彈:

Unity 寶塔對(duì)戰教程

好了(le),子彈假設飛(fēi)過整個(gè)遊戲場(chǎng)景直到它擊中怪獸。正如我們所知,物(wù)理(lǐ)世界中的(de)事想移動需要一個(gè)剛體。我們選擇Add Component->Physics->Rigidbody在Inspector并設置下(xià)面的(de)屬性:

現在我們用(yòng)剛體來(lái)飛(fēi)向怪獸。我們選擇Add Component->NewScript在Inspector中,命名爲Bullet并選擇C#。我們移動腳本到腳本文件夾并打開:

[C#] 純文本查看 複制代碼

?

0102030405060708091011121314using UnityEngine;using System.Collections;public class Bullet : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { }}

我們不需要Start或者Update函數。相反,我們用(yòng)FixedUpdate,有點像Update,在相同的(de)間隔期内被調用(yòng),那裏是做(zuò)了(le)物(wù)理(lǐ)計算(suàn)的(de)。因爲子彈是物(wù)理(lǐ)世界的(de)一部分(fēn),我們使用(yòng)FixedUpdate:

[C#] 純文本查看 複制代碼

?

12345678using UnityEngine;using System.Collections;public class Bullet : MonoBehaviour { void FixedUpdate() { }}

子彈需要一個(gè)目标來(lái)擊中,以及一個(gè)速度變量:

[C#] 純文本查看 複制代碼

?

01020304050607080910111213using UnityEngine;using System.Collections;public class Bullet : MonoBehaviour { // Speed public float speed = 10; // Target (set by Tower) public Transform target; void FixedUpdate() { }}

注意:目标是子彈想擊中的(de)怪獸。寶塔發射子彈時(shí),目标會被設置好。

我們來(lái)修改下(xià)我們的(de)FixedUpdate函數使得(de)子彈能夠飛(fēi)向目标。我們簡單使用(yòng)剛體的(de)速度屬性。速度被定義爲移動方向乘以速度,我們這(zhè)麽做(zuò):

[C#] 純文本查看 複制代碼

?

1234void FixedUpdate() { // Fly towards the target Vector3 dir = target.position - transform.position; GetComponent().velocity = dir.normalized * speed;}

注意:我們通(tōng)過從怪獸的(de)位置抽取現在的(de)位置來(lái)計算(suàn)方位,這(zhè)是基本的(de)向量數學。然後我們誠意速度的(de)方向。我們用(yòng)向量化(huà)的(de)方向來(lái)确保有一個(gè)長(cháng)度。

就這(zhè)麽簡單。現在可(kě)能會發生怪獸跑進城(chéng)堡然後死亡,當子彈嘗試到達它的(de)時(shí)候,我們來(lái)準備:

[C#] 純文本查看 複制代碼

?

01020304050607080910void FixedUpdate() { // Still has a Target? if (target) { // Fly towards the target Vector3 dir = target.position - transform.position; GetComponent().velocity = dir.normalized * speed; } else { // Otherwise destroy self Destroy(gameObject); }}

好極了(le),還(hái)有一件事需要做(zuò)。我們想讓子彈碰到怪物(wù)的(de)時(shí)候對(duì)怪獸形成傷害。子彈對(duì)怪獸形成傷害後會自行消失。我們僅僅用(yòng)unity的(de)OnTriggerEnter函數就知道子彈什(shén)麽時(shí)候會遇到怪獸:

[C#] 純文本查看 複制代碼

?

123456void OnTriggerEnter(Collider co) { Health health = co.GetComponentInChildren(); if (health) { health.decrease(); Destroy(gameObject); }}

這(zhè)是我們的(de)子彈。但是我們從開始确實不需要在場(chǎng)景中讓它***時(shí)間出現,我們從Hierarchy拖它到預設文件夾在我們的(de)項目區(qū)域中:

Unity 寶塔對(duì)戰教程

然後我們從Hierarchy删除它,因爲我們還(hái)不需要它。

寶塔

我們已經創建了(le)很多(duō)Buildplaces,我們可(kě)以往上放寶塔,是時(shí)候來(lái)創建一個(gè)寶塔。

我們将從頂部菜單通(tōng)過選擇GameObject->3DObject->Cube來(lái)開始。我們重命名爲寶塔(Tower),縮放它小點兒(ér)并旋轉它,爲了(le)更好看:

Unity 寶塔對(duì)戰教程

我們爲我們的(de)寶塔用(yòng)16*16像素的(de)紋理(lǐ):

注意:右擊圖像,選擇另存爲,并保存它到項目的(de)Assets/Textires文件夾。

現在是導入設置:

Unity 寶塔對(duì)戰教程

我們從項目區(qū)域拖動紋理(lǐ)到寶塔上,現在是它看起來(lái)的(de)樣子:

Unity 寶塔對(duì)戰教程

我們的(de)寶塔模型已經完成了(le)。現在我們不得(de)不添加邏輯來(lái)發現靠近寶塔的(de)怪獸,然後向它發射子彈。有許多(duō)不同的(de)方式來(lái)完成。***明(míng)顯的(de)方式是寫個(gè)腳本來(lái)發現所有的(de)怪獸然後向***近的(de)那個(gè)怪獸進行射擊。這(zhè)個(gè)運行得(de)很好,但運算(suàn)可(kě)能會很消耗很多(duō)性能。

在寶塔周圍添加一個(gè)大(dà)的(de)球形觸發器很聰明(míng)并用(yòng)Unity的(de)OnTriggerEnter函數。不論什(shén)麽時(shí)候怪獸進入寶塔的(de)‘意識’區(qū)域,Unity都會自動通(tōng)知我們。

我們首先移除寶塔的(de)盒子碰撞器:

Unity 寶塔對(duì)戰教程

然後我們選擇AddComponent->Physics->Sphere Collider并賦予下(xià)面的(de)屬性:

Unity 寶塔對(duì)戰教程

如果我們看場(chǎng)景,我們看到了(le)球。這(zhè)是寶塔看到的(de)區(qū)域并攻擊怪獸:

Unity 寶塔對(duì)戰教程

我們需要腳本來(lái)實行寶塔攻擊。我們選擇Add Component->NewScript,命名爲寶塔并選擇C#作爲編程語言。我們移動腳本到腳本文件夾并打開它:

[C#] 純文本查看 複制代碼

?

0102030405060708091011121314using UnityEngine;using System.Collections;public class Tower : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { }}

我們不需要Start函數,我們移除它:

[C#] 純文本查看 複制代碼

?

123456789using UnityEngine;using System.Collections;public class Tower : MonoBehaviour { // Update is called once per frame void Update () { }}

我們添加一個(gè)公共的(de)BulletPrefab變量具體定義哪個(gè)子彈預設可(kě)以用(yòng):

[C#] 純文本查看 複制代碼

?

01020304050607080910111213using UnityEngine;using System.Collections;public class Tower : MonoBehaviour { // The Bullet public GameObject bulletPrefab; // Update is called once per frame[mw_shl_code=csharp,true]void OnTriggerEnter(Collider co) { // Was it a Monster? Then Shoot it if (co.GetComponent()) { GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity); g.GetComponent().target = co.transform; }}

void Update () {

}

}

[/mw_shl_code]

現在我們用(yòng)OnTriggerEnter函數并發現是否進入到觸發器的(de)是怪獸,在這(zhè)個(gè)例子中我們對(duì)它發射子彈:

[C#] 純文本查看 複制代碼

?

123456void OnTriggerEnter(Collider co) { // Was it a Monster? Then Shoot it if (co.GetComponent()) { GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity); g.GetComponent().target = co.transform; }}

注意:我們用(yòng)GetComponent來(lái)發現進入觸發器的(de)是否是怪獸。如果這(zhè)個(gè)例子中我們用(yòng)實例來(lái)導入子彈到遊戲世界中,在寶塔的(de)現在的(de)位置及默認的(de)選擇(Quaternion,identity).畢竟我們通(tōng)過了(le)子彈組件并設置目标爲怪獸。

我們用(yòng)我們的(de)Update功能來(lái)添加一個(gè)簡單的(de)選擇給我們的(de)寶塔,這(zhè)樣看起來(lái)更好點:

[C#] 純文本查看 複制代碼

?

010203040506070809101112131415161718192021using UnityEngine;using System.Collections;public class Tower : MonoBehaviour { // The Bullet public GameObject bulletPrefab; // Rotation Speed public float rotationSpeed = 35; void Update() { transform.Rotate(Vector3.up * Time.deltaTime * rotationSpeed, Space.World); } void OnTriggerEnter(Collider co) { // Was it a Monster? Then Shoot it if (co.GetComponent()) { GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity); g.GetComponent().target = co.transform; } }}

我們的(de)寶塔旋轉在遊戲中看起來(lái)是這(zhè)樣的(de):

Unity 寶塔對(duì)戰教程

别忘記從項目區(qū)域的(de)拖子彈預設到寶塔的(de)子彈預設槽:

Unity 寶塔對(duì)戰教程

有個(gè)小修改我們一會兒(ér)做(zuò)。寶塔有一個(gè)漂亮的(de)大(dà)的(de)球形碰撞器環繞著(zhe)它。這(zhè)個(gè)碰撞器重疊一個(gè)Buildplace's 碰撞器,阻止OnMouseUpAsButton函數被調用(yòng)。我們所有能做(zuò)的(de)使它準确運行來(lái)告訴Unity忽略寶塔的(de)碰撞器當鼠标點擊的(de)時(shí)候。我們通(tōng)過選擇Ignore Raycast 層來(lái)做(zuò)這(zhè)個(gè):

現在我們通(tōng)過從Hierarchy拖動寶塔到我們的(de)預設文件夾來(lái)創建預設:

Unity 寶塔對(duì)戰教程

然後我們從Hierarchy删除它:

我們在Hierarhcy中選擇所有的(de)Buildplaces,看下(xià)檢查器并拖動寶塔預設到寶塔預設槽:

Unity 寶塔對(duì)戰教程

如果我們按下(xià)Play然後我們現在通(tōng)過點擊Buildplaces來(lái)創建寶塔。寶塔甚***會攻擊怪獸:

Unity 寶塔對(duì)戰教程

意味著(zhe)我們的(de)unity寶塔對(duì)抗遊戲完成了(le):

Unity 寶塔對(duì)戰教程

總結

這(zhè)是我們的(de)很長(cháng)的(de)Unity寶塔對(duì)抗教程。通(tōng)常,現在是讀者的(de)遊戲時(shí)間,有多(duō)種事情可(kě)以被添加:

分(fēn)數

***

不同怪獸

不同寶塔

不同子彈

不同水(shuǐ)平

背景音(yīn)樂(yuè)

帶動畫(huà)的(de)更好的(de)3D模型

菜單

存檔

以及更多(duō)

下(xià)載源碼及項目文件

Unity寶塔對(duì)抗教程的(de)源碼及項目的(de)文件能夠被下(xià)載。

原文鏈接:https://noobtuts.com/unity/tower-defense-game

發表評論

發表評論:

17601037727 1280857492