2014年11月27日 星期四

【Unity】射擊遊戲系列(1/?) 玩家子彈射擊

這次來透過Unity寫射擊遊戲的相關功能,就從最基本的攻擊手段"子彈"開始吧,至於要寫到什麼階段,可能就看之後進度規劃的情況再決定,另外接續上一篇是使用Sprite,做出來會是2D射擊遊戲,這次的成品看這裡
在開始之前來看看經典的射擊遊戲"雷電",聚焦在玩家操控的飛機子彈上的話,可以列出幾點設計上要做的事:
shooting game
縱向射擊遊戲:雷電 google圖片搜尋
(1)子彈從操控角色位置產生,在離開畫面或碰撞到敵人後消失。
(2)子彈本身帶有攻擊力、移動速度等特性。
(3)另外操控角色可影響子彈生成間隔、生成數量和生成角度等等。
(在這裡使用Unity 2D功能,所以內容會和3D有些許的差異)

首先從子彈的生成開始,生成位置依通常情況設定在操控角色上,所以將以下腳本(BulletCreate.cs)加入至操控的角色。
using UnityEngine;
using System.Collections;

public class BulletCreate : MonoBehaviour {

    public GameObject Bullet;
    private GameObject BulletClone;

    private float time = 0;
    private float BulletInterval;
 
    void Start () {
        BulletInterval = 0.5f;////(1)
    }

    void Update () {
        time += Time.deltaTime;
        if (Input.GetKeyDown (KeyCode.Space) && time>BulletInterval)////(2)
        {
            Vector3 pos = transform.position;
            Quaternion rot = transform.rotation;
            BulletClone = (GameObject)Instantiate(Bullet, pos, rot);////(3)
            BulletClone.AddComponent("BulletState");////(4)
            time = 0;
        }
    }
}
(1)兩發子彈生成的間隔時間。
(2)再按下空白鍵且間隔時間合乎條件時,
(3)生成子彈並初始化位置和角度。
(4)在生成的子彈下加入以下腳本(BulletState.cs),含有子彈速度和攻擊力。
using UnityEngine;
using System.Collections;

public class BulletState : MonoBehaviour {

    static public int BulletAtk;
    private float BulletSpeed;
 
    void Start () {
        BulletSpeed = 0.25f;
        BulletAtk = 2;
    }

    void Update () {
        transform.Translate (0, BulletSpeed, 0);
    }
}
接著將子彈物件加入場景中攝影機拍不到的地方,子彈物件新增Tag名稱"Bullet",在子彈物件下加入Box Collider 2D和Rigidbody 2D並把Rigidbody 2D下的Is Kinematic打勾,最後將子彈物件加入到腳本(BulletCreate.cs)下的Bullet變數。
Unity shooting game

把子彈產生出來之後,在子彈超過畫面以及碰觸到敵方角色後要將子彈消除,否則產生的子彈數量會讓記憶體爆炸,在子彈的發射方向新增消除子彈用的牆以及敵方角色,在兩個物件下新增Box Collider 2D並把Is Trigger打勾。
Unity shooting game

在牆及敵方角色下新增以下腳本(BulletDestroy.cs)。
using UnityEngine;
using System.Collections;

public class NPCState : MonoBehaviour {

    private int HP = 5;

    void OnTriggerEnter2D(Collider2D collider){
        if (collider.tag == "Bullet") ////(1)
        {
            Destroy (collider.gameObject);
            HP -= BulletState.BulletAtk;////(2)
        }
    }

    void Update () {
        if (HP <= 0)////(3)
            Destroy (gameObject);
    }
}
(1)如果有物件觸發同時物件的tag的名稱為Bullet時,消除該物件。
(2)如果是敵方角色,需要再新增血量(HP),並在觸發的時候做扣寫的動作。
(3)將血量降至0以下的敵方角色消除。

文章最後提幾點需要注意的事:
在這裡是使用Sprite物件,所以不管是觸發(Is Trigger)、碰撞(Collider)和物理(Rigidbody)都是使用2D,另外雖然都是2D物件,但要產生正確的觸發,物件本身還是需要相同的Z值。
接著雖然與內文無關,Sprite物件前後關係可以透過Sprite下的Order in Layer值調整,值越大代表物件在越上層。

物件觸發和碰撞相關的細節是參考以下兩位:
http://home.gamer.com.tw/creationDetail.php?sn=2300960
http://aartrice-study.blogspot.tw/2013/12/unity3d-c_9.html

最後感謝素材的提供:
王國興亡記-ドラゴン、影の怪物 by そーいち
http://makapri.web.fc2.com/top.html
雲 by ぴぽや
http://piposozai.blog76.fc2.com/
草皮、花、草 by ドット絵世界
http://yms.main.jp/index.html
火球
http://www.stadiagames.com/willsworld/bestiary.html

沒有留言:

張貼留言

【自製小遊戲】水平思考猜謎(海龜湯)

遊戲連結 海龜湯的玩法是由出題者提出一個難以理解的事件,參與猜題者可以提出任何問題以試圖縮小範圍並找出事件背後真正的原因。但出題者僅能以「是」、「不是」或「沒有關係」來回答問題。 本遊戲蒐集各種論壇、平台的42個題目,提供給想玩海龜湯卻愁找不到題目的你們。 ...