Unity備忘録6 当たり判定の設定をする方法part1【Unity2D】

アイキャッチ ゲーム制作
スポンサーリンク

こんにちは、slashです。
今回はUnityの当たり判定の設定方法です。

オブジェクト同士が衝突したかどうかの判定、
衝突した時に何らかの命令を実行させる、
といった事をやっていきます。

下準備

今回はオブジェクトの辺り判定を設定するので
適当にオブジェクトの画像を用意しておきます。

player
ground
enemy

①基本的な当たり判定の設定

オブジェクトの設置、当たり判定の設定をしていきます。

playerオブジェクトの設定

まず、プレイヤー画像をシーンに設置します。
オブジェクト名はplayerとしておきます。

図①-1 player画像を設置

Rigidbody2Dをアタッチ

playerオブジェクトを選択し、
AddComponent>physics2D>Rigidbody2Dをアタッチします。

図①-2 Rigidbody2Dをアタッチ

Rigidbody2Dをアタッチする事で
オブジェクトに力をかけて動かしたりと
物理的な挙動をさせる事ができます。

当たり判定の設定

さらにコンポーネントを追加していきます。
AddComponent>physics2D>BoxCollider2Dを選択します。
BoxCollider2Dは矩形の当たり判定です。

図①-3 BoxCollider2Dをアタッチ

BoxCollider2Dをアタッチすると、
オブジェクト周囲に四角の枠が表示されますが、
これが当たり判定となります。

EditColliderの横のアイコンをクリックすると、
当たり判定の大きさや位置を調整できます。

図①-4 当たり判定の確認と調整
補足

当たり判定は他にも
CircleCollider(円形)、CapsleCollider(カプセル形)などがあり、
複数のColliderをアタッチして複雑な形の
当たり判定を作る事もできます。

地面の設定

次は地面を作ります。
地面の画像をシーンにドラッグアンドドロップでセットします。
オブジェクト名はgroundとしておきます。
そしてgroundに先ほどと同様の方法でBoxCollider2Dをアタッチします。

playerとgroundの位置関係は
playerがgroundの上に来るように位置を調整しておきましょう。

図①-5 地面の設置

実行してみる

ゲームを実行してどんな動作になるか確認します。
playerが重力に引っ張られて落下し、
地面にぶつかって止まる動作になるかと思います。
これでplayerとgroundとの当たり判定動作ができました。

図①-6 実行して動作確認

②接触した時に何らかの動作をさせる

次に、オブジェクト同士がぶつかった時に
何らかの動作をさせるスクリプトを作ってみます。

C#Scriptを作る

新規でC#Scriptを作り、PlayerControllerという名前にします。
これをplayerオブジェクトにアタッチします。

図②-1 C#Scriptを作成

そして、スクリプトを以下のように更新します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        Debug.Log("Landed!");
    }
}

playerオブジェクトが何か他の当たり判定にぶつかった瞬間に
OnCollisionEnter2D(Collision2D collision)
のメソッド内に記述した命令が実行されます。

上記の場合はプレイヤーが他の当たり判定に接触した時に
コンソールにLanded!というメッセージが出る動作となります。

実行する

playerが地面にぶつかった時に
Landed!というメッセージが出たら成功です!

図②-2 地面に接触した時の動作を確認
スポンサーリンク

③タグを使ってみる

先ほどの例で、オブジェクト同士が接触した時に
命令を実行させる事ができましたが、
次は接触したオブジェクトに応じて
動作を変えられるようにしたいと思います。

具体的にはオブジェクトにtagを設定し、
接触したオブジェクトのtagに応じて
それぞれ異なる動作ができるようにしていきます。

オブジェクトにtagをつける

ここから、各オブジェクトにタグを設定していきます。

playerのtag

playerオブジェクトを選択し、
インスペクターのTagからPlayerを選択します。

これでplayerのタグ設定は完了です。

図③-1 playerのタグを設定

groundのtag

groundオブジェクトを選択し、
インスペクターのTagからタグを選びますが、
タグは新しく追加する事ができます。

インスペクターのTag>Add Tag…を選択します。
「Tags」の「+」マークをクリックすると、
タグの名称を入力するウィンドウが出てくるので、
Groundという名前を入力して「Save」をクリックします。

図③-2 groundのタグ設定1
図③-3 groundのタグ設定2

これで「Ground」というタグが新しく使えるようになりました。
その後、groundオブジェクトを再選択>Tag>Groundを選択します。

図③-4 groundのタグ設定3

enemyのタグ

まず、敵キャラの設置をします。
enemy画像をシーンビューにドラッグアンドドロップでセットします。
そして、先ほどplayerに対して行ったのと同様に
rigidbody2Dと当たり判定を設定します。

今回のenemy画像は丸っこい形状をしているので
当たり判定はBoxCollider2Dではなく
CircleCollider2D(円形の当たり判定)をアタッチします。

