【Unity 2022】当たり判定とスクリプトについての初心者用講座
こんにちは、今回は当たり判定についての講座ということで、当たり判定を実装する方法をわかりやすく解説していこうと思います。
ゲーム作りをするなら今回学ぶ要素は必須のものとなります。
しっかり押さえていきましょう。
3Dオブジェクトについているコライダーを見てみよう
まずは、手始めに、当たり判定について学ぶ際にコライダーという概念について知っておく必要があります。
コライダーとは、一言で言いますと、当たり判定を行う範囲のこととなります。
このコライダーはオブジェクトに付与することができ、範囲をカスタマイズすることもできます。
そして、このコライダーとコライダーが接触したときに、当たったと判定されることになるのです。
今回この記事では、Unityの3Dの環境を用いて説明していきますので、Unityのプロジェクトを作成するときは、3Dを選んでプロジェクトの作成を行ってください。
Cubeについているコライダー
プロジェクトを作成し開きましたら、ヒエラルキーの+(Create)から、3Dオブジェクト→Cubeを選択し、Cubeの作成を行ってください。
そして、作成したCubeをヒエラルキーからクリックし、インスペクターに注目しましょう。
インスペクターの中に“BoxCollider”と書かれたコンポーネントがあるのが確認できると思います。
以下の画像を参考にしてください。
これもコライダーの一種で、Cubeを作成したときに勝手についてくるコライダーとなります。
一応このBoxCollider(というよりすべてのコライダー)は、EditColliderと書かれた項で、範囲を柔軟に編集することができます。
しかし、自分で編集するのはなかなか大変なので、あまり使用しない機能です。使い分けが必要ですね。
それ以外にも、コライダーのサイズを変更したり、オブジェクトを基準としたときのコライダーの位置を設定したりすることができます。
コライダーのサイズを変えてみる
では、BoxColliderの大きさを試しに変えてみたいと思います。
先ほどのインスペクター中のBoxColliderで、Sizeという項があったと思います。
この項のX,Y,Zすべての値をそれぞれ2にしてみてください。
そしたら、シーンビューのCubeオブジェクトを見てみましょう。
なんだか、緑色の枠のようなものが出てきましたね。
こいつがコライダーの正体になります。
じつは最初からCubeには存在していましたが、Cube自体によって、枠線が目立ちにくくなっていたと思います。
サイズが大きくなったことで、見やすくなりました。
この緑色の線で囲まれた範囲が当たり判定を行う範囲になります。
この領域にほかのコライダーが接触すると、衝突が起こったと判定されるようになるのです。
3Dオブジェクト同士を衝突させてみよう
では、一度3Dオブジェクト同士をぶつけて、コライダーの挙動をみましょう。
+(Create)から、もう一つCubeを作成してください。
おそらく名前はCube(1)となっていると思いますが(前の項でCubeの名前を変えていない場合)、そのままでも構いません。
作成したら、インスペクターからPositionの値をX:0,Y:5,Z:0に変えましょう。
さらに、インスペクターの下のほうにあるAddComponentを選択し、Phisics→Rigidbodyを選択してください。
下の画像のようなものが追加されていればOKです。
さらに、今度は、初めに作成したCubeのほうを選択し、Positionの値をX:0,Y:0,Z:0に変更しましょう。
最終的に、シーンビューのオブジェクトが以下の画像のような配置になっていれば大丈夫です。
ちなみに、Rigidbodyとは、オブジェクトに物理的な挙動ができるように、実体のある物質と同じような特徴を持たせるコンポーネントになります。
そのため、このRigidbodyが付与されたオブジェクトは、重力が働いてそのまま落下していきます。
このことを踏まえたうえで、実行してみましょう。
すると、実行と同時に上方のCubeのほうが落ちてきて、やがて、下のCubeと少し間隔をとった状態で止まったと思います。
これが、オブジェクト同士の衝突です。
オブジェクトに付与されたコライダー同士がぶつかって、それ以上交わらないようになっています。
オブジェクトの衝突を検知する関数
コライダーについて一通り理解できましたと思いますので、ここからは、スクリプトを用いて当たり判定を実装していく方法について説明していきます。
スクリプトが何なのか全くわからない人は、以下の記事を参考にしてください。
まずは、スクリプトを作成してください。
名前は“collision"とでもしておいてください。任意でもいいです。
作成しましたら、スクリプトを開きます。
そして、まずは当たり判定の準備として、Update()の中ではなく、一つ下のところに下記の関数を書いてください。
void OnCollisionEnter(Collision collision)
{
}
上記のスクリプトを持っているオブジェクトは、コライダー同士がぶつかったとき、このOnCollisionEnterという名前の関数が呼び出されることになっています。
つまり、この関数の中にダメージを受けた時などの処理を書いておくことで、実際にオブジェクトが衝突したときに、その処理を行うことができるのです。
OnCllisionEnterの場合は、コライダーが触れた時(コライダーが別のコライダーに入る瞬間)を検知していますが、そのほかにもいろいろ種類があります。
Enterの部分をStayに変えると、コライダーが別のコライダーの中にとどまっている間、処理が実行され続け、Exitに変えると、コライダーがコライダーから出ていく瞬間に処理が実行されるという意味になります。
また、OnClliderは、衝突を検知しますが、すり抜けるオブジェクト用の関数であるOnTriggerEnterなんてのもあったりします。
実際に当たり判定を作ってみよう
それでは、実際に、オブジェクト同士が衝突したときに、処理を実行していこうと思います。
先ほど作成したOnCollisionEnter関数の中に、次のように書いてください。
transform.position=new Vector3(5f,0f,0f);
書きましたら、これだけで完了ですので、Ctrl+sキーでセーブして閉じてください。
下の画像のようにかけていればOKです。
では、書いたスクリプトをドラッグしてCubeオブジェクト(スクリーンビュー内の上下のうちの下のほうのキューブ)にアタッチしてください。
アタッチできましたら、さっそく実行してみましょう。
上のキューブが落ちてきて、下のキューブにあたるところまで待ちましょう。
するとどうでしょうか、キューブ同士が衝突した瞬間、下のキューブが右のほうに移動したのが確認できたと思います。
この例はすごく簡単で大したものではありませんが、当たり判定の一種です。
これと同じものを実装することで、ゲームの複雑な当たり判定を作っていくことができます。
オブジェクトを区別して判定する
前の項で説明した方法で、まずは簡単な当たり判定を作ることができました。
しかし、よく考えてみるとゲームの中では、例えばシューティングゲームであれば、「a弾は50ダメージを与えるけどb弾は80ダメージを与える」といったような、オブジェクトによって当たり判定による処理を変える必要がある場面があります。
そういう場合は、オブジェクトを区別して判定するようにしなければなりません。
これからその方法について説明していきます。
オブジェクトをもう一つ追加
まず、オブジェクトを区別して当たり判定を行うということをわかりやすく行うために、衝突させるCubeをもう一つ追加します。
ヒエラルキーのCube(1)(上から落ちてくるほうのキューブ)を選択し、右クリック→Copyを選びます。
同じくヒエラルキーの、空白のところで適当に右クリックし、出てきたメニュー中のPasteを選択してください。
すると、名前がCube(2)のキューブが出てきたと思います。
これでオブジェクトを複製することができました。
そしたら、そのオブジェクトのインスペクターを開き、positionの値を次のようにします。
X:5,Y:10,Z:0
こうすることで、ゲームを実行したとき、一つ目のキューブが落ちていった後に少し遅れてこのキューブも落ちていくことになります。
タグをつける
次に、一つ一つのオブジェクトが衝突したときそれぞれ区別するために、タグと呼ばれるものをオブジェクトに着けていきます。
タグは、そのまま「名札」と同じ意味になります。
オブジェクトが衝突したときに、この名札を見てあげることで、オブジェクトの区別が可能となります。
まずは、一つ目のオブジェクト(Cube(1))に名札を付けます。
Cube(1)をクリックし、インスペクターを見てください。
右上にTagという項があり、そこの右側がUntaggedとなっていると思います。
ここにタグをつけていきます。
では、Untaggedとなっているプルダウンメニューをクリックし、開いてください。
いまはまだつけるべきタグがありませんので、新しいタグを作成しようと思います。
タグの作成
メニューの一番下のAddTag…を選択してください。
すると、以下の画像のようになると思いますので、TagsのList is Emptyの+を押してください。
そしたら、NewTagNameという項目が出現し、そこに任意の名前を設定できるようになりますので、
Cube1
という名前にし、Saveをクリックしましょう。
すると、以下の画像のように、新しいタグを作ることができました。
あともう一つタグが必要ですので、同じ手順でタグをもう一つ作ります。
タグの名前は Cube2 としてください。
タグをつけていく
それでは、これからタグをつけていこうと思いますので、まずはCube(1)を選択してください。
そして、インスペクターの上のほうにあるTagをクリックしてください。
すると、プルダウンメニューが表示され、下のほうに、先ほど作った二つのタグ(Cube1とCube2)が追加されていることが確認できると思います。
Cube(1)のほうには、Cube1タグをつけたいので、Cube1をクリックしましょう。
すると、TagのところにCube1が当てはめられたのが確認できます。
同じやり方で、Cube(2)オブジェクトにCube2タグをつけてください。
つけることができましたら、下準備OKです。
当たり判定の実装
では、スクリプトを開いてください。
すると、OnCollisionEnterの中に、
transform.position…
と書かれた一文があると思います。
この一文はもう使いませんので、消してください。
次に、まっさらになったOnCollisionEnter関数の中に以下の文を書いてください。
transform.Translate(5,0,0);
いったんこれで実行してどんな挙動になるかみてみましょう。
キューブが上から落ちてくると、衝突と同時に右へスライドしましたね。
さらに、もう一つ上からキューブが落ちてきますが、衝突すると、またもや右へスライドしたと思います。
この状態は、オブジェクトを区別していない状態です。
では、少し上のプログラムを改造して、オブジェクトを区別するようにしてみたいと思います。
OnCollisionEnterの中を以下の文に書きかえてください。
なお、if文の中のtransform.のところは、先ほどと同じですので、切り取りや移動をさせると楽です。
if(collision.gameObject.tag=="Cube1")
{
transform.Translate(5,0,0);
}
ここまで書きましたら、いったん実行してみましょう。
すると、以下の画像のようになったのではないでしょうか。
一つ目のオブジェクトの時は、しっかりスライドしますが、二つ目の時は、びくともしません。
これは、Cube1とCube2とでオブジェクトを区別することができているためです。
ここで少し、スクリプトの中身について解説しようと思います。
まず、ifの中のcollision.gameObject.tagについてですが、まず、collisionというのは、衝突してきたオブジェクトを格納しておくための変数のようなものだと思ってください。
OnCollisionEnterのすぐ右の()の中にCollision collisionと書かれていますが、これがその変数の宣言になります。
この右側のcollisionは、自分で好きな名前に変えることもできますが、このままでも差し支えありません。
collision.gameObjectと書くことで、衝突してきたオブジェクトについて実際に取り扱うことができます。
そして、この
collision.gameObject.tag=="Cube1″
という文は、衝突してきたキューブのタグがCube1であるかどうかを判定しているわけです。
そういうわけで、Cube(1)にあたったときはスライドしますが、Cube(2)に当たっても何も起こらなかったというわけです。
ぜひ、当たり判定を実装するときは、この方法を用いて区別してみてください。
それぞれ別の処理をさせてみよう
では、最後に、スクリプトのOnCollisionEnterの中に下のコードを追加してみましょう。
if(collision.gameObject.tag=="Cube2")
{
transform.Translate(0,5,0);
}
このコードをコピペすれば確実ですが、一応注意を言っておきますと、5という引数を入れる場所はTranslateの()の中の左側(Xの引数)ではなくて、真ん中(Yの引数)になりますので、間違えないようにしましょう。
また、タグの判定はCube2を対象にしていますので、Cube1と間違わないように注意しましょう。
書き込むことができましたら、スクリプトを保存して実行してみてください。
すると以下の画像のようになったと思います。
右にずれた後に上へあがっていますね。
イメージとしては、⤴この矢印のような感じですね。(矢印が表示されていなかったらすみません苦笑)
これは、当たってきたオブジェクトによって行う処理が違うということを表しています。
前項の方法を用いることで、うまくオブジェクトを区別した当たり判定を実装することができました。
最後に
今回の説明はこの辺で終わりにしますが、当たり判定についてはまだまだ伝えきれていない技術もたくさんあります。
ゲームを作っていくうえでは、様々な仕様の当たり判定が必要になってきます。
その時は、その都度その都度自分で調べてみるようにしましょう。
持っている当たり判定スキルのレベルと比例して、ゲームのクオリティも格段に上がっていきます。
ぜひ、これから上位の知識についても自主的に身に着けていってください。
この分野は磨けば磨くほどゲームがゲームらしくなっていきます。
それではまた。