[Unity3D]Unity3D遊戲開發之飛機大戰專案講解
首先感謝大家對我部落格的關注,今天我想和大家分享的是一個飛機大戰的專案。這是一個比較綜合的專案,希望對大家學習Unity3D有所幫助,我會在文章最後給出專案程式碼。作為一個遊戲而言,遊戲策劃十分重要,所以在開始今天的文章之前,我們先來了解下這個專案的策劃。我們的玩家是一個飛機,玩家可以使用A、D、S、W四個鍵位來控制飛機位置,當按下空格鍵時,我方飛機可以向敵機發射炮彈,當敵機中彈後將減少生命值,當敵機生命值為0時,敵機將爆炸銷燬。在遊戲場景中只有一種從螢幕上方不斷向下飛行的敵機,當我方飛機與敵機碰撞後,雙方都將減少生命值。當我方生命值減少至0時,遊戲將結束。好了,瞭解完遊戲規則設定後,我們就可以開始今天的內容了。
一、遊戲場景
我們這裡在場景中新增GUIText物件來顯示玩家得分等基本資訊,指令碼定義如下:
using UnityEngine; using System.Collections; public class GameManager : MonoBehaviour { //玩家得分 private Transform Grade; //玩家生命 private Transform HP; //遊戲結束 private Transform Text; //玩家 private GameObject Player; void Start () { //初始化介面 Grade=transform.Find("Grade"); HP=transform.Find("HP"); Text=transform.Find("Text"); Text.guiText.enabled=false; //獲取玩家物件 Player=GameObject.Find("Player"); } void Update () { if(Player!=null) { //更新UI Grade.guiText.text="得分:"+Player.GetComponent<Player>().Grade.ToString(); HP.guiText.text="生命:"+Player.GetComponent<Player>().MaxHP.ToString(); } if(HP.guiText.text=="生命:0") { Text.guiText.enabled=true; //立即復活 if(Input.GetKey(KeyCode.Y)) { Application.LoadLevel("Main"); } //退出 if(Input.GetKey(KeyCode.N)) { Application.Quit(); } } } }
二、玩家飛機
玩家飛機的建立和背景的建立時相同的,這裡我們不再多說。玩家飛機需要完成移動、發射、碰撞的事件處理。為此我們編寫下面的指令碼:
using UnityEngine; using System.Collections; public class Player : MonoBehaviour { //飛機的移動速度 public float MoveSpeed; //飛機的最大生命值 public int MaxHP=100; //定義子彈物件 public GameObject Bullet; //定義子彈發射位置 private Transform BulletPosL; private Transform BulletPosR; [HideInInspector] public int Grade=0; void Start () { BulletPosL=this.transform.Find("BulletPosL"); BulletPosR=this.transform.Find("BulletPosR"); } void Update () { if(Input.GetKey(KeyCode.A)) { transform.Translate(Vector3.left*Time.deltaTime*(-MoveSpeed)); } if(Input.GetKey(KeyCode.D)) { transform.Translate(Vector3.left*Time.deltaTime* MoveSpeed ); } if(Input.GetKey(KeyCode.W)) { transform.Translate(Vector3.forward*Time.deltaTime*(-MoveSpeed)); } if(Input.GetKey(KeyCode.S)) { transform.Translate(Vector3.forward*Time.deltaTime*MoveSpeed); } //按下空格鍵,發射子彈 if(Input.GetKey(KeyCode.Space)) { Instantiate(Bullet,BulletPosL.transform.position,Quaternion.Euler(new Vector3(0,1,0))); Instantiate(Bullet,BulletPosR.transform.position,Quaternion.identity); } } #region 減血 public void Hit(int Value) { if(MaxHP>0) { MaxHP-=Value; }else { Destroy(this.gameObject); } } #endregion #region 增加分數 public void Add(int Value) { Grade+=Value; } #endregion }
在這段程式碼中,Bullet是我們的子彈物件,它從飛機的兩個子彈發射位置BulletPosL、BulletPosR發射,向螢幕上方按照一定的速度緩緩移動,當子彈與敵人碰撞時,子彈物件將銷燬,同時敵人生命值減少。Bullet物件對應於我們的一個Prefab。BulletPosL、BulletPosR對應于飛機上的兩個位置。如圖:
我們的子彈Bullet是一個綁定了指令碼的Capsule。它的程式碼定義如下:
using UnityEngine;
using System.Collections;
public class Bullet : MonoBehaviour {
//定義子彈的移動速度
public float MoveSpeed=10F;
//定義子彈的銷燬時間
public float DestroyTime=2.0F;
//定義子彈對敵人的傷害值
public int Damage=2;
//玩家飛機
private GameObject Player;
void Start()
{
Player=GameObject.Find("Player");
}
void Update ()
{
//移動子彈
transform.Translate(Vector3.up * MoveSpeed * Time.deltaTime);
}
//碰撞事件捕捉
void OnTriggerEnter(Collider mCollider)
{
if(mCollider.gameObject.tag=="Enemy")
{
//敵人減血
mCollider.gameObject.GetComponent<Enemy>().Hit(Damage);
//我方得分
Player.GetComponent<Player>().Add(1);
//銷燬子彈
Destroy(this.gameObject);
}
}
//當離開攝像機範圍時觸發銷燬事件
void OnBecameInvisible()
{
Destroy(this.gameObject);
}
}
三、敵人飛機
在我們的遊戲中共有三種敵機,我們先將它們製作成預設。然後通過敵機生成器不斷地生成敵機。如圖:
和子彈相反,我們希望敵機從螢幕上方以一定速度向下移動,當碰到玩家飛機或者子彈時,將減少生命值。為此,我們這樣定義敵機的指令碼:
using UnityEngine;
using System.Collections;
public class Enemy : MonoBehaviour {
//移動速度
public float MoveSpeed=1.5F;
//爆炸
public GameObject Explosion;
//最大生命值
public int MaxHP=100;
void Update ()
{
//移動飛機
transform.Translate(Vector3.forward*Time.deltaTime*MoveSpeed);
}
public void Hit(int Value)
{
//如血量不低於0,則敵人飛機掉血
if(MaxHP>0)
{
MaxHP-=Value;
}else
{
//產生爆炸效果
Instantiate(Explosion,transform.position,Quaternion.Euler(new Vector3(90,180,0)));
//銷燬敵機
Destroy(this.gameObject);
}
}
void OnTriggerEnter(Collider mCollider)
{
//如果與玩家飛機遭遇,則雙方減血
if(mCollider.gameObject.tag=="Player")
{
//敵機掉血
this.Hit(2);
//玩家飛機掉血
Transform mPlayer=mCollider.gameObject.transform.Find("Player");
mPlayer.GetComponent<Player>().Hit(2);
}
}
void OnBecameInvisible()
{
Destroy(this.gameObject);
}
}
接下來,我們通過敵機生成器來不斷地生成敵機。敵人生成器是我們預製在遊戲場景中的空遊戲體,它位於遊戲場景的頂部。我們將下面的指令碼繫結到遊戲生成器 上,使其可以不斷地生成敵人:using UnityEngine;
using System.Collections;
public class SpawnEnemy : MonoBehaviour {
//定義敵人速度
public float SpawnTime=1.0f;
//定義敵人物件陣列
public GameObject[] Enemys;
void Start ()
{
StartCoroutine("Spawn");
}
//通過迭代器生成敵人
IEnumerator Spawn()
{
//等待
yield return new WaitForSeconds(SpawnTime);
//克隆物件
Instantiate(Enemys[Random.Range(0,3)],new Vector3(transform.position.x * Random.Range(-1F,1F),
transform.position.y,-4),Quaternion.Euler(new Vector3(90,180,0)));
StartCoroutine("Spawn");
}
}
其中Enemys對應到我們的敵人預設,每隔一段時間,我們隨機地產生一種敵人,該敵人將從螢幕上方緩緩向下移動。四、碰撞檢測
在這個遊戲中,主要存在子彈與敵機的碰撞、玩家飛機與敵機的碰撞兩種形式。它們分別被定義在Bullet.cs和Enemy.cs兩個類檔案中。
//碰撞事件捕捉
void OnTriggerEnter(Collider mCollider)
{
if(mCollider.gameObject.tag=="Enemy")
{
//敵人減血
mCollider.gameObject.GetComponent<Enemy>().Hit(Damage);
//我方得分
Player.GetComponent<Player>().Add(1);
//銷燬子彈
Destroy(this.gameObject);
}
}
void OnTriggerEnter(Collider mCollider)
{
//如果與玩家飛機遭遇,則雙方減血
if(mCollider.gameObject.tag=="Player")
{
//敵機掉血
this.Hit(2);
//玩家飛機掉血
Transform mPlayer=mCollider.gameObject.transform.Find("Player");
mPlayer.GetComponent<Player>().Hit(2);
}
}
五、爆炸特效
當敵機被摧毀時,將顯示爆炸特效,我們這裡採用一組2D貼圖來實現爆炸特效,原理是改變貼圖的mainTextureScale和mainTextureOffset兩個屬性值。我們來一起看程式碼:
using UnityEngine;
using System.Collections;
public class Explosion : MonoBehaviour {
//動畫序列索引
private int index=0;
//聲音
private AudioSource mAudio;
void Start()
{
mAudio=GetComponent<AudioSource>();
}
void FixedUpdate ()
{
if(index<8)
{
this.renderer.sharedMaterial.mainTextureScale=new Vector2(1.0F/8,1);
this.renderer.sharedMaterial.mainTextureOffset=new Vector2(index * 1.0F/8,0);
index+=1;
}else
{
mAudio.Play();
Destroy(this.gameObject);
}
}
}
其中mAudio對應到一個AudioSource元件,我們在這裡指定一個爆炸的音效。同樣地,我們將爆炸製作成預設,該預設對應於Enemy.cs中的Explosion。好了,到這裡今天的 內容就講解完了,我們一起來看看最終的效果吧!
希望今天的內容大家能夠喜歡。學了這麼長時間的Unity3D,感慨還是挺多的,很多東西你不努力去做,是永遠做不好的,你不給自己壓力,你不會知道自己有多優秀。本專案原始碼可以從這裡下載。
每日箴言: 不管活到什麼歲數,總有太多思索、煩惱與迷惘。一個人如果失去這些,安於現狀,才是真正意義上的青春的完結。—— 渡邊淳一
喜歡我的部落格請記住我的名字:秦元培,我的部落格地址是blog.csdn.net/qinyuanpei
轉載請註明出處,本文作者:秦元培,本文出處:http://blog.csdn.net/qinyuanpei/article/details/25158323