衝突を検知しよう:当たり判定のイベントとタグ【Unityスタートガイド6-10】

「敵にぶつかったらダメージ」「コインに触れたら取る」「ゴールに入ったらクリア」。ゲームのほとんどのイベントは、オブジェクト同士がぶつかったり重なったりしたときに起こります。今回は、当たり判定をスクリプトで受け取る方法と、相手を見分けるためのタグをご紹介します!

目次

この記事で学べること

  • ぶつかったときに呼ばれるメソッド(OnCollisionEnter)
  • 重なったときに呼ばれるメソッド(OnTriggerEnter)
  • イベントが呼ばれるための条件(Rigidbodyが必要)
  • タグの作り方と、CompareTagで相手を見分ける方法
  • 2Dゲームの場合の書き方

前提知識

当たり判定のイベントとは?

Colliderの付いたオブジェクト同士が接触すると、Unityが決まった名前のメソッドを呼んでくれます。StartやUpdateと同じように、スクリプトにその名前のメソッドを書いておくだけで動きます。

3-4の記事で説明したとおり、Colliderには2つのモードがありました。

モード動き呼ばれるメソッド
Collision(Is Triggerがオフ)ぶつかって止まる・跳ね返るOnCollisionEnter / Stay / Exit
Trigger(Is Triggerがオン)すり抜けて、重なったことだけ知らせるOnTriggerEnter / Stay / Exit
  • Enter:触れた瞬間(1回)
  • Stay:触れている間(毎フレーム)
  • Exit:離れた瞬間(1回)

イベントが呼ばれる条件

ここが一番つまずきやすいところです。イベントが呼ばれるには、次の条件がそろっている必要があります。

  • 両方のオブジェクトにColliderが付いている
  • どちらか一方(または両方)にRigidbodyが付いている
  • 3Dどうし・2Dどうしであること(3DのColliderと2DのColliderは反応しません)
スライム

スクリプトはちゃんと書いたのに、ぶつかっても何も起きない・・・

フェアリー

9割はRigidbodyの付け忘れ!どちらか片方に付いているか、まず確認してね

OnCollisionEnter:ぶつかったとき

ボールが床に落ちたときに、ログを出してみましょう。

  1. Hierarchyで右クリック>3D Object>Planeを作る(床。名前はGround)
  2. Hierarchyで右クリック>3D Object>Sphereを作り、Position Yを5にする
  3. SphereにAdd Component>Physics>Rigidbodyを付ける
  4. 下のスクリプト「BallHit」をSphereにアタッチして再生
using UnityEngine;

public class BallHit : MonoBehaviour
{
    void OnCollisionEnter(Collision collision)
    {
        Debug.Log(collision.gameObject.name + "にぶつかった!");
    }
}

再生すると、Sphereが落ちて床にぶつかった瞬間に「Groundにぶつかった!」と表示されます。

  • メソッドの名前と、カッコの中の型(Collision collision)はこの通りに書く必要があります
  • collision.gameObjectで、ぶつかった相手のオブジェクトが分かります

タグで相手を見分ける

ぶつかった相手が「床」なのか「敵」なのか「コイン」なのかを見分けるのに、タグを使います。

タグを作る

  1. オブジェクトを選び、Inspectorの一番上にあるTagのプルダウンを開く
  2. 一番下のAdd Tag…を選ぶ
  3. Tagsの一覧の「+」を押して、名前(例:Coin)を入力してSave
  4. もう一度オブジェクトを選び、Tagのプルダウンから作ったタグを選ぶ

作っただけでは付かないので、最後にオブジェクトのTagを選び直すのを忘れないようにしましょう。

「Player」「Respawn」「Finish」など、最初から用意されているタグもあります。

CompareTagで調べる

void OnCollisionEnter(Collision collision)
{
    if (collision.gameObject.CompareTag("Enemy"))
    {
        Debug.Log("敵にぶつかった!");
    }
}

CompareTag("タグ名")は、そのオブジェクトのタグが指定した名前ならtrueを返します。

OnTriggerEnter:コインを集めてみよう

6-8で作ったプレイヤーで、コインを集める仕組みを作ってみましょう。

