iT邦幫忙

2021 iThome 鐵人賽

DAY 9
0
自我挑戰組

用unity製作2DRPG雛形-沒有大野狼的小紅帽系列 第 9

9.unity物件偵測(碰撞Collider2D)

碰撞器2D (參閱Collider 2D)

碰撞器可以讓物體碰撞停下、設定障礙物;也可以達成撿金幣、攻擊...這類物件偵測事件。

如何偵測兩個物件接觸?

碰撞器在物件身上建立一個碰裝偵測範圍,可以去碰撞其他帶有碰撞器的物件。
並且規定主動方(移動的物件)必須帶有Rigidbody,碰撞時才有因應的物理系統。
※且不可兩邊的rigidbody都使用Kinematic運動學(忽略物理)

添加碰撞元件
Add Component元件 → 形狀 Collider 2D
1.png
方盒碰撞器;橢圓碰撞器;圓形碰撞器;複合碰撞器;邊界碰撞器;多邊形碰撞器;瓦片地圖碰撞器
依照物件選擇適合的碰撞器即可。

以BoxCollider2D為例
2.png

Edit Collider 碰撞範圍編輯,可以手動調整碰撞範圍
3.png

Material 材質,可以下載不同模式的碰撞效果(例如彈跳皮球或冰塊材質的運動),也可以是空值。

Is Trigger 觸發器,打開的話不會與其他物體碰撞,取消物理系統,會被穿越,碰到可以觸發事件。


偵測事件

Enter函式是兩個物件碰撞瞬間,執行一次函式

Exit函式是兩個物件分開瞬間,執行一次函式

Stay函式是兩個物件保持接觸,不斷執行函式

基本寫法:

void OnCollisionEnter2D(Collision2D coll) //傳入碰撞對象,coll(自己取)
{
   //碰撞成立之後想幹嘛就寫在這裡
}

碰撞事件 OnCollision

OnCollisionEnter2D
OnCollisionExit2D
OnCollisionStay2D

官方腳本:

using UnityEngine;
public class Example : MonoBehaviour
{
//Enter函式是兩個物件碰撞瞬間,執行一次函式
    void OnCollisionEnter2D(Collision2D coll) //傳入碰撞對象 取名coll
    {
        if (coll.gameObject.tag == "Enemy") //這個對象的tag如果是敵人
        {
            coll.gameObject.SendMessage("ApplyDamage", 10);
						//傳參數10給這個物件,gameObject.SendMessage()之後會花一天了解他~
        }
				
//Exit函式是兩個物件分開瞬間,執行一次函式
		int bumpCount;
    void OnCollisionExit2D(Collision2D coll)
    {
        if (coll.gameObject.tag == "DodgemCar")
        {
            bumpCount++;
        }
    }

//Stay函式是兩個物件保持接觸,不斷執行函式
		float rechargeRate = 10.0f;
    float batteryLevel;
    void OnCollisionStay2D(Collision2D coll)
    {
        if (coll.gameObject.tag == "RechargePoint")
        {
            batteryLevel = Mathf.Min(batteryLevel + rechargeRate * Time.deltaTime, 100.0f);
						//Mathf.Min(值,值,...) 回傳最小值。
        }
    }
 }

觸發事件 OnTrigger

用法基本上跟OnCollision一樣,差在會不會穿越。
OnTriggerEnter2D
OnCollisionExit2D
OnCollisionStay2D

實例:跟OnCollision一樣,OnTriggerEnter2D不太一樣,寫隱形碰撞器(在下面)

using UnityEngine;
public class Example : MonoBehaviour
{
//Exit函式是兩個物件分開瞬間,執行一次函式
		int bumpCount;
    void OnCollisionExit2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "DodgemCar")
        {
            bumpCount++;
        }
    }

//Stay函式是兩個物件保持接觸,不斷執行函式
    float rechargeRate = 10.0f;
    float batteryLevel;
    void OnCollisionStay2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "RechargePoint")
        {
            batteryLevel = Mathf.Min(batteryLevel + rechargeRate * Time.deltaTime, 100.0f);
        }
    }
}

