傳送門
Unity官方實例教程 Space Shooter(一)
Unity官方實例教程 Space Shooter(二)
Unity官方實例教程 Space Shooter(三)
Unity官方實例教程 Space Shooter(四)
Unity官方實例教程 Space Shooter(五)
前言
在Unity官方實例教程 Space Shooter(三)中,我們學會了:
- 如何回收子彈
- 如何創建障礙物
- 如何實現子彈擊碎障礙的效果
- 如何實現飛船撞擊障礙的華麗爆炸效果
現在我們的游戲已經具備了基本的玩法了,但是我們的障礙還是太少了,玩家擊碎一個之后,就已經無所事事了,所以我們需要加大難度,來看看我們這一節會做哪些事情。
你將學到什么?
- 如何讓障礙向下移動對玩家造成威脅
- 如何隨機生成一個障礙
- 如何生成多個障礙
- 如何設置障礙生成的間隔
- 如何生成無盡波數的障礙
- 如何基于時間來回收GameObject
一、實現障礙向下移動
我們讓障礙能夠往下移動,這樣才能對我們的飛船造成一些威脅。不知道大家是否還記得當初我們讓子彈向前飛行的做法,有了這個東西,我們就能很快的讓障礙向下移動,首先我們給障礙添加之前我們創建過的Mover腳本,然后將speed變量設置為-5,運行一下游戲,看看障礙是不是向下移動了
很好,我們看到障礙已經向下移動了,飛船如果不躲避,也會被他撞毀,下面我們就要來生成更多的障礙了,首先我們來思考一下,要實現生成更多的障礙,我們應該做什么?
- 首先我們需要能夠自動生成一個障礙物
- 而且這個障礙能夠隨機出現在不同的位置,不然就太沒有挑戰了
我們先來看看如何隨機生成一個障礙
二、隨機生成障礙
首先,我們這些邏輯需要綁定在一個游戲控制器上,所以我們新建一個空的GameObject,命名為GameController,然后給GameController添加一個新的腳本,也命名為GameController(有點繞,希望大家耐心點),然后我們打開GameController腳本輸入以下代碼:
- 首先我們定義一個公共變量hazard,來設置生成的障礙對象
- 然后我們繼續定義一個公共變量spawnValue,它是一個Vector3的變量,用來設置障礙生成的位置,我們可以在編輯器中設置
- 接著我們在Start方法中調用SpawnWaves方法,因為很多我們自定義的方法,Unity都不會自動調用的,需要我們自己在合適的地方去調用
- 然后我們定義了SpawnWaves方法,我們來看看這個方法里面做了什么?
- 首先我們在方法里面定義了一個局部變量spawnPosition,這個變量是用來記錄障礙生成的位置,我們來看看如何對他進行賦值
- 我們通過new Vector3的方法來新建了一個Vector3,而它的xyz值,我們對它進行了分別的設置,x值是在我們設置的spawnValue的x的[-x, x]之間隨機,這樣才能保證我們的障礙每次生成在不同的位置上
- y和z我們直接調用spawnValue的y和z值,而spawnValue的y和z值是后面我們在編輯器里面進行設置,來確保障礙生成的位置在屏幕的上方
- 障礙的Position屬性搞定后,我們要看看它的Rotation屬性如何確定,Rotation屬性是一個Quaternion類型的變量,所以我們定義了一個spawnRotation的變量,用來記錄障礙的Rotation屬性,在這里我們不需要讓障礙一開始帶著任何的旋轉,所以我們直接賦值Quaternion.identity
- 到現在,我們確定了障礙的對象hazard,障礙的Position,障礙的Rotation,我們便可以使用Instantiate方法生成一個障礙實例了
寫完代碼,保存一下,回到Unity編輯器,我們還需要做兩件事情:
- 設置hazard
- 設置spawnValue
首先我們來看看如何設置hazard,hazard我們需要的其實就是我們的障礙物,但是現在障礙物還只是我們場景中的一個GameObject,為了方便使用,我們需要將它做成一個Prefab,我們首先進入到Assets->Prefabs文件下面,然后將Asteroid拖入到文件夾下面,這樣我們的Prefab就做好了
然后我們在選中GameController,將Asteroid的Prefab拖入到hazard中
這樣hazard我們就設置好了,下面我們來看看如何設置spawnValue,首先我們得知道spawnValue是用來確定障礙生成的位置的,由于我們游戲是頂視圖,所以y值我們不會變化,直接設置為0,然后z值代表障礙在屏幕中的垂直位置,我們肯定希望障礙一開始從屏幕最上方掉下來,所以我們通過測量得知z值可以設置為16,而最后的x值代表障礙在屏幕中的水平位置,同時我們在代碼中通過隨機函數來確保障礙的x值在一定范圍內隨機,所以這個范圍就是我們屏幕邊界,通過測量,我們得到x的值為6,做好這些設置后,我們便可運行游戲來進行測試了,如無意外,我們每次運行游戲,障礙生成的位置都是隨機的
三、讓障礙來得更猛烈一些
現在我們可以隨機生成障礙了,但是生成的障礙還是只有1個,這樣太沒有挑戰性了,所以下面我們讓障礙每次生成的數量變得多一點,那怎么讓障礙生成數量邊多一點了,聰明的朋友可能想到了,我們可以多調用幾次生成障礙的方法就可以了,比如像下面這樣:
我們運行一下游戲,發現這樣確實能夠起到效果,現在可以一次生成3個障礙了,但是這樣的寫法可不好,如果我們需要生成100個障礙呢?難道我們要寫100句SpawnWaves?這顯然是很笨的方法,所以我們在這里要用到循環函數來生成多個障礙
- 首先我們定義了一個公共變量hazardCount,用來設置每次生成的障礙的數量
- 然后我們修改了SpawnWaves方法,將生成的代碼放入了一個for循環里面,循環的次數就是我們的hazardCount
寫完代碼,保存一下,然后回到Unity編輯器,將hazardCount的數量設置為10,再運行游戲測試一下,便可以看到一次生成了10個障礙
現在的確一次可以生成多個障礙了,但是還是存在幾個問題:
- 障礙不是一個接一個的出現的
- 同時出現的障礙還會互相碰撞發生爆炸
所以我們需要讓障礙間隔生成
四、如何設置障礙生成的間隔
要讓障礙物一個個的生成,其實邏輯說起來很簡單,就是讓一障礙生成后,稍等一會,再生成第二個,依次類推,那我們來看看如何在代碼里面實現這個功能
- 首先我們定義了一個公共變量spawnWait,用來設置每個障礙生成的間隔時間
- 然后我們又定義了一個公共變量startWait,用來設置游戲開始生成障礙的準備時間,我們給予玩家一定準備時間
- 然后我們來看這里里面最重要的一個語句yield return new WaitForSeconds,這給方法就是讓代碼等待一定時間,這是個協同程序,可以讓游戲不暫停的同時,讓代碼暫停(關于協同程序這里大家不用太在意他的內容,只要理解我們這里通過這個代碼來實現讓代碼等待一定時間的效果就好了)
- 然后我們看一下,我們在方法最開始,使用yield return new WaitForSeconds語句,讓代碼等待startWait秒,然后再開始執行下面的代碼,這樣就實現了游戲開始給予玩家準備時間的功能
- 接著我們在每一次循環結束后,使用yield return new WaitForSeconds語句,讓代碼等待spawnWait秒,然后再開始執行下一次循環,這樣就實現了障礙生存間隔的效果
- 然后為了使用yield return new WaitForSeconds語句,我們還需要將SpawnWaves的返回值改為IEnumerator類型
- 最后調用SpawnWaves方法也需要修改為StartCoroutine (SpawnWaves ())
寫完代碼,保存一下,然后回到Unity編輯器,并且將startWait和spawnWait的時間都設置為1,運行游戲測試一下
到這里看上去越來越棒了,但是還是有問題,障礙落下10個之后,就不會再落下來了,這可不太好玩,我們能不能讓他一直落下呢?當然可以!
五、實現無限波數的障礙
要實現無限波數的障礙,我們需要用到一個新的循環語句——While循環,我們直接看代碼來說明
- 首先我們定義一個公共變量waveWait,用來設置每一波的間隔時間
- 然后我們使用一個While循環,這里我們將里面的判斷條件直接寫為true,讓它可以一直循環,然后將我們生成障礙的代碼放入While循環中
- 之后在每次循環結束是,我們使用yield return new WaitForSeconds語句,讓代碼等待waveWait秒
寫完代碼,保存一下,然后回到Unity編輯器,將waveWait的值設置為3,接著運行游戲測試一下,我們可以看到,現在障礙會不停的生成了
六、回收爆炸效果
也許有些細心的朋友已經發現了,我們在游戲中發生的爆炸效果,都會創建一個GameObject,隨著玩家擊碎障礙越多,爆炸效果的GameObject就會越多
這些效果越多,就會讓游戲的負擔越大,所以我們也需要及時的進行清理,那么怎么來清理呢?我們無法像清理子彈一樣,如果子彈飛出屏幕就將他清楚,因為爆炸效果是不會移動的,既然這樣,我們就只能通過時間來控制了,我們讓每個爆炸效果存在一定時間后就會自動清楚,就像給它綁上了一個定時炸彈一樣,時間一到就會爆炸,將其清楚掉,首先我們在Assets->Scripts文件夾下面新建一個名為DestroyByTime的腳本,然后輸入以下代碼:
- 首先我們定義一個公共變量lifeTime,來設置GameObject的存活時間,時間一到就會被銷毀
- 然后我們在Start方法中,調用Destroy方法來消除GameObject,第二個參數就是我們的lifeTime
寫完代碼,保存一下,然后回到Unity編輯器,找到我們的爆炸效果的Prefab,然后添加DestroyByTime腳本
腳本添加完成后,我們再將lifeTime的值設置為2,運行游戲測試一下,這次我們發現所有的爆炸效果,再生成2秒后就會自己消除了
下集預告
在下一集中,我們將會學到:
- 如何給游戲添加背景音樂
- 如何給游戲添加各種音效
- 如何給飛船擊碎障礙后進行計分
- 如何判斷游戲結束
- 如何重新開始游戲
- 如何發布游戲