準備

  1. 6-8のシーン(床のPlaneと、PlayerMoverを付けたPlayer)を用意する
  2. PlayerにRigidbodyを付けて、Is Kinematicにチェックを入れる
    • PlayerMoverはtransform.positionで動かしているので、物理で動かされないようにKinematicにします。Rigidbodyが付いていればTriggerのイベントは呼ばれます
  3. Hierarchyで右クリック>3D Object>Sphereを作り、名前をCoinにする
    • Scaleを(0.5, 0.5, 0.5)、Position Yを0.5にして床の上に置く
    • Sphere ColliderのIs Triggerにチェック
    • Tagに「Coin」を作って設定する
    • 3-3の記事のように黄色いマテリアルを付けると、コインらしくなります
  4. CoinをCtrl+Dで何個か複製して、床の上に並べる

スクリプト

「CoinCollector」という名前でスクリプトを作り、Playerにアタッチします。

using UnityEngine;

public class CoinCollector : MonoBehaviour
{
    private int coinCount = 0;

    void OnTriggerEnter(Collider other)
    {
        // 重なった相手がコインなら
        if (other.CompareTag("Coin"))
        {
            coinCount++;
            Debug.Log("コインをゲット! 合計: " + coinCount);

            // コインを消す
            Destroy(other.gameObject);
        }
    }
}

再生して、WASDでコインに触れると、コインが消えて枚数が増えていけば成功!

ポイント

  • OnTriggerEnterの引数はCollider other(OnCollisionEnterのCollisionとは型が違うので注意)
  • other.CompareTag("Coin")で、コイン以外(床など)には反応しないようにしています
  • Destroy(other.gameObject)で、相手(コイン)を消しています。Destroy(gameObject)と書くと、自分(プレイヤー)が消えてしまいます!

2Dゲームの場合

2Dゲームでは、Rigidbody 2DやBox Collider 2Dなど「2D」の付いたコンポーネントを使います。メソッドも2D用の名前になります。

3D2D
OnCollisionEnter(Collision collision)OnCollisionEnter2D(Collision2D collision)
OnTriggerEnter(Collider other)OnTriggerEnter2D(Collider2D other)
using UnityEngine;

public class CoinCollector2D : MonoBehaviour
{
    private int coinCount = 0;

    void OnTriggerEnter2D(Collider2D other)
    {
        if (other.CompareTag("Coin"))
        {
            coinCount++;
            Debug.Log("コインをゲット! 合計: " + coinCount);
            Destroy(other.gameObject);
        }
    }
}

3D用のメソッドを2Dのオブジェクトに書いても呼ばれません。名前の最後の「2D」と、引数の型を確認しましょう。

よくあるエラーと対処法

エラー:ぶつかっても何も起きない

  • 原因:どちらにもRigidbodyが付いていない、Colliderがない、または3Dと2Dが混ざっている
  • 対処法:両方にCollider、どちらかにRigidbodyが付いているか確認する。2Dなら「2D」の付いたコンポーネントとメソッドを使う

エラー:OnTriggerEnterが呼ばれない

  • 原因:Is Triggerにチェックが入っていない(ぶつかるだけでTriggerのイベントにならない)
  • 対処法:重なって反応させたい方のColliderのIs Triggerにチェックを入れる。ぶつかって止まるほうを使いたいなら、OnCollisionEnterに書き換える

エラー:メソッドを書いたのに呼ばれない(つづりの問題)

  • 原因:OnTriggerEnterの大文字・小文字の間違い(OnTriggerenterなど)、または引数の型の間違い
  • 対処法:名前と引数の型を、この記事の通りに書く

エラー:Tag: ○○ is not defined

  • 原因:CompareTagで指定したタグを、まだ作っていない
  • 対処法:Add Tag…でタグを作る。つづり(大文字・小文字)も合わせる

エラー:コインではなくプレイヤーが消えた

  • 原因:Destroy(gameObject)と書いている
  • 対処法:相手を消すときはDestroy(other.gameObject)

まとめ

  • ぶつかったときはOnCollisionEnter、重なったときはOnTriggerEnter
  • イベントが呼ばれるには、両方にCollider、どちらかにRigidbody
  • 相手を見分けるのはタグ。CompareTag("タグ名")で調べる
  • 2DゲームではOnCollisionEnter2D / OnTriggerEnter2D

入力で動かして、ぶつかったら何かが起きる。これだけで、もう立派にゲームの形になってきました!

次のステップ

コインや敵のように「同じものをたくさん使う」ためのプレハブは、第7章で説明します。

よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!

コメント

コメントする

目次