iT邦幫忙

2017 iT 邦幫忙鐵人賽
DAY 17
0
自我挑戰組

我要和天一樣高!!!(Unity 2D手機小遊戲開發日誌)系列 第 17

Day 17: 子彈、敵人碰撞

(本篇文章網誌版:http://shineright.blogspot.tw/2016/12/day-17.html

完成裝備和敵人重生系統,終於可以來做遊戲的核心──子彈、敵人、玩家之間的碰撞了。

首先,把各物件間的碰撞結果列出來:

http://ithelp.ithome.com.tw/upload/images/20161217/20103149z5hL71KAJ0.png

主角的子彈有兩種,一種擊中便會消失,如皮卡耳、死亡之帽、竹蜻蜓、雷達,另一種擊中後仍可持續作用,如綠帽、爆炸頭、鐵頭功。

主角的子彈落打到敵人,會產生兩種動畫,分別為敵人的死亡動畫以及子彈的擊中動畫。我會把動畫另存於新的Prefab,並在兩者被Destroy時以Instantiate產生動畫。

馬上進入程式碼。先來寫主角發射的子彈的Script,「PlayerBulletHit.cs」:

public class PlayerBulletHit : MonoBehaviour
{
    public GameObject hitAnimation = null; //子彈擊中動畫Prefab
    public bool destroySelf;  //是否為「擊中一次就消失」的子彈
    
    void OnTriggerEnter2D(Collider2D col)
    {
        if (col.gameObject.tag == "Enemy Bullet") {
            Destroy (col.gameObject);  //移除敵人
            
            if (destroySelf)
                Destroy (gameObject); //移除自身
        }  else if (col.gameObject.tag == "Enemy") {
            EnemyBeingHit enemyData = col.gameObject.GetComponent<EnemyBeingHit>();
           
            //產生子彈擊中動畫
            if (hitAnimation != null)
                Instantiate (hitAnimation, enemyData.bulletAnimationPos.position, Quaternion.identity);
                
            col.gameObject.GetComponent<EnemyBeingHit> ().BeingHit ();
                
            if (destroySelf)
                Destroy (gameObject);
        }
    }
}

再建立另一個「EnemyBeingHit.cs」,輸入以下程式碼:

public class EnemyBeingHit : MonoBehaviour 
{
    public GameObject dieAnimation = null;  //死亡動畫Prefab
    public Transform bulletAnimationPos; //產生子彈擊中動畫位置
    
	public void BeingHit()
    {
        if (dieAnimation != null)
            Instantiate (dieAnimation, transform.position, Quaternion.identity);
            
        Destroy (gameObject);
    }
}

先來看PlayerBulletHit.cs,它有兩個成員變數,第一個hitAnimation用來存「擊中敵人動畫」Game Object的Prefab,第二個destroySelf用來決定是否在擊中後會把自身移除。死亡之帽、竹蜻蜓、皮卡耳、雷達的子彈都只能擊中一次,所以之後要勾選Destroy Self。

若有其他Collider 2D進入子彈的Collider 2D,OnTriggerEnter2D會被呼叫。此函數內,以if判斷擁有該Collider 2D的Game Object的Tag,若為「Enemy Bullet」(敵方子彈),則移除敵方子彈,並根據Destroy Self來決定是否移除自己(子彈)。若Tag為「Enemy」(敵方),則指定型態為EnemyBeingHit的變數enemyDatacol.gameObject.GetComponent<EnemyBeingHit>()

GetComponent<>()是Unity Scripting常用的函數,可輕易在Script中取得Game Object的任一Component。例如,若一Game Object內有Rigidbody 2D Component,GetComponent<Rigidbody2D>()就可取得該Component。

這裡我以GetComponent<EnemyBeingHit>()取得之後會為敵人裝上的Enemy Being Hit (Script) Component。因為要讓子彈的擊中動畫出現在敵人正上方,所以讓每個敵人在Enemy Being Hit (Script) Component指定不同的動畫產生位置。之後呼叫EnemyBeingHitBeingHit()函數,讓敵人自行產生動畫及移除自身(因為每個敵人的死亡動畫不同,且子彈不知道自己擊中的敵人為何者,所以不能直接在PlayerBulletHit.cs中產生敵人死亡動畫)。

EnemyBeingHit.cs的BeingHit()函數和PlayerBulletHit.cs碰觸敵人的程式碼非常相似。先檢查是否擁有死亡動畫,若有,則產生該動畫的Game Object,並移除自己。

回到Unity,為所有主角的子彈新增Rigidbody 2D Component,並根據它們的形狀加上Circle Collider 2D, Box Collider 2D或Polygon Collider 2D Component。把Rigidbody 2D的Is Kinematic打勾,Collider 2D的Is Trigger打勾,再裝上剛寫好的Player Bullet Hit (Script) Component。把擊中動畫做成Prefab拉到Hit Animation欄,並設定好Destroy Self。

http://ithelp.ithome.com.tw/upload/images/20161217/20103149CM5DgA4jty.png

http://ithelp.ithome.com.tw/upload/images/20161217/20103149Xv7KF1Jam7.png

為所有敵人prefab加上Enemy Being Hit (Script)。一樣做好它們死亡動畫的Game Object Prefab,拉至Die Animation欄,並新建一個子Game Object作為它的Bullet Animation Pos。
(敵人死亡動畫和子彈擊中動畫的Game Object Prefab都必須加上Destroy After Seconds (Script) Component,並設定好時間,不然動畫會一直存留在Scene上)

http://ithelp.ithome.com.tw/upload/images/20161217/20103149Sm3zLGZDDW.png

http://ithelp.ithome.com.tw/upload/images/20161217/20103149U1mZ3zuNqU.png

最後,把所有敵人Prefab的Tag改成”Enemy”、所有敵人子彈的Prefab改成”Enemy Bullet”。進入Play Mode測試,現在除了玩家碰到敵人或敵人子彈不會受到傷害外,遊戲的核心機制已大致完成啦!

http://ithelp.ithome.com.tw/upload/images/20161217/20103149ABX8fvyDmT.png

待續。


上一篇
Day 16: 敵人重生、移除
下一篇
Day 18: 少林功夫好 II
系列文
我要和天一樣高!!!(Unity 2D手機小遊戲開發日誌)30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言