在這個賽道上有很多的障礙物讓玩家閃避,但要如何知道我們撞到了障礙物呢?因此,今天要來製作物體的碰撞檢測。我們需要再為 Player 開一個新的 Script
,命名為 PlayerCollision
。
// PlayerCollision.cs
using UnityEngine;
public class PlayerCollision : MonoBehaviour
{
void OnCollisionEnter()
{
Debug.Log("We hit Something!");
}
}
OnCollisionEnter()
是一個檢測碰撞的函式,任何在 Rigidbody
和 Collider
中發生的碰撞都會呼叫這個函式,我們在發生碰撞後在 Console
面板中顯示一段話來提示我們這個函式被呼叫了。
執行看看遊戲
當方塊下落並且與地板發生碰撞時,我們看到 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!");
}
}
}
然後執行遊戲
這樣只有當 Player 碰到 Obstacle
時才會輸出訊息!
這樣看似一點問題都沒有,但是當場上有數十數百個不同名字的障礙物時,我們寫的 if
判斷式就會顯得特別沒效率,因為每次碰撞他都要檢查碰撞物名是否與這上百個障礙物的其中一個相等,這相當消耗時間。所以更聰明的方法是使用 Tag
!
Tag
在 Obstacle
中的最上面可以看到現在的 Obstacle
並未使用任何 Tag
,我們點擊一下並且選擇 Add Tag
新建一個名為 Obstacle
的 Tag
並且將障礙物的 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
判斷式來知道我們是否與障礙物發生了碰撞!