Unity 寶塔對戰教程
這個教程詳細介紹了如何在unity中製作一個漂亮的小的寶塔對戰遊戲。我們會一步步介紹使得每個人都可以理解。
序言
教程中我們會用完全獨一無二的圖像風格來創建一個小的三維寶塔對戰遊戲。這個遊戲很容易做,不需要任何三維建模技巧,沒有動畫,且沒有任何複雜的。很簡單,我們所需要的是90行代碼。
必要條件
知識
我們的教程不需要任何特殊的技巧。如果你之前了解unity並聽過Gameobjects(遊戲主體),Prefabs(預設)以及轉變,然後你就可以準備開始了。如果你沒有,不用太擔心。
去閱讀我們簡單的教程比如Unity2D乒乓球遊戲來學會使用這個引擎。
不用擔心,沒有恐怖的數學!
Unity 版本
我們的寶塔對戰遊戲是用Unity 5.3.1f1製作完成。新的版本應該可以,老的版本有的可以,有的不行。
Advertisements
我們不需要任何高級的特效,因此Unity的免費版本就可以了
遊戲機制
對於那些從來沒聽過寶塔對戰的人,這兒有些基本常識:
怪獸每幾秒孵化的地方是個點
怪獸跑遍整個世界向著它們想摧毀的城堡
玩家可以建立城堡來攻擊怪獸
另外,我們用Buildplaces.Buildplaces是在地圖上預先設置好的地方,那裡玩家可以建立寶塔。我們會用到它們。因為它會使得我們更容易活下來(作為對比,在地圖上到處可以建立寶塔)
藝術風格
我們有兩個操作:我們可以找現實主義的東西,會耗費幾百個高質量的3D模型,紋理和著色器,或者我們可以找些簡單但獨一無二的東西。
我們的格言是跟我談談,比如我很厲害!因此我們不用深入到CAD工具的世界里來創建現實主義的3D模型。相反,我們會用到一個完全抽象的風格,會省去我們的許多工作,但看起來很有趣。我們會使用Unity的原件(立方體,球形,圓柱體,...)與僅有的一些顏色結合(大部分是綠色,黃色和灰色)。
Advertisements
這種藝術風格的好處是每個人都可以在少於一個小時的時間內創建它沒有任何3D建模或動畫知識。
項目建立
我們命名為towerdefense,選擇任意位置比如C:\,選擇3D並點擊創建項目:
如果我在Hierarchy中選擇Main Camera,然後我們可以設置背景色為黑色,調整位置和旋轉如下圖所示:
注意,這會使照相機以45度角向下俯視整個遊戲場景。
燈光
我們為遊戲添加些燈光,以至於場景不至於太黑暗。我們通過選擇GameObject->light->Directional Light來添加光源在頂部菜單中。我們可以用下面的設置來確保燈光在我們的場景中處於一個更好的角度:
注意:我們基本可以用任何我們想要的設置,但上面那個看著比較好。
地面
我們需要某種地面使得怪獸能夠行走。我們通過從頂部菜單來選擇GameObject->3D Object->Plane來添加平面。我們命名為Ground並在Inspector中設置為如圖所示的位置(Position)和大小(Scale).
注意,這個大小是最合適的大小,適合於所有的Buildplaces和城堡.
我們打開我們選擇的繪畫工具並創建一個小的有基本綠色色調的40*40px的紋理。通過用基本色來填充來創建你自己的紋理,然後用稍微明亮或暗沉的綠色調來繪製一些隨意的線條。這是我們得到的
注意:右擊這個圖片,選擇Save As...,導航到項目的Assets文件夾並保存它到新的紋理文件夾。
現在我們可以從項目區域的紋理文件夾內拖動紋理到地面(Ground):
如果我們現在靠近看地面,我們可以看到紋理看起來是多麼光滑
對大多數遊戲來說是好的,但對我們的寶塔對戰教程,我們想紋理看起來像素化來獲得一個更獨一無二的風格。我們在Project Area中選擇紋理並在Inspector中改變Import Settings如下圖所示:
現在看起來完全像素化了:
注意:我們在遊戲中會對所有的紋理使用這個風格。
地點
立方體地點
好了,我們需要一些地方用來給玩家建立寶塔(與其在整個場景中到處建造它,那樣會更複雜)。我們會通過創建一個地點來開始然後複製它幾個以至於我們能用地點來設計一些怪獸行走的迷宮。
我們選擇GameObject->3D Object->立方體從頂部菜單。我們放置它於(-14,0.5,-14)並命名為Buildplace:
注意:x,z坐標應該是四捨五入為整數比如14(而不是13.99)。Y的位置是0.5,以至於立方體能準確待在地面上,而不是嵌入到地面中。
看起來場景是這樣的:
Buildplace的紋理
我們畫一個簡單的8*8像素的紋理,我們可以穿上它:
tex_buildplace.png
注意:右擊鏈接,選擇Save as...保存它到項目的assets/textures文件夾
我們用下面的導入設置:
畢竟我們可以從項目區域拖動它到Buildplace以至於紋理看起來更漂亮:
Buildplace 腳本
我們想在用戶點擊Buildplace的時候就建立寶塔。這種行為總是用腳本來繼承。我們通過在Inspector中選擇Add Component->New Script來創建新的腳本。我們命名為Buildplace並選擇CSharp作為語言:
現在我們的Buildplace有一個腳本:
我們在項目區域創建一個新的腳本文件夾並移動腳本到文件夾中,以至於看起來乾淨整潔:
然後我們雙擊項目區域里的腳本並打開:
[C#] 純文本查看 複製代碼
?
0102030405060708091011121314 | using 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#] 純文本查看 複製代碼
?
12345 | using UnityEngine; using System.Collections; public class Buildplace : MonoBehaviour { } |
我們將需要一些公共的變數來具體化將要建立的寶塔:
[C#] 純文本查看 複製代碼
?
1234567 | using UnityEngine; using System.Collections; public class Buildplace : MonoBehaviour { // The Tower that should be built public GameObject towerPrefab; } |
注意:因為towerPrefab變數是公共的,我們一會兒可以在Inspector中具體化它。
下一步是點擊Buildplace后,用Instantiate函數來建立寶塔。通常,Unity使得我們的生活更同意因為已經提供了OnMouseUpAsButton函數,我們可以用:
[C#] 純文本查看 複製代碼
?
01020304050607080910 | using UnityEngine; using System.Collections; public class Buildplace : MonoBehaviour { // The Tower that should be built public GameObject towerPrefab; void OnMouseUpAsButton() { // TODO build stuff... } } |
現在我們能做的就是在Buildplace上面建立Tower:
[C#] 純文本查看 複製代碼
?
1234 | void OnMouseUpAsButton() { // Build Tower above Buildplace GameObject g = (GameObject)Instantiate(towerPrefab); g.transform.position = transform.position + Vector3.up; } |
注意:首先我們通過使用Instantiate來導入towerPrefab到遊戲中。然後我們修改位置成為現在Buildplace's的位置往上移一個單位。
如果我們保存腳本並觀察Inspector,我們也可以看到TowerPrefab 槽,那兒我們可以拖動寶塔到裡面:
創建更多的Buildplaces
既然一個Buildplace已經完成,我們右擊Hierarchy並選擇Duplicate:
然後我們放置它到(-13,0.4,-14)以至於準確與之前那個相鄰:
我們重複這個過程幾次為了給怪獸創建行走的迷宮。我們在城堡頂部留一個空白的區域:
城堡
城堡立方體
對了,我們創建一個城堡以致於怪獸有可以攻擊的地方。我們通過從頂部菜單選擇GameObject->3D Object->Cube開始。我們命名為城堡(Castle),放置它到我們迷宮的空的區域並通過縮放,使它變大點:
城堡紋理
我們再創建一個簡單的16*16像素的紋理:
注意:右擊圖片,選擇Save As..並保存它到項目的Assets/Textures文件夾
這兒有我們城堡紋理的導入設置:
我們從項目區域中拖動紋理到城堡並收到一個很簡單但獨一無二的視角:
健康值條柱
好了,我們在城堡上添加健康值條柱。有許多種不同的方法來做,我們選個簡單的做。我們為城堡添加一個3D紋理,它包括文字比如『-』是1個健康值,『--』是2個健康值,『---』是3個健康值等等。
我們通過右擊Hierarchy並選擇創建空的並添加3D紋理到城堡:
然後我們重命名新的遊戲主體到健康柱並在Inspector選擇Add Component->Mesh->TextMesh;
我們放置它在城堡上方一個單位,然後修改TextMesh 組件來獲得更好的結果:
注意:Text屬性已經包含了7x'-',相當於7個健康值。其他屬性大部分被改變了,來改變字體大小和尖銳性。放置Arial到字體屬性很重要。我們通過點擊字體屬性右邊的小圈來做這個。然後Unity展現目前可用的字體列表,我們從列表中可以選擇一個。
場景看起來是這樣的:
很簡單。現在我們需要一個健康簡本準確得做三個事情:
通過數『-』來返回現在的健康值
通過移除『-』來減少現在的健康
一直使得TextMesh面對照相機
我們想TextMesh來面對照相機為了避免奇怪的角度比如這個:
對了,我們選擇Add Component->New Script,命名為Health並選擇CSharp。我們移動它到項目區域的腳本文件夾並打開它:
[C#] 純文本查看 複製代碼
?
12345678 | using UnityEngine; using System.Collections; public class Health : MonoBehaviour { // Use this for initialization void Start () { } |
[C#] 純文本查看 複製代碼
?
1234 | // Update is called once per frame void Update () { } } |
首先我們需要獲得TextMesh組件:
[C#] 純文本查看 複製代碼
?
0102030405060708091011121314 | using UnityEngine; using System.Collections; public class Health : MonoBehaviour { // The TextMesh Component TextMesh tm; // Use this for initialization void Start () { tm = GetComponent<TextMesh>(); } // Update is called once per frame void Update () {[/align][align=left]} |
現在我們用Update功能,使它一直面對計算機:
[C#] 純文本查看 複製代碼
?
0102030405060708091011121314151617 | using UnityEngine; using System.Collections; public class Health : MonoBehaviour { // The TextMesh Component TextMesh tm; // Use this for initialization void Start () { tm = GetComponent<TextMesh>(); } // Update is called once per frame void Update () { // Face the Camera transform.forward = Camera.main.transform.forward; } } |
注意:沒有複雜的數學。我們能做的是使得我們的遊戲主體進入準確的照相機對著的方位。
現在我們添加current()和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); } |
注意,這是唯一一件看著有點奇怪的事情。通常我們有些整型變數來表展現我們現在的健康值。相反,我們利用包含這些『-』的字元串的TextMesh的文字。我們自動摧毀健康柱的父對象(這個是城堡)直到健康值變為0。我們使得這些函數公共以致於其他腳本能用它們。
是的,我們遊戲最簡單的健康柱。好事是我們也能夠為怪獸用。
怪獸
我們為我們的遊戲添加怪獸。通常我們需要用CAD工具比如blender,maya或3dsmax來創建怪獸。但因為我們想把事情簡單化,我們會用Unity原件來創建看起來像怪獸的圓柱體。
我們從頂部菜單選擇GameObject->3D Object->Cube開始。我們命名為Monster並檢查碰撞器的Is Trigger 操作以至於 怪獸之後不會互相碰撞:
我們繪製很小的8*8的紋理來給它賦予顏色:
tex_monster.png
注意:右擊鏈接,選擇Save As..保存到項目的Assets/Textures文件夾
我們用下面的Import Settings來設置:
從項目區域(Project Area)中拖拽到怪獸上,看起來是這個樣子的:
詳情頁
我們在Hierarchy中右擊怪獸並選擇3D Object->Cube。我們命名新的立方體為Eye,放置它到立方體的左中心並使它變小以至於看起來像個眼睛。我們再檢查下IsTrigger:
這是場景中看起來的樣子:
我們為眼睛畫一個簡單的白色的紋理:
-tex_eye.png
注意:右擊鏈接並選擇Save As..並保存到項目的Assets/Textures文件夾。
我們用下面的導入設置(Import Settings):
然後拖拽它到我們的EyeGameObject上。
我們重複這個步驟製作另一個眼睛,像這樣:
像你所想的那樣為怪獸添加更多細節。我們簡單地添加兩隻腳:
怪獸物理
我們的怪獸已經有了一個碰撞器,使得它已經成為了物理世界。還有一件事需要添加。假設通過物理世界的每個東西需要有一個剛體賦予它。剛體擁有引力,速度和其他力使得物體移動。
我們首先選擇怪獸遊戲主體(不是眼睛也不是腳)來添加剛體,然後點擊AddComponent->Physics->Rigidbody 在Inspector中。我們使用下面的設置:
注意:我們使用默認設置。
路徑尋找
我們想要怪獸能夠通過迷宮並進入城堡。我們不得不做兩件事來實現它:
烘焙一個導航網格(來告訴Unity哪個區域是可走的)
添加導航網格代理給怪獸
我們告訴Unity那些部分是可走的來開始。好消息是Unity實際上自己繪製出來了。我們不得不做的事情是告訴Unity我們哪部分世界是靜態的(例如::絕不移動)
我們選擇地面(Ground)和所有的BuildPlaces在Hierarchy中然後使得檢查器中的Static(靜態) 屬性可用:
現在unity知道這些東西絕不能移動,因此會用它們來計算可移動的區域。
現在我們從頂部菜單選擇Window->Navigation並使用下面的屬性:
然後我們點擊底部的Bake按鈕。幾秒之後,我們能看到Unity怎麼計算場景中的可移動區域:
注意:最重要的部分是通過迷宮的路徑。Unity也認為Buildplaces是可移動的,但因為沒有為怪獸提供階梯來爬,所以沒關係的。
對了,我們現在再次選擇怪獸並點擊AddComponent->Navigation->Nav Mesh Agent.這個組件被所有的東西所需要,通過我們剛剛我們烘焙過的的導航網格。我們為我們的代理使用下面的設置:
注意:我們僅僅修改了移動的速度和大小使其適合我們的怪獸。如果你對設置還不滿意還可以修改。
既然我們的導航網格被烘焙並且怪獸有個導航網格代理,我們能做的就是使它移動到一個地方比如:
[C#] 純文本查看 複製代碼
?
GetComponent<NavMeshAgent>.destination = new Vector3(1, 2, 3); |
注意:當我們之後創建怪獸腳本的時候我們來做這個。
健康柱
我們添加一個健康柱到怪獸,以至於寶塔可以攻擊它。我們用準確相同的工作流,我們為我們城堡的健康柱用的,一些不同的設置使得它更小並變紅:
注意:我們改變Text屬性為4x"-"以至於怪獸僅能攻擊4個寶塔。
這個是怪獸的健康柱在場景中看起來的樣子:
怪獸腳本
好了正如前面我們提到的,我們想要創建怪獸腳本,使它移動到城堡然後當它到達城堡后就受到一點的傷害。
我們在Hierarchy中選擇怪獸,然後點擊Add Component->New Script,命名為怪獸(Monster)並選擇C#作為編程語言。我們移動它到腳本文件夾並打開:
[C#] 純文本查看 複製代碼
?
12345678 | using 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#] 純文本查看 複製代碼
?
123456789 | using UnityEngine; using System.Collections; public class Monster : MonoBehaviour { // Use this for initialization void Start () { } } |
我們用Start函數來找到場景中的城堡遊戲主體,然後使用怪獸的導航網格代理來移動它:
[C#] 純文本查看 複製代碼
?
123456 | // Use this for initialization void Start () { // Navigate to Castle GameObject castle = GameObject.Find( "Castle" ); if (castle) GetComponent<NavMeshAgent>().destination = castle.transform.position; } |
像這樣簡單。
現在我們想要怪獸走近城堡的時候就減少城堡的健康值。我們怪獸的碰撞器有IsTrigger可用,意味著Unity自動通知我們OnTriggerEnter函數中有多種碰撞器。我們所能做的是找出我們碰撞的是不是城堡,然後減少它的健康柱:
[C#] 純文本查看 複製代碼
?
12345 | void OnTriggerEnter(Collider co) { // If castle then deal Damage if (co.name == "Castle" ) { co.GetComponentInChildren<Health>().decrease(); } } |
當它處理完城堡的傷害值后就不再需要怪獸了,然後我們來摧毀怪獸:
[C#] 純文本查看 複製代碼
?
123456 | void OnTriggerEnter(Collider co) { // If castle then deal Damage, destroy self if (co.name == "Castle" ) { co.GetComponentInChildren<Health>().decrease(); Destroy(gameObject); } } |
這是我們的怪獸腳本,Unity使得我們的生活更簡單。
注意,別忘了保存腳本。
怪獸預設
現在從開始我們在遊戲中不需要怪獸了。相反我們想要保存它為預設以至於我們可以導入它到遊戲中,在我們想的任何時候。
我們所能做的是創建一個預設,從Hierarchy中拖動我們的怪獸到新的項目區域的預設文件夾中:
現在我們任何時間就可以導入它到場景中,我們可以從項目區域中拖它到場景或者在腳本中使用實例化(Instatiate)函數(我們馬上就做)。
因為我們現在有預設,我們在Hierarchy中右擊怪獸並選擇刪除(Delete)。
產生器
好了,我們創建一個產生器每幾秒就導入新的怪獸到遊戲中。我們從頂部菜單選擇GameObject->CreateEmpty開始。我們重新命名為產生器(Spawn)並放置它到迷宮入口處:
我們看下Inspector並選擇一個Gizmo:
注意:A Gizmo是一個可視化指示器。能被空的遊戲主體使用以至於他們看起來容易點。Gizmo只在場景視圖中出現,不在最後的遊戲中。
現在產生器能被輕易看到:
我們選擇Add Component->New Scrupt,命名為Spawn並選擇C#編程語言。我們移動它到我們的項目區域腳本文件夾中並打開:
[C#] 純文本查看 複製代碼
?
0102030405060708091011121314 | using UnityEngine; using System.Collections; public class Spawn : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } } |
我們不需要Update方法,所以我們移除它:
[C#] 純文本查看 複製代碼
?
123456789 | using UnityEngine; using System.Collections; public class Spawn : MonoBehaviour { // Use this for initialization void Start () { } } |
現在我們可以添加一個公共的MonsterPrefab變數以至於我們能具體化可以產生的怪獸:
[C#] 純文本查看 複製代碼
?
0102030405060708091011 | using UnityEngine; using System.Collections; public class Spawn : MonoBehaviour { // The Monster that should be spawned public GameObject monsterPrefab; // Use this for initialization void Start () { } } |
我們為interval添加另一個變數,用來表示產生怪獸之間的延遲:
[C#] 純文本查看 複製代碼
?
0102030405060708091011121314 | using 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每幾秒來調用函數:
[C#] 純文本查看 複製代碼
?
010203040506070809101112131415161718 | using 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,我們從項目區域中拖動我們的怪獸預設到腳本的怪獸預設槽:
如果我們點擊Play,然後我們現在看到一個新的怪獸是怎麼每隔3秒產生的。怪獸向著城堡前進:
子彈
我們創建一個簡單的子彈預設,以至於之後我們創建一個寶塔。我們通過頂部菜單選擇GameObject->3Dobject->Cube來開始。我們命名為子彈,縮放它小點並使得IsTrigger可用:
注意:我們使得IsTrigger可用以至於子彈能夠穿透牆並擊中怪獸。
我們畫一個簡單的8*8像素的紋理,我們用來賦予子彈:
tex_bullet.png
注意:右擊鏈接,選擇Save As並保存到項目的Assets/Textures文件夾
我們用下面的導入設置:
然後我們從項目區域中拖動紋理到我們的子彈:
好了,子彈假設飛過整個遊戲場景直到它擊中怪獸。正如我們所知,物理世界中的事想移動需要一個剛體。我們選擇Add Component->Physics->Rigidbody在Inspector並設置下面的屬性:
現在我們用剛體來飛向怪獸。我們選擇Add Component->NewScript在Inspector中,命名為Bullet並選擇C#。我們移動腳本到腳本文件夾並打開:
[C#] 純文本查看 複製代碼
?
0102030405060708091011121314 | using UnityEngine; using System.Collections; public class Bullet : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } } |
我們不需要Start或者Update函數。相反,我們用FixedUpdate,有點像Update,在相同的間隔期內被調用,那裡是做了物理計算的。因為子彈是物理世界的一部分,我們使用FixedUpdate:
[C#] 純文本查看 複製代碼
?
12345678 | using UnityEngine; using System.Collections; public class Bullet : MonoBehaviour { void FixedUpdate() { } } |
子彈需要一個目標來擊中,以及一個速度變數:
[C#] 純文本查看 複製代碼
?
01020304050607080910111213 | using UnityEngine; using System.Collections; public class Bullet : MonoBehaviour { // Speed public float speed = 10; // Target (set by Tower) public Transform target; void FixedUpdate() { } } |
注意:目標是子彈想擊中的怪獸。寶塔發射子彈時,目標會被設置好。
我們來修改下我們的FixedUpdate函數使得子彈能夠飛向目標。我們簡單使用剛體的速度屬性。速度被定義為移動方向乘以速度,我們這麼做:
[C#] 純文本查看 複製代碼
?
1234 | void FixedUpdate() { // Fly towards the target Vector3 dir = target.position - transform.position; GetComponent<Rigidbody>().velocity = dir.normalized * speed; } |
注意:我們通過從怪獸的位置抽取現在的位置來計算方位,這是基本的向量數學。然後我們誠意速度的方向。我們用向量化的方向來確保有一個長度。
就這麼簡單。現在可能會發生怪獸跑進城堡然後死亡,當子彈嘗試到達它的時候,我們來準備:
[C#] 純文本查看 複製代碼
?
01020304050607080910 | void FixedUpdate() { // Still has a Target? if (target) { // Fly towards the target Vector3 dir = target.position - transform.position; GetComponent<Rigidbody>().velocity = dir.normalized * speed; } else { // Otherwise destroy self Destroy(gameObject); } } |
好極了,還有一件事需要做。我們想讓子彈碰到怪物的時候對怪獸形成傷害。子彈對怪獸形成傷害後會自行消失。我們僅僅用unity的OnTriggerEnter函數就知道子彈什麼時候會遇到怪獸:
[C#] 純文本查看 複製代碼
?
123456 | void OnTriggerEnter(Collider co) { Health health = co.GetComponentInChildren<Health>(); if (health) { health.decrease(); Destroy(gameObject); } } |
這是我們的子彈。但是我們從開始確實不需要在場景中讓它第一時間出現,我們從Hierarchy拖它到預設文件夾在我們的項目區域中:
然後我們從Hierarchy刪除它,因為我們還不需要它。
寶塔
我們已經創建了很多Buildplaces,我們可以往上放寶塔,是時候來創建一個寶塔。
我們將從頂部菜單通過選擇GameObject->3DObject->Cube來開始。我們重命名為寶塔(Tower),縮放它小點兒並旋轉它,為了更好看:
我們為我們的寶塔用16*16像素的紋理:
注意:右擊圖像,選擇另存為,並保存它到項目的Assets/Textires文件夾。
現在是導入設置:
我們從項目區域拖動紋理到寶塔上,現在是它看起來的樣子:
我們的寶塔模型已經完成了。現在我們不得不添加邏輯來發現靠近寶塔的怪獸,然後向它發射子彈。有許多不同的方式來完成。最明顯的方式是寫個腳本來發現所有的怪獸然後向最近的那個怪獸進行射擊。這個運行得很好,但運算可能會很消耗很多性能。
在寶塔周圍添加一個大的球形觸發器很聰明並用Unity的OnTriggerEnter函數。不論什麼時候怪獸進入寶塔的『意識』區域,Unity都會自動通知我們。
我們首先移除寶塔的盒子碰撞器:
然後我們選擇AddComponent->Physics->Sphere Collider並賦予下面的屬性:
如果我們看場景,我們看到了球。這是寶塔看到的區域並攻擊怪獸:
我們需要腳本來實行寶塔攻擊。我們選擇Add Component->NewScript,命名為寶塔並選擇C#作為編程語言。我們移動腳本到腳本文件夾並打開它:
[C#] 純文本查看 複製代碼
?
0102030405060708091011121314 | using UnityEngine; using System.Collections; public class Tower : MonoBehaviour { // Use this for initialization void Start () { } // Update is called once per frame void Update () { } } |
我們不需要Start函數,我們移除它:
[C#] 純文本查看 複製代碼
?
123456789 | using UnityEngine; using System.Collections; public class Tower : MonoBehaviour { // Update is called once per frame void Update () { } } |
我們添加一個公共的BulletPrefab變數具體定義哪個子彈預設可以用:
[C#] 純文本查看 複製代碼
?
01020304050607080910111213 | using 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<Monster>()) { GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity); g.GetComponent<Bullet>().target = co.transform; } } |
void Update () {
}
}
[/mw_shl_code]
現在我們用OnTriggerEnter函數並發現是否進入到觸發器的是怪獸,在這個例子中我們對它發射子彈:
[C#] 純文本查看 複製代碼
?
123456 | void OnTriggerEnter(Collider co) { // Was it a Monster? Then Shoot it if (co.GetComponent<Monster>()) { GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity); g.GetComponent<Bullet>().target = co.transform; } } |
注意:我們用GetComponent來發現進入觸發器的是否是怪獸。如果這個例子中我們用實例來導入子彈到遊戲世界中,在寶塔的現在的位置及默認的選擇(Quaternion,identity).畢竟我們通過了子彈組件並設置目標為怪獸。
我們用我們的Update功能來添加一個簡單的選擇給我們的寶塔,這樣看起來更好點:
[C#] 純文本查看 複製代碼
?
010203040506070809101112131415161718192021 | using 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<Monster>()) { GameObject g = (GameObject)Instantiate(bulletPrefab, transform.position, Quaternion.identity); g.GetComponent<Bullet>().target = co.transform; } } } |
我們的寶塔旋轉在遊戲中看起來是這樣的:
別忘記從項目區域的拖子彈預設到寶塔的子彈預設槽:
有個小修改我們一會兒做。寶塔有一個漂亮的大的球形碰撞器環繞著它。這個碰撞器重疊一個Buildplace's 碰撞器,阻止OnMouseUpAsButton函數被調用。我們所有能做的使它準確運行來告訴Unity忽略寶塔的碰撞器當滑鼠點擊的時候。我們通過選擇Ignore Raycast 層來做這個:
現在我們通過從Hierarchy拖動寶塔到我們的預設文件夾來創建預設:
然後我們從Hierarchy刪除它:
我們在Hierarhcy中選擇所有的Buildplaces,看下檢查器並拖動寶塔預設到寶塔預設槽:
如果我們按下Play然後我們現在通過點擊Buildplaces來創建寶塔。寶塔甚至會攻擊怪獸:
意味著我們的unity寶塔對抗遊戲完成了:
總結
這是我們的很長的Unity寶塔對抗教程。通常,現在是讀者的遊戲時間,有多種事情可以被添加:
分數
金牌
不同怪獸
不同寶塔
不同子彈
不同水平
背景音樂
帶動畫的更好的3D模型
菜單
存檔
以及更多
下載源碼及項目文件
Unity寶塔對抗教程的源碼及項目的文件能夠被下載。
原文鏈接:https://noobtuts.com/unity/tower-defense-game