OnTriggerEnter2D官方腳本

腳本一,掛載在物件一
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Create GameObject1 that falls under gravity.  It will pass through
// Example2 and cause a collision.  GameObject1 is moved back to
// the start position and it will again start to fall under gravity.
//創建一個會自由落體的物件1,穿過物件2時會造成事件,然後物件1回到原點再一次自由落體

public class Example1 : MonoBehaviour
{
    void Awake()
    {

        SpriteRenderer sr; //建立sprite渲染(遊戲對象)
        sr = gameObject.AddComponent<SpriteRenderer>() as SpriteRenderer;
        sr.color = new Color(0.9f, 0.9f, 0.1f, 1.0f);//設定顏色RGBA

        BoxCollider2D bc; //建立碰撞器
        bc = gameObject.AddComponent<BoxCollider2D>() as BoxCollider2D;
        bc.size = new Vector2(1.0f, 1.0f);//碰撞器範圍

        Rigidbody2D rb; //建立剛體
        rb = gameObject.AddComponent<Rigidbody2D>() as Rigidbody2D;
        rb.gravityScale = 1.0f; //設重力大小

        // A square in the Resources folder is used.
				//使用Resources資料夾內的square圖片
        gameObject.GetComponent<SpriteRenderer>().sprite = Resources.Load<Sprite>("square");

        // GameObject1 starts 3 units in the Up direction.
				//物件1起始於Y軸上第三格
        gameObject.transform.position = new Vector3(0.0f, 3.0f, 0.0f);
        gameObject.transform.localScale = new Vector3(0.5f, 0.5f, 1.0f);
    }

    private float timer = 0.0f;   //計時器預設為0
    private bool restart = false; //重新啟動布林值預設為否

    void FixedUpdate()//固定時間更新的Update。
    {
        if (restart == true) //如果重新啟動布林值為是
        {
            timer = timer + Time.deltaTime; //開始計時
            if (timer > 0.25f) //當計時到0.25f
            {
								//物件回到起始點、速度為0、重新啟動布林值改為否
                gameObject.transform.position = new Vector3(0.0f, 3.0f, 0.0f);
                gameObject.GetComponent<Rigidbody2D>().velocity = new Vector2(0.0f, 0.0f);
                restart = false;
            }
        }
    }

    // called when this GameObject collides with GameObject2.
		//當物件1碰到物件2時會呼叫此函式
    void OnTriggerEnter2D(Collider2D col)
    {
        Debug.Log("GameObject1 collided with " + col.name);//顯示物件1撞到物件的"名稱"
        restart = true; //重新啟動布林值改為是
        timer = 0.0f;   //timer歸零
    }
}
腳本二,掛載在物件二
using System.Collections;
using System.Collections.Generic;
using UnityEngine;

// Create a rectangle that the other GameObject will collide with.
// Note that this GameObject has no visibility.
// (View in the Scene view to see this GameObject.)
//創建一個方型物件讓其他物件進行碰撞偵測,且這個物件無法被看到。(沒有渲染圖案sprite)

public class Example2 : MonoBehaviour
{
    void Awake()
    {
        BoxCollider2D bc;//建立碰撞器
        bc = gameObject.AddComponent<BoxCollider2D>() as BoxCollider2D;
        bc.size = new Vector2(3.0f, 1.0f);//碰撞器範圍
        bc.isTrigger = true; //設置為偵測器
				
				//偵測器定位於Y軸上-2格
        gameObject.transform.localScale = new Vector3(3.0f, 1.0f, 1.0f);
        gameObject.transform.position = new Vector3(0.0f, -2.0f, 0.0f);
    }

    void OnTriggerEnter2D(Collider2D col)
    {
        Debug.Log("GameObject2 collided with " + col.name);
    }
}

上一篇
8.unity角色移動(剛體Rigidbody2D)
下一篇
10.unity攝影機跟隨功能(Cinemachine)
系列文
用unity製作2DRPG雛形-沒有大野狼的小紅帽30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言