iT邦幫忙

2024 iThome 鐵人賽

DAY 15
0
自我挑戰組

Unity入門遊戲開發與實作系列 第 15

【Day 15】製作一個簡單 Unity 小遊戲(四)物體碰撞檢測

  • 分享至 

  • xImage
  •  

在這個賽道上有很多的障礙物讓玩家閃避,但要如何知道我們撞到了障礙物呢?因此,今天要來製作物體的碰撞檢測。我們需要再為 Player 開一個新的 Script
,命名為 PlayerCollision

// PlayerCollision.cs
using UnityEngine;

public class PlayerCollision : MonoBehaviour
{
	void OnCollisionEnter()
	{
		Debug.Log("We hit Something!");
	}
}

OnCollisionEnter() 是一個檢測碰撞的函式,任何在 RigidbodyCollider 中發生的碰撞都會呼叫這個函式,我們在發生碰撞後在 Console 面板中顯示一段話來提示我們這個函式被呼叫了。

執行看看遊戲
https://ithelp.ithome.com.tw/upload/images/20240929/201693018mlEL862Lj.png
當方塊下落並且與地板發生碰撞時,我們看到 Console 視窗中顯示了 We hit Something! 這就表示我們的程式正常運行囉

創建障礙物

接下來我們要在 Unity 中創建一些障礙物。新建一個新的 3D 方塊,並且命名為 Obstacle。在 Scale 的地方給這個障礙物的 x 軸 Scale 調整為 2,所以這個障礙物是個長方體。同樣給這個 Obstacle 加上 Rigidbody ,並且在 Rigidbody 中的 Mass 控制項調整為 2,也就是比 Player 更重一點點。

優化程式

接下來我們要優化一下剛剛的程式碼,我們並不希望碰撞到所有東西都執行程式裡的指令,我們只希望當碰到特定物體時(障礙物)才要執行相對應的指令。
為了解決這個問題,我們希望可以知道我們剛剛究竟跟甚麼物體發生碰撞,所以我們可以這樣更改程式碼:

// PlayerCollision.cs
using UnityEngine;

public class PlayerCollision : MonoBehaviour
{
	void OnCollisionEnter(Collision collisionInfo)
	{
		Debug.Log(collisionInfo.collider.name);
	}
}

Collision 是當函式被呼叫時,Unity 知道我們想要碰撞物體的資訊,所以提供了這個欄位的變數,我們可以創建一個 Collision 的物件來取用相關的碰撞資訊,例如這邊就輸出了碰撞物體的名稱。
如果我們只想要當 Player 撞到障礙物時才執行一些程式,那麼我們可以加上一些判斷:

// PlayerCollision.cs
using UnityEngine;

public class PlayerCollision : MonoBehaviour
{
	void OnCollisionEnter(Collision collisionInfo)
	{
		if (colisionInfo.collider.name == "Obstacle")
		{
			Debug.Log("We hit Obstacle!");
		}
	}
}

然後執行遊戲
https://ithelp.ithome.com.tw/upload/images/20240929/20169301ApOWwWupKB.png
這樣只有當 Player 碰到 Obstacle 時才會輸出訊息!
https://ithelp.ithome.com.tw/upload/images/20240929/20169301UVWv2AzjhB.png
這樣看似一點問題都沒有,但是當場上有數十數百個不同名字的障礙物時,我們寫的 if 判斷式就會顯得特別沒效率,因為每次碰撞他都要檢查碰撞物名是否與這上百個障礙物的其中一個相等,這相當消耗時間。所以更聰明的方法是使用 Tag

使用Tag

Obstacle 中的最上面可以看到現在的 Obstacle 並未使用任何 Tag ,我們點擊一下並且選擇 Add Tag
https://ithelp.ithome.com.tw/upload/images/20240929/20169301TEeLa7h07W.jpg
新建一個名為 ObstacleTag
https://ithelp.ithome.com.tw/upload/images/20240929/20169301tmot0Ef2bK.jpg
並且將障礙物的 Tag 選為我們剛剛創建的 Obstacle


接著回到程式,我們不再檢測 name 了,而是檢測 tag

// PlayerCollision.cs
using UnityEngine;

public class PlayerCollision : MonoBehaviour
{
	void OnCollisionEnter(Collision collisionInfo)
	{
		if (colisionInfo.collider.tag == "Obstacle")
		{
			Debug.Log("We hit Obstacle!");
		}
	}
}

這樣我們終於完成了物體檢測的程式,即使場景中有上百個障礙物他們各自有不同的名字(例如:Obstacle1, Obstacle2, Obstacle3...),只要他們都享有同一個 Tag,我們就不用一直不斷地寫 if 判斷式來知道我們是否與障礙物發生了碰撞!


上一篇
【Day 14】製作一個簡單 Unity 小遊戲(三)鍵盤控制和第三人稱視角
下一篇
【Day 16】製作一個簡單 Unity 小遊戲(五)建立 Prefab 和布置關卡
系列文
Unity入門遊戲開發與實作30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言