1. 程式人生 > >Unity3D案例太空射擊(Space Shooter)流程介紹與程式碼分析(中)

Unity3D案例太空射擊(Space Shooter)流程介紹與程式碼分析(中)

(上)部分主要介紹了素材的新增以及基本的移動與涉及功能,這部分關注事件的實現(如碰撞檢測)。 傳送門: 太空射擊(Space Shooter)流程介紹與程式碼分析(中) 6.邊界的設定 在上述過程中,若一直髮射子彈,在Hierarchy中會一直出現子彈的程序,造成不必要的記憶體開銷。因此我們需要設定一個區域,用以檢測子彈是否出了邊界並將出邊界的子彈刪除。 為了實現邊界的設定,我們採用gameObject中的Cube進行邊界模擬,新建一個Cube,將Cube的Size設定成與背景相同的大小,並將Position參照Background進行設定。
之後,為邊界新建一個指令碼,用以銷燬邊界外的子彈,程式碼如下
using UnityEngine;
using System.Collections;
public class DestroyByBoundary : MonoBehaviour {
void OnTriggerExit(Collider other)
    {
        Destroy (other.gameObject);
    }
}
即可達成目標。 7.新增隕石 隕石的新增與子彈類似,新建一個gameObject(命名為Asteriod)再將model中的隕石拖入Asteriod,對Asteriod新增rigidbody和Capsule Collider
新增完畢後,為了使隕石效果逼真,加入旋轉的功能,新建一個Script實現該功能 輸入
using UnityEngine;
using System.Collections;
public class RandmRotation : MonoBehaviour {
    public float tumble = 5f;
    // Use this for initialization
    void Start () {
        rigidbody.angularVelocity = Random.insideUnitSphere * tumble; //隕石的旋轉是隨機的
    }
    
}
即可完成隕石的旋轉操作。隕石的運動可以參照子彈的運動指令碼,將速度設定為負值即可。
同理,我們可以多設定幾組隕石,在model中可見,方法同上。建立完畢後,將3個隕石模型放入Prefabs中。
8.子彈與隕石碰撞 為隕石建立一個指令碼 輸入
using UnityEngine;
using System.Collections;
public class DestroyByCotact : MonoBehaviour {
    void OnTriggerEnter (Collider other)
    {
        Destroy (other.gameObject);
        Destroy (this.gameObject);
    }
}
即可 但上述程式碼存在問題,即隕石已經在Boundary中,在產生隕石的瞬間就能觸發OnTriggerEnter,因此直接就被銷燬。因此我們需要設定不同的Boundary以解決以上問題。
並將程式碼修改為
        if (other.gameObject.tag == "Boundary")     //若隕石在邊界之中,什麼也不做。
        {
            return;
        }
即可,此時子彈就可正常與隕石進行碰撞並銷燬。需保證子彈和隕石在同一個2D平面上 為了保證遊戲反饋,我們需要新增爆炸效果讓玩家有一個直觀的視覺體驗。因此對程式碼進行修改如下。
using UnityEngine;
using System.Collections;
public class DestroyByCotact : MonoBehaviour {
    
    public GameObject explosion;
    public GameObject playerExplosion;
    
    void OnTriggerEnter (Collider other)    //只要打到了隕石,執行如下操作
    {
        if (other.gameObject.tag == "Boundary")     //如果隕石碰到邊界,什麼也不做
        {
            return;
        }
        if (other.gameObject.tag == "Player")     //如果碰撞的是玩家,銷燬飛機
        {
            Instantiate (playerExplosion, this.transform.position, this.transform.rotation);
        }
        Destroy (other.gameObject);
        Destroy (this.gameObject);
        Instantiate (explosion, this.transform.position, this.transform.rotation);    //銷燬隕石
    }
}
即可,注意要將playership的Tag改成別的,方便指令碼中判斷。
將兩個爆炸素材帶入即可實現
9.隨機建立隕石 開啟GameController,將控制程式碼如下寫入,實現隨機產生隕石的效果。
using UnityEngine;
using System.Collections;
public class GameController : MonoBehaviour {
    public Vector3 spawnValue;    
    public GameObject[] hazards;    
    // Use this for initialization
    void Start () {
        Debug.Log("Spaceshooter begins!!!");
    }
    
    // Update is called once per frame
    void Update () {
        if(Random.value<0.1)    //Random.value隨機產生0~1的數,小於0.1表示十分之一的概率出現隕石
        Spawn ();
    }
    void Spawn()
    {
        GameObject o = hazards [Random.Range (0, hazards.Length)];    //從3個隕石model中任選一個
        Vector3 p = new Vector3 (Random.Range (-10, -2), spawnValue.y, spawnValue.z);//隕石隨機出現的區域要在邊界內,用Random.Range (-10, -2)限定
        Quaternion q = Quaternion.identity;  //i.e (0,0,0)
        Instantiate (o, p, q);
    }
}
即可,並將3種隕石放入hazards陣列內,即可實現。
但此時的隕石會互相發生碰撞併發生爆炸,應改進。 10.建立一波又一波的隕石 這部分內容主要是在程式碼中進行修改,直接上程式碼
using UnityEngine;
using System.Collections;
public class GameController : MonoBehaviour {
    public Vector3 spawnValue;    
    public GameObject[] Hazards;    
    public int numPerWave  = 10;
    public float gameStartTime = 2f;    //遊戲開始的等待時間
    public float waitTime = 1f;    //每個隕石出現間隔
    public float waveTime = 4f;    //每一波的間隔
    // Use this for initialization
    void Start () {
        Debug.Log("Spaceshooter begins!!!");
        StartCoroutine (SpawnWave ());
    }
    
    // Update is called once per frame
    void Update () {
//        if(Random.value<0.1)
//        Spawn ();
    }
    IEnumerator SpawnWave()
    {
        yield return new WaitForSeconds(gameStartTime);
        while (true)    //無限迴圈
        {
            for (int i=0; i<10; i++)    //for迴圈實現每一秒出一個,10個為一波
            {
                Spawn ();
                yield return new WaitForSeconds (waitTime);
            }
            yield return new WaitForSeconds(waveTime);    //出完一波後的等待
        }
    }
    void Spawn()
    {
        GameObject o = Hazards [Random.Range (0, Hazards.Length)];   
        Vector3 p = new Vector3 (Random.Range (-10, -2), spawnValue.y, spawnValue.z);
        Quaternion q = Quaternion.identity;  //i.e (0,0,0)
        Instantiate (o, p, q);
    }
}
即可 至此,基本功能已實現,為了提高遊戲的即時反饋,我們需要對遊戲進行完善,在(下)中進行介紹。