図③-5 敵キャラの設置

rigidbody2Dは
playerにアタッチした時と同じ方法で
アタッチしておきます。

図③-6 敵キャラの設置2

これで敵キャラの設置ができたのでタグを設定します。
先ほど、「Ground」タグを作った時と同様の方法で
Enemy」というタグを作ります。

図③-7 enemyのタグ設定

そして、敵キャラのオブジェクトに対して
「Enemy」タグを設定します。

接触時の動作を作成する

スクリプトを更新して
敵キャラや地面に接触した時の動作を作成します。
PlayerControllerのスクリプトを再度開き、
OnCollisionEnter2Dメソッドを以下のように変更します。

void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Ground")
        {
            Debug.Log("Ground");
        }
        else if (collision.gameObject.tag == "Enemy")
        {
            Debug.Log("Enemy");
        }            
    }

collision.gameObject.tagには接触したオブジェクトの
タグが代入されます。
例えば、playerがGroundタグを設定したオブジェクトに接触すると、
collision.gameObject.tagが”Ground”となります。

タグを使い分ける事で
「playerが何に接触したか」を判別可能となり
接触した物に応じてそれぞれ
異なる挙動をさせられるようになるわけです。

上記スクリプトの場合ですと、
playerが
地面に接触するとコンソールに「Ground」という文字列が出力され、
敵キャラに接触すると「Enemy」という文字列が出力される、

という動作になります。

プレイヤーが動けるようにする

さて、接触時の動作を作成したので
早速テストプレイといきたいところですが・・・

このままでは、
地面とプレイヤーは接触できますが、
敵キャラとプレイヤーは動けないので
接触することができません。

図③-8 このままでは敵とプレイヤーが接触できない

そこで、キー入力で
プレイヤーを左右に動かせるようにします。
PlayerControllerを以下のように更新します。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class PlayerController : MonoBehaviour
{
    float PlayerSpeed = 0.0f;//プレイヤー速度

    // Start is called before the first frame update
    void Start()
    {
        
    }

    void Update()
    {
        if (Input.GetKey(KeyCode.LeftArrow))
        {
            //左キーが押されている
            PlayerSpeed = -0.1f;
        }
        else if (Input.GetKey(KeyCode.RightArrow))
        {
            //右キーが押されている
            PlayerSpeed = 0.1f;
        }
        else
        {
            //左キーも右キーも押されていない
            PlayerSpeed = 0.0f;
        }
    }

    void FixedUpdate()
    {
        transform.Translate(PlayerSpeed, 0.0f, 0.0f);
    }

    void OnCollisionEnter2D(Collision2D collision)
    {
        if (collision.gameObject.tag == "Ground")
        {
            Debug.Log("Ground");
        }
        else if (collision.gameObject.tag == "Enemy")
        {
            Debug.Log("Enemy");
        }            
    }
}

プレイヤーの速度を代入する変数として
float型の変動のPlayerSpeedを定義します。

Update()メソッドは毎フレーム実行されるメソッドなので
ここに、キーの入力状況に応じて
PlayerSpeedの値が変化するようにスクリプトを書きます。

Input.GetKey(KeyCode.LeftArrow)
キーボードの左キーが押されている間はtrue
押されていなければfalseとなるので、
if (Input.GetKey(KeyCode.LeftArrow))と書くと
キーボードの左キーが押されている間だけ
実行される条件分岐ができます。

同様に、Input.GetKey(KeyCode.RightArrow)
キーボードの右キーが押されているかどうかの
判定に使う事ができます。

上記スクリプトでは、
左キーが押されている間はPlayerSpeedが-0.1
右キーが押されている間はPlayerSpeedが0.1
どちらも押されていない場合はPlayerSpeedが0
なるようにしています。

次にFixedUpdate()メソッド内に
transform.Translate(PlayerSpeed, 0.0f, 0.0f);
と、書くことで
playerをPlayerSpeedの速度で左右に動かす事ができます。

FixedUpdateについて

transform.Translate(PlayerSpeed, 0.0f, 0.0f);は
Update()メソッド内に書いてもキャラを動かす事は可能です。

しかし、Update()メソッドは
使用する環境によって1秒あたりの実行回数が
変わってしまう事があるため、
ゲーム実行時のデバイスによって
キャラの移動速度が変わってしまいます。

FixedUpdate()メソッドは
1秒あたりの実行回数が固定されているため、
環境に影響されず移動速度が一定になります。

実行して動作確認

それではゲームを実行してみます。

キーボードの左右キーで
プレイヤーを左右に動かす事が
できるようになっているかと思います。

プレイヤーが地面に接触した時に「Ground」
敵に接触した時に「Enemy」が
コンソールに出力されていれば成功です。

図③-9 動作確認

結構、記事が長くなったので
part2へ続きます。

タイトルとURLをコピーしました