Colliderを作っていてワケが分からなくなった人
Colliderの設定はちゃんとしたはずなのに当たり判定が出ない…どこを直せばいいんだろう?
OnCollisionEnterとか関数が色々あるけれど、どうスクリプトを書けば動くんだ?
このような疑問に答えます。
本記事の内容
●Colliderの設定方法
●Colliderの動作の流れとコード解説
この記事を書いている私は12才からフルスクラッチでゲームを作っています。
またコンパイラを専門として情報理工学の博士まで進学、中退をしており、プログラミング言語の文法にも関わる論文を書いていました。
本記事ではコピペで使える実行済みのコードと設定方法を紹介しつつ、簡単なミスでハマらないよう詳細な設定方法も解説します。
※実行環境
Unity2021.3.1f1
Windows 10
コピペ推奨、Colliderのコード
ささっとコピペをしましょう。
この複雑な綴りを間違っても自分で書かないようにしてください。
私はこの記事を書くための実験で、綴りのミスにより1時間以上を溶かしました。
CollisionDetectorスクリプト
using UnityEngine; public class CollisionDetector : MonoBehaviour { //衝突していない状態から衝突している状態になった時 void OnCollisionEnter(Collision other) { Debug.Log(other.gameObject.name); } //衝突している状態が続いている時 void OnCollisionStay(Collision other) { Debug.Log(other.gameObject.name); } //衝突している状態から衝突していない状態になった時 void OnCollisionExit(Collision other) { Debug.Log(other.gameObject.name); } }
TriggerDetectorスクリプト
using UnityEngine; public class TriggerDetector : MonoBehaviour { //判定が発生していない状態から発生している状態になった時 void OnTriggerEnter(Collider other) { Debug.Log(other.gameObject.name); } //判定が発生している状態が続いている時 void OnTriggerStay(Collider other) { Debug.Log(other.gameObject.name); } //判定が発生している状態から発生していない状態になった時 void OnTriggerExit(Collider other) { Debug.Log(other.gameObject.name); } }
●other
衝突や判定を行った際に渡される、相手の情報をまとめたインスタンス変数
Collision系の引数はCollisionクラスで、Trigger系の引数はColliderクラスのインスタンスであることに注意
各関数の呼び出しは1対1で行われる
例えば自キャラが3体の相手キャラと衝突した場合、自キャラの関数は3回呼び出される
Colliderの設定方法
それでは簡単なオブジェクトを2つ作って動作を確認しましょう。
今自分で作っているゲームがある方は、以下の設定をパクって適用してみてください。
Colliderはスクリプトを書くよりも設定する方がややこしい部分だと思います。
私も入門書を読んでいた時に、設定できたつもりなのに当たり判定が出ないことがよくありました。
そこで今回は学習用に「効率はよくないかもしれないけれど分かりやすい、確実に動く」ことを優先した構成を紹介します。
全く動かない、よりはとりあえず動く、の方が作業は進むし楽しいので気を付けて取り掛かりましょう。
当たり判定を取りたいオブジェクトを作る
1.「Hierarchy」ウィンドウの余白を「右クリック > 3D Object > Cube」
2.「Hierarchy」ウィンドウの余白を「右クリック > 3D Object > Cube」
3.「Hierarchy」ウィンドウで、追加した各Cubeをクリック
4.「Inspector」ウィンドウで各「Transform」を下図のように設定
この段階でCollision系の当たり判定を準備します。
物を押すなど、文字通り物と物がぶつかっているかを知りたい場合に利用できます。
例によって自分のオリジナルキャラなどがあれば使ってみましょう。
作りたいものを1歩でも進めるのが大事です。
CollisionDetectorなどをアタッチする
1.「Hierarchy」ウィンドウで、追加した各Cubeをクリック
2.「Inspector」ウィンドウ最下部の「AddComponent」ボタンをクリック
3.「collisiondetector」と入力すると「Collision Detector」が出てくるのでクリック
4.同様の手順でRigidbodyコンポーネントを各Cubeにアタッチ
5.Box Colliderコンポーネントを各Cubeにアタッチ
6.床などのオブジェクトを作る場合、「Inspector」ウィンドウでRigidbodyの「isKinematic」にチェック
●isKinematic
重力や衝突による移動を全てオフにすることが出来る
もう少し細かい理屈は下記を参考
参考:【コピペでUnity】Rigidbody(リジッドボディ)の分かりづらいスクリプト制御を攻略
Colliderコンポーネントはデフォルトでついていることも多いですが、ワケも分からずやっていると削除したりしがちなので確認のため書いています。
なんかバグった時にColliderを消した覚えはありませんか?
私はあります。
ここまでで普通の当たり判定の実装は完了です!
物体同士がぶつかると物理演算に従って動くようになります。
例えばCubeを2つ、3つと増やしていけば、沢山のブロックが崩れるような動きを観察できます。
そして「Console」ウィンドウを見ると分かるとおり、衝突が起きた場合に各関数が呼び出されます。
●Cube2つがOnCollisionStayを呼び出す…2行
このような呼び出しにより4行のログが出力されます。
それぞれのオブジェクトの子に、空のオブジェクトを作る
1.「Hierarchy」ウィンドウで、追加した各Cubeに「右クリック > Create Empty」
ここからはTrigger系の当たり判定を設定します。
例えば格闘ゲームなどで、
●攻撃判定
●くらい判定
のように、2種類以上の異なる形の判定を使いたくなる場合に活用できます。
子オブジェクトなので数が増えても管理がしやすくなるハズです。
TriggerDetectorなどをアタッチする
1.Box Colliderコンポーネントを各GameObjectにアタッチ
2.各GameObjectで「isTrigger」にチェック
3.各GameObjectで「Size」を下図のように設定
4.TriggerDetectorスクリプトを各GameObjectにアタッチ
Colldierはオブジェクトの見た目に囚われず、実装の目的に合わせて自由に設定しましょう。
「Size」を変更したり、Collider系であればCapsule Colliderなどに変えてみるのもアリです。
なぜならTrigger系の判定は当たり判定やゴール判定に使う場合が主だからです。
当たり判定はキャラクターよりひとまわり小さかったり、ゴール判定はそもそもプレイヤーに見えては意味がないものだったりしますよね。
ここで「Inspector」ウィンドウを見てみると、10種類の判定が出ています。
ちゃんと関数が機能していますね。
Collision系の判定に加え、
●GameObject2つが、GameObjectと相互にOnTriggerStayを呼び出す…名前が被るため1行
●GameObject2つが、CubeとのOnTriggerEnterを呼び出す…2行
●GameObject2つが、CubeとのOnTriggerStayを呼び出す…2行
以上により10行のログが出来上がります。
これでCollider系の実装は完成ですね。
名前の変更などをサボっていることもあり、この時点で当たり判定の区別はかなり複雑なことが分かると思います。
ここから作りこんでいくには、「Hierarchy」ウィンドウでオブジェクトの名前を変更したり、タグなどの機能を使ってスクリプトで区別していきます。
Colliderの動作の流れとコード解説
Colliderの仕組みを大まかに理解し直そう
細かい設定ばかりをやってきましたが、大まかな理解も大事です。
Colliderとソースコードの関数の仕組みは下図のとおりです。
Unityのソースが分からないので、これまでの作業から最低限分かっていることをまとめています。
少なくとも同一のオブジェクト内ではこういう構造です。
どのオブジェクトとぶつかったかなど、当たり判定の詳細は各関数の引数で分かります。
OnTrigger~…Colliderクラスのインスタンス
どちらもgameObject変数を持っているので、そこから基本的な情報は好きに参照できるハズ。
今回のソースでは「gameObject.name」で「Hierarchy」ウィンドウ上の名前を取得しています。
Enter、Stay、Exitの違い
Enter、Stay、Exitはなんとなくで使い分けるのも結構ですが、この際しっかり理解しておくことをオススメします。
まずは関数の違い以前に、Colliderとしての判定を2種類覚えましょう。
図の通り、
②衝突していない
この2通りです。
一見関係なく思えますがそんなことはありません。
この2つの状態から、関数は以下のように呼び分けられます。
②の状態から、①の状態に移った時に呼び出される
①の状態から、①の状態を保った時に呼び出される
①の状態から、②の状態に移った時に呼び出される
これらを踏まえて理解すると、実装にどの関数を使えばよいのか判断しやすくなると思います。
Enterなどは格闘ゲームでいう「発生」のフレームを作れたりしそうですね。
Stayはダメージを受ける床などに活用できそうです。
Exitは謎解きゲームで、床から離れた時に仕掛けを動かす、などで活躍しそうです。
ソースコードや設定をキチンと整理し、なんとなくで済ましがちな知識もしっかり理解してあげればより一層のレベルアップが期待できると思います。
今回は以上です。
Unityはいいぞ。
コメント