【Unity】『Is Trigger』が2つを分かつ!
本日のテーマ

「当たり判定」と「トリガー」の2つを分ける
「Is Trigger」について

 

当たり判定」を詳しく知りたい方
⇒ 「『当たり判定』の設定方法を詳しく解説!

「トリガー」を詳しく知りたい方
⇒ 「『Trigger』の設定方法を詳しく解説!

「当たり判定」と「トリガー」の違いを詳しく知りたい方
⇒ 「『Collider』をマスター!

 

 

もくじ

1.『Is Trigger』とは
2.『Is Trigger』の設定方法
3.『Is Trigger』の使用上の注意
4.『Is Trigger』のまとめ
 

 

『Is Trigger』とは

Is Trigger」とは、Colliderコンポーネントの設定の一つであり、

「当たり判定」と「トリガー」を区別するための重要な項目となります。

 

具体的な話をすると、

GameObjectは「Collider」がアタッチされることで、

衝突により力を受けるといった物理挙動が行えるようになるわけですが、

この「Is Trigger」にチェックを入れることで、物理挙動を行えなくし

(物理エンジンから無視されることで物理的接触がなくなる)、

トリガー」として利用することができるようになります。

 

 

『Is Trigger』の設定方法

「トリガー」を発生させたい場合は、

GameObjectに「Collider」を取り付けて、「Is Trigger」にチェックを入れる。

「当たり判定」を発生させたい場合は、

GameObjectに「Collider」を取り付けて、「Is Trigger」にはチェックを入れない。

 

「Is Trigger」にチェックを入れると、物理的接触がなくなり「トリガー」となり、

「Is Trigger」のチェックを外すと物理的接触が起こり「当たり判定」が

行えるようになるわけです。

 

とても簡単に設定できるのですが、

よく間違えてはまってしまうポイントでもあります。

 

 

『Is Trigger』の使用上の注意

Is Trigger」のチェックの有無は非常に重要です。

 

当たり判定』を発生させたい、すなわち物理的接触を発生させたい場合には、

両方のオブジェクトの『Is Trigger』のチェックを外しておかなければなりません。

 

両方の』が重要です。

衝突する両方のオブジェクトの「Is Trigger」のチェックが外れている、すなわち

両方のオブジェクトが物理挙動可能な場合にのみ、「物理的接触」が発生します。

 

言い換えると、

どちらか一方でも『Is Trigger』のチェックが入っていると物理的接触は発生せず、

「トリガー」が発生することになってしまうのです。

 

まとめると、

・『当たり判定』は、両方のオブジェクトの『Is Trigger』のチェックを外す

・『トリガー』は、少なくとも一方の『Is Trigger』にチェックを入れる

 

しっかり覚えておいてくださいね。

 

では、「当たり判定」と「トリガー」を同時に発生させたい!

となった場合にはどうすればよいのか。

 

そんなときは、

「Is Trigger」にチェックを入れたColliderと、チェックを外したCollider、

この2つを1つのオブジェクトにアタッチしてあげれば解決できます。(画像5image5

 

 

『Is Trigger』のまとめ

・『当たり判定』は、両方のオブジェクトの『Is Trigger』のチェックを外す

・『トリガー』は、少なくとも一方の『Is Trigger』にチェックを入れる

これが全てです。

 

「当たり判定」と「トリガー」の違いは、「Is Trigger」のチェックの有無

だけでなく、使用できる関数がそれぞれで決まっていますので

使用する際は注意してください。

そのあたりの詳しいことは個別の記事をご覧ください。

 

「当たり判定」を詳しく知りたい方
⇒ 「『当たり判定』の設定方法を詳しく解説!

「トリガー」を詳しく知りたい方
⇒ 「『トリガー』の設定方法を詳しく解説!

 

これで、『Is Trigger』が2つを分かつ!の解説を終わります。

 

【Unity】さよならエラー!『Find関数』を深く理解する!
本日のテーマ

GameObjectの検索&取得に使われる
「Find関数」について

Unityにおいて、オブジェクトを取得・検索するために使われる「Find」関数。

間違った使い方をすると、エラーが発生するだけでなく、ゲームが重くなる原因にもなります。

「Find」関数を正しく使い、快適なUnityライフを目指しましょう。

 

 

もくじ

1.『GameObject.Find』について
  1.『GameObject.Find』とは
  2.『GameObject.Find』の使用例
  3.『GameObject.Find』の使用上の注意
2.『Transform.Find』について
  1.『Transform.Find』とは
  2.『Transform.Find』の使用例
  3.『Transform.Find』の使用上の注意
3.『GameObject.Find』と『Transform.Find』の比較
4.具体例で理解を深める
5.Find関数のまとめ

 

 

GameObject.Findについて

 

GameObject.Findとは

GameObject.Find」は、Hierarchyから指定した「GameObject」を取得する関数です。

 

使用例

・GameObject.Find(“example”);

・GameObject.Find(“Parent_1/Parent_2/example”);

 

使用上の注意

「GameObject.Find」は、Hierarchy内の全オブジェクトを検索して

指定したGameObjectを見つけ出すため、時間もかかり重くなる原因になります。

完成品のゲームでの使用は極力控えた方が良いみたいです。

 

代わりとして「GameObject.FindWithTag」を使うか、

子オブジェクトの検索の場合には「Transform.Find」を使うようにしましょう。

どうしても使用したいのであれば、Start関数Awake関数の中だけにすることです。

 

GameObject.Find」では、

指定したGameObjectが非アクティブ(チェックが入っていない)だった場合には、

取得することができない(nullが返される)ということにも注意が必要です。

 

非オブジェクトの取得に関しては例外があるみたいです。

 

GameObject.Find(“example”);

このように直接オブジェクトを指定して取得する場合には、

非アクティブでの取得は絶対にできないのですが、

 

GameObject.Find(“Parent_1/Parent_2/Parent_3/example”);

このようにスラッシュ(/)を使ったパス付きで指定して取得する場合には、

非アクティブであっても「一部」取得できるみたいです(Unityのバグの可能性も?)。

1階層目(Parent_1)と2階層目(Parent_2)が非アクティブでさえなければ

3階層目以降の非アクティブなオブジェクトは取得することができます

 

例えば、

「Parent_1 > Parent_2 > Parent_3 > example」 という構成になっている場合、

Parent_1とParent_2がアクティブでありさえすれば、

Parent_3やexampleが非アクティブであっても

GameObject.Find(“Parent_1/Parent_2/Parent_3/example”);

これでexampleを取得することができます。

 

逆にいえば、Parent_1かParent_2が非アクティブであったなら

exampleがアクティブであったとしてもnullが返ってきて取得することはできません。

不思議な話です・・・。

 

非アクティブなGameObjectを取得したい場合には、

無難に「Transform.Find」を使用するほうが良いですね。

 

 

Transform.Findについて

 

Transform.Findとは

Transform.Find」は、子オブジェクトから指定した「Transform」を取得する関数です。

 

使用例

・this.transform.Find(“example”);

・this.transform.Find(“child_1/child_2/example”);

 

使用上の注意

取得されるのが「GameObject」ではなく「Transform」であることに注意が必要です。

Transform.Find」では、子オブジェクトが検索の対象となっています。

Transform.Find」では、アクティブ・非アクティブに関係なく取得することできます。

 

 

2つの比較

 

GameObject.Find

・「GameObject」を検索&取得する

・Hierarchy内すべてが検索対象となる

・基本的には非アクティブなGameObjectは取得できない

 

Transform.Find

・「Transform」を検索&取得する

・子オブジェクトが検索対象となる

・非アクティブなGameObjectのTransformも取得できる

 

 

「GameObject.Find」と「Transform.Find」の説明が終わりましたので、

具体例をみて、さらに理解を深めていきましょう。

 

 

具体例で理解を深める

以下ようなファイル構成になっている場合のGameObjectの取得方法を見ていきましょう。

スクリプトは「Parent_1」にアタッチしているものと考えてください。

 

基礎1. 「target_1」を取得してみましょう

 

GameObject.Findを使った場合

例1)GameObject target = GameObject.Find(“target_1”); ※取得できません

例2)GameObject target = GameObject.Find(“Parent_1/Parent_2/target_1”);

target_1が非アクティブなので、基本は取得できませんが、

例2の場合には取得することができます。ただしこの方法は用いないほうが良いですね。

 

Transform.Findを使った場合

例1)Transform target = this.transform.Find(“Parent_2/target_1”);

例2)GameObject target = this.transform.Find(“Parent_2/target_1”).gameObject;

Transform.Findを使えば、target_1が非アクティブでも取得可能ですね。

注意が必要なのは、Transform.Findを使ったときは「Transform」で取得されることです。

例2では「.gameObject」として、TransformからGameObjectを取得しています。

 

 

基礎2. 「target_2」を取得してみましょう

 

GameObject.Findを使った場合

今回の場合、GameObject.Findの使用ではtarget_2を取得することはできません。

 

Transform.Findを使った場合

例1)Transform target = this.transform.Find(“Parent_3/target_2”);

例2)GameObject target = this.transform.Find(“Parent_3/target_2”).gameObject;

と、非アクティブでも問題なく取得することができます。

 

 

応用 .「target」を取得してみましょう

少し複雑なパターンも練習しておきましょう。

以下ような構成になっていて、スクリプトが”Script”にアタッチされている場合です。

 

“Script”にスクリプトがアタッチされているため、

this.transform.Find(“Parent_2/target”);

このように直接”子オブジェクト”を探す書き方ができません。

 

一旦、targetの親オブジェクトで「アクティブ」になっているParent_2を取得し、

そのあとでtargetを取得する、という手順を踏みます。

1.GameObject temp = GameObject.Find(“Parent_1/Parent_2”);

2.GameObject target = temp.transform.Find(“target”).gameObject;

この手順を踏めば、非アクティブなtargetも取得することができます。

 

上記を1つにまとめて書くこともできます。

GameObject target = GameObject.Find(“Parent_1/Parent_2”).transform.Find(“target”).gameObject;

こんな感じになります。

 

どうでしたでしょうか。

子オブジェクトの検索しかできないですが、非アクティブでも取得できる「Transform.Find」は便利ですね。

 

ちなみに、以前は子オブジェクトを取得するために、Transform.FindChildとい関数が使われていましたが(現在も使うことはできますが)、古い型なので使用しないように注意しましょう。

 

 

Find関数のまとめ

GameObject.Find」はゲームを重くする原因になるので、極力使用は避けるべきです。

代わりとして「GameObject.FindWithTag」や「Transform.Find」を利用する。

どうしても使いたいなら、Start()Awake()だけでの使用に限る。

非アクティブのGameObject取得には「Transform.Find」を利用してください。

 

【Unity】NullReferenceExceptionのエラーと対策
本日のテーマ

「NullReferenceException」の原因と対策

 

NullReferenceExceptionとは

NullReferenceException』とは、

オブジェクトの参照が切れているときに発生するエラーのことです。

 

もっと噛み砕いた言い方をするなら、

「そんなオブジェクト見つからないよ?」

「どのオブジェクトのことをいってるの?」

と、このよう状況のときに発生するエラーです。

 

エラーメッセージの内容

UnityエディターのConsole(コンソール)画面に、

このようなエラーメッセージが表示されます。

エラーメッセージ2行目に、

エラーが発生した関数(Example.Start())と、

エラーが出たファイルとその行数(Assets/Scripts/Example.cs:12)

が表示されています。

 

エラーが起こった場所の特定に利用できます。

このエラーメッセージをダブルクリックすることで、

エラー箇所に飛ぶ(そのスクリプトを開く)こともできるので非常に便利です。

 

3つの原因と対策

では、どういった場面で「NullReferenceException」のエラーが起こるのか。

ポイントは3つです。

 

スクリプトで定義した変数の初期化を行っていない

このスクリプトでは、

“player”というGameObjectを定義しているが、初期化が行われずに使用されています。

 

[原因]

スクリプトで定義したGameObjectを、初期化することなく使用した。

 

[対策]

Find関数を使ってシーン内(Hierarchy)からGameObjectを取得したり、

Prefabを使ってGameObjectを生成するなどして、

しっかりと初期化を行ってください。

 

こちらが、Find関数を使った正しいスクリプトになります。

 

 

続いては、

上記のようにFind関数を使って、しっかりと初期化したにもかかわらず、

NullReferenceExceptionのエラーが出る場合です。

 

Find関数でGameObjectの取得に失敗している

スクリプトには問題ないが、NullReferenceExceptionのエラーが出る場合があります。

これはFind関数を使ってGameObjectを取得している場合に発生して、

原因は2つあります。

 

[原因1]

そもそも指定したGameObjectがScene内に存在していない

存在していないのだから取得できなくて当然ですよね。

もちろん、指定したGameObject名のスペルミスの場合も同様です。

 

[対策]

Scene内(Hierarchy)にGameObjectが間違いなく存在していること、

指定したGameObject名に間違いがないことを確認してください。

 

 

[原因2]

Find関数で取得するGameObjectが非アクティブになっている。画像2image2

見落としがちですが、

GameObjectが非アクティブ、すなわち「チェックが外れた状態」になっていると、

GameObject.Findでは、GameObjectを取得することができずにnullが返されます。

結果、NullReferenceExceptionのエラーが発生します。

 

[対策]

GameObjectをアクティブに設定することです。

どうしても非アクティブのままにしたい場合には、

GameObject.Find()ではなく、Transform.Find()を使用するようにしてください。

説明すると長くなってしまうので、当記事では割愛させていただきますが、

詳しくは「さよならエラー!『Find関数』を深く理解する!」をご覧ください。

 

 

インスペクターでGameObjectの初期化を行っていない

UnityエディタのInspector(インスペクター)で、

初期化しなければならないGameObjectの初期化を忘れている場合にも、

NullReferenceExceptionのエラーが発生します。


[原因]

インスペクターでGameObjectの初期化を行っていない。

 

[対策]

エラーメッセージを見て、

エラーが出ているスクリプトがアタッチされているGameObjectのインスペクターで、

GameObjectを正しく設定してください。

 

まとめ

NullReferenceExceptionのエラーが発生したときのチェックポイントです。

1.スクリプトで定義したGameObjectの初期化し忘れがないか

2.Find関数を使っている場合、GameObjectの指定を間違っていないか

3.GameObject.Findを使っている場合、GameObjectが非アクティブになっていないか

4.インスペクター上で、GameObjectの初期化し忘れがないか

 

これで、NullReferenceExceptionのエラーと対策の解説を終わります。

 

【Unity】オブジェクトが壁をすり抜ける!そんなときの対策
本日のテーマ

多くのUnityユーザーを「壁抜け」で悩ませている
『Collision Detection』について

 
オブジェクトの速度が速くなったときにオブジェクトをすり抜けてしまう

といった方は、当記事を読めば1分とかからず解決できることでしょう。

 

通常の「当たり(衝突)判定」がうまくいっていない方は、こちらをどうぞ。
⇒ 「『当たり判定』の設定方法を詳しく解説!

 

では、解説を始めます。

何はともあれ、最初に対処法をお話しします。

 

オブジェクトの「すり抜け」対処法

「すり抜け」が発生するオブジェクトには、『Rigidbody』がアタッチされていますね?
 

POINT

Rigidbodyの「Collision Detection」の項目を「Continuous」に設定します。 

 
これで解決できるはずです。

もしこれで解決できない場合は、申し訳ありませんが当記事ではお役に立てません。

 

 

それでは、

Collision Detection」について解説していきます。

まずはRigidbodyの説明から。

 

『Rigidbody』とは

Rigidbodyとは、オブジェクトの物理挙動を可能にするためのコンポーネントです。

Rigidbodyをつけることで、重力の影響を受けるようになったり、

オブジェクトとの衝突時に衝突の影響により動く、といった物理挙動が可能になります。

 

『Collision Detection』とは

Rigidbodyの設定に『Collision Detection』という項目があります。

この設定は「Collision(衝突)」と名前に入っている通り、

「当たり判定」に大きく関わってくる設定項目となっています。

 

Unityでゲームを作っていて、「オブジェクトの速度が速いと壁をすり抜けてしまう」

なんて現象に悩まされたことがある方もいるのではないでしょうか。

この「速度が速いと壁をすり抜ける」という部分に大きく関わっているのが

Rigidbodyの『Collision Detection』という設定なのです。

 

オブジェクトが高速で動いていると、物理計算が行われている間に、

オブジェクトが壁をすり抜け、通り越してしまうということが起こってしまいます。

そんなときにどういった処理を行うのかということが、

この『Collision Detection』により決定されます。

 

Collision Detection」には、

「Discrete」と「Continuous」の2つの設定があります。

Discrete(不連続): 最も新しい位置で接触判定を行う

Continuous(連続): 最初に衝突が発生した位置で接触判定を行う

 

「Discrete」では “最も新しい位置” で接触判定が行われるので、

壁をすり抜けてしまった場合、そのすり抜けた位置で接触判定が行われます。

一方「Continuous」では “最初に衝突が発生した位置” で接触判定が行われるので、

たとえ壁をすり抜けたとして、壁との最初の接触位置で接触判定が行われます。

 

要約すると、

Point

Discrete」に設定していると壁抜けが起こり得て、

「Continuous」に設定していると壁抜けの心配がなくなる

ということですね。

 

ゲームにおいて高速に動くオブジェクトが存在せず、壁抜けの心配がないのであれば、

Discrete」に設定しておくのがよいでしょう。こちらの方が処理速度が速いですから。

すべてのRigidbodyを「Continuous」に設定しておくのはナンセンスです。

 

というわけで、

壁抜けにお困りの方は、この「Collision Detection」の設定を見直して見てください。

 

※当記事では、オブジェクトをすり抜けることを、便宜上「壁抜け」や「壁のすり抜け」と表現させていただいておりますことをご了承ください。

 

【Unity】『Collider』をマスターする!
本日のテーマ

『当たり判定』や『トリガー』きの要となる
「Collider」をマスターしよう!

 

当記事は、出来るだけわかりやすく書いておりますが、

Colliderを迷わず使いこなす!」そんな内容になっているため、

正直言って長いです。

 

もし、単純に設定だけを知りたいという場合には、以下をご覧ください。

「当たり判定」の設定方法
⇒ 「『当たり判定』の設定方法を詳しく解説!

「Trigger」の設定方法
⇒ 「『Trigger』の設定方法を詳しく解説!

「壁すり抜け」に困っている方
⇒ 「オブジェクトが壁をすり抜けるときの対処法

 

 

『Collider(コライダー)』について

それでは、ゲーム制作には欠かせない「Collider」について説明していきます。

 

Colliderとは

Collider」とは「当たり判定」や「トリガー」を利用するときに、

ゲームオブジェクトにつける図形(形状)のことです。

 

「Collider」をキャラクターのGameObjectにアタッチすると、

Scene画面において以下のような緑色の図形が表示されます。

余談ですが、オブジェクトにColliderなどを付けることを『アタッチする』といいます。

この緑色の「Collider」同士が接触することにより、

「当たり判定」や「トリガー」が発生するわけです

ですので、接触するすべてのオブジェクトに「Collider」をつける必要があります。

「Collider」のついていないGameObjectには、「当たり」は発生しないので、

背景なんかのGameObjectには付ける必要がないですね。

 

 

では、「Collider」にはどのような種類があるのでしょうか。

 

Colliderの種類

・Circle Collider 2D :円形
・Box Collider 2D :正方形・長方形
・Polygon Collider 2D :多角形
・Edge Collider 2D :線で自由に描く
・Capsule Collider 2D :円形・ひし形
・Composite Collider 2D :BoxCollider2DとPolygonCollider2Dの融合型

・Box Collider :立方体
・Sphere Collider :球体
・Capsule Collider :円柱
・Mesh Collider :メッシュに基づくコライダー
・Wheel Collider :陸上車用の特殊コライダー
・Terrain Collider :Terrain Dataに基づくコライダー

特殊なものも含めてこんな感じになります。用途に合わせて使い分けましょう。

 

1つのGameObjectに複数の「Collider」をアタッチするのは問題ありません。

「Collider」を組み合わせて、理想の「当たり」を作り上げましょう。

とはいえ、処理の問題もあるので付けすぎには注意してください。

 

 

上記の「Collider」一覧を見ていると、

2Dのついたものとついていないものの2種類あるが・・・

 

Colliderの2Dと3Dの違い

Collider」には2D用のColliderと3D用のColliderがあります。

2Dオブジェクトには、2DのついたColliderを、

3Dオブジェクトには、2DのついていないColliderを使うことになります。

 

 

上記の「Collider」一覧で太字で表記されたものがあるが・・・

 

Colliderの正しい使い方

太字になっている「Collider」はプリミティブなコライダーと呼ばれ、

単純な構造ゆえ負荷が小さい(ゲームが重くなりにくい)Colliderとなっています。

それ以外のCollliderは複雑な構造で非常に負荷が大きいため、

極力使用を控えたほうが良いみたいです。

うまくプリミティブなコライダーを組み合わせて使うのが正しい使い方のようです。

 

 

オブジェクトに『Collider』をつけることで「当たり判定」や「トリガー」が発生する

ということは分かったけど、

「当たり判定」では物理的な接触が起こるが、「トリガー」では物理的な接触は起きない

2つにはこのような決定的な違いがあるのに、『Collider』だけで大丈夫なの?

どうやって使い分けるの?

というわけで、続いては『Collider』の設定を見ていくことにしましょう。

 

『Collider』の設定方法

何はともあれ、「当たり判定」や「トリガー」を行いたいGameObjectに

Collider」をアタッチします。

GameObjectに「Collider」をアタッチして、初めて「当たり」が発生します。

 

Colliderの設定

今回は、TestObjectを作って、そこに「Box Collider 2D」をアタッチしてみました。

EditColliderというボタンをクリックすることで画像3image3

Scene画面でコライダー(緑の枠)のサイズや位置を変更することができます。

下部にあるSizeやOffsetから直接数値を入力することでも変更可能です。画像4image4

基本の設定は以上となります。

 

では、「当たり判定」と「トリガー」の区別をつける設定はどこになるか。

それは「Is Trigger」という項目になります。

 

『両方の「Is Trigger」のチェックが外れていると「当たり判定」が発生し、

いずれか一方の「Is Trigger」にチェックが入っていると「トリガー」が発生します』

 

両方の「Is Trigger」のチェックが外れているときのみ「当たり判定」が発生する

ということをしっかり覚えておいてください。

 

「Is Trigger」に関する詳しいことはこちらの記事をお読みください。

『Is Trigger』が2つを分かつ!

 

 

これで『Collider』に関する話が一通りが終わりましたので、

具体例をみながら、さらに理解を深めましょう。

 

『Collider』の理解を深める

具体的な例を見ていき、より「Collider」の理解を深めていきましょう。

 

Colliderの具体例

以下のようなものを用意してみました。

登場するのは、「Unityちゃん」と「床」と「Trigger」です。

「Trigger」には画像を設定していないので、ゲーム画面には表示されません。

単なる「トリガー」なので、ゲームをプレイする人には見える必要がないですよね。

実際のトリガーはもっと小さなもので良いのですが、

今回は見やすいようにこの大きさにしています。

「Unityちゃん」が「床」を歩いていて、接触する大きさであればよいので、

本当に小さいもので大丈夫です。

 

この3つのGameObjectすべてに『Collider』をアタッチして、

「Unityちゃん」と「床」には「Is Trigger」のチェックを入れず、

「Trigger」にのみ「Is Trigger」のチェックをいれています。

 

ここでやりたいことは、「Unityちゃん」が「床」の上を歩いていき、

「Trigger」に接触すると、「床」が開いて「Unityちゃん」が穴に落ちる

といったことです。

 

では、説明していきます。

まず「Is Trigger」のチェックが外されている「Unityちゃん」と「床」との間には

物理的な接触が起こり当たり判定」が発生します。

なので「Unityちゃん」が「床」より下に落ちてしまうことはありません。

両方の「Is Trigger」のチェックが外れている』がポイントですね。

※「Unity」ちゃんには重力がかかっている想定でお願いします。

 

では、「床」と「Trigger」はどうでしょうか。

「Is Trigger」にチェックが入った「Trigger」と、

「Is Trigger」にチェックが入っていない「床」なので、

物理的接触は起こらず「トリガー」が発生する・・・のかと思いきや、

画像にも書いてある通り、実は何も発生しないのです

 

そうなんですね。

「Collider」がついているだけでは、

「当たり判定」や「トリガー」といった『接触』は発生しないのです。

これらの『接触』を発生させるには、「Collider」以外にもう一つ

Rigidbody(あるいはRigidbody2D)』というものが必要になります。

 

Rigidbody』とは、オブジェクトの物理挙動を可能にするためのコンポーネントで、

「当たり判定」「トリガー」を行うための必須コンポーネントとなっています。

 

『Rigidbody』に関してはこちらの記事をご覧ください。

⇒『オブジェクトが壁をすり抜ける!そんなときの対処法

「Rigidbody」の「当たり判定」が関わる部分を詳しく解説しております。

 

そういうわけで、「当たり判定」や「トリガー」を発生させるには、

Collider」に加え、『Rigidbody』がアタッチされている必要があるのです

どちらか一方のオブジェクトにアタッチされていれば大丈夫です。

 

では、改めて「当たり判定」「トリガー」が発生する条件をまとめますと、

・両方のオブジェクトに『Collider』がアタッチされている

・少なくとも一方のオブジェクトに『Rigidbody/Rigidbody2D』がアタッチされている

となります。

 

Collider』に加え、『Rigidbody』のアタッチも忘れないようにしてください。

 

 

「Unityちゃん」へと話を戻します。

今回の場合は「Unityちゃん」にRigidbody2Dがアタッチされています。

そのため「Unityちゃん」と「床」との間には物理的接触である「当たり判定」が発生し、

「床」と「Trigger」の間には何も発生しなかったのです。

 

では、

「Unityちゃん」が右方向に進んでいき、「Trigger」と接触したらどうなりますか?

 

考えてみてくださいね。

Unityちゃん:Rigidbody + Collider(Is Trigger はチェックなし)

Trigger:Collider(Is Triggerにチェックあり)

 

答えは、

「Unityちゃん」と「Trigger」の間には物理的接触が発生しないため

「Unityちゃん」は何事もなく右方向へと進んでいくことになります。

「Unityちゃん」が「Trigger」と接触している間は、「トリガー」が発生しています。

大丈夫ですね?

 

 

ところで、

「Unityちゃん」と「Trigger」の接触により、

トリガー」が発生するのは理解できたけど、

落とし穴に落とすという話はどうなったの?

これが次のテーマになります。

 

『衝突』を検知する関数

ここからはスクリプトを触ることになります。

 

「当たり」の発生を検知する関数

物理的接触(当たり判定)が発生したときには、下記6つの関数が呼び出されます。

OnCollisionEnter2D
OnCollisionStay2D
OnCollisionExit2D

OnCollisionEnter
OnCollisionStay
OnCollisionExit

言うまでもないですが、2Dがついている関数は2D同士の「当たり判定」に、

2Dがついていない関数は3D同士の「当たり判定」に使用します。

ですので、「BoxCollider2D」をアタッチしているオブジェクトで使用する関数は、

「OnCollisionEnter」ではなく「OnCollisionEnter2D」となりますので、

書き間違えには十分注意してください。

 

では、「Enter」「Exit」「Stay」の3つの違いは何かというと、

OnCollisionEnter」は、物体同士が接触した瞬間の1回のみ呼び出され、

OnCollisionExit」は、物体同士が離れた瞬間の1回のみ呼び出されます。

OnCollisionStay」に関しては、物体同士が接触している間、常に呼び出されます。

 

実際のスクリプトの書き方は、このようになります。

C#でのコードですが、新しく「CollisionScript」という名前でスクリプトを作成し、

6つの「当たり判定」用の関数を書き足してみました。

「当たり判定」だけを行いたいなら 最初のStartやUpdateの関数は不要ですし、

「当たり判定」用の関数も自分で必要なものだけを書けば良いです。

2Dの「当たり判定」なら3D用の関数は不要で、3Dなら2D用の関数は不要ですね。

 

このスクリプトを「当たり判定」を検知したいオブジェクトにアタッチします。

そうすることで、衝突が発生したときに、

スクリプトに記述した該当関数の中に処理が入ってきます。

 

関数を見ていると『Collision』や『Collision2D』という文字(変数)がありますが、

「Collision」には、衝突したオブジェクトの情報が格納されています。

「Collision」に関しては、こちらの記事で解説しております。

⇒「『Collision』を理解する

 

 

以上で「当たり」の発生を検知する関数の説明を終わります。

続いては、「トリガー」の発生を検知する関数です。

 

「トリガー」の発生を検知する関数

「当たり判定」とは使用する関数が違っています。

・OnTriggerEnter2D
・OnTriggerStay2D
・OnTriggerExit2D

・OnTriggerEnter
・OnTriggerStay
・OnTriggerExit

「当たり判定」では「Collision」だった箇所が「Trigger」に変わっていますね。

使い方に関しては、「当たり判定」と全く同じです。

 

では、実際の書き方ですが、新しく「TriggerScript」という名前でクラスを作成しました。

「当たり判定」では、取得できる情報が「Collision」になっていたのに対し、

「トリガー」では「Collider」になっています。

Collider」はもうわかりますよね。

「トリガー」では、接触した相手の「Collider」情報のみを取得することができます。

 

ここまで読んでこられた方なら、もうわかりますよね。

「Unityちゃん」を「穴」へ落とす方法のことです。

詳しい処理は省略しますが、

このように「OnTriggerEnter2D」の関数内に、床を消すなどの処理を書いておけば、

「Unityちゃん」が「Trigger」に接触した瞬間に、床を消すことが実現できそうです。

 

 

かなり長くなってしまいましたが、ようやくすべての説明が終わりました。

お疲れさまでした。

「当たり判定」や「トリガー」というのは、ゲームを作るうえで必須の項目なので、

繰り返し読んで、ぜひ使いこなせるようになってください。

使いこなせるようになっても、どうしてもミスはしてしまいます。

そんなときは、もう一度一から設定を見直してみてください。

 

 

項目別の設定方法まとめ

それでは最後に、項目別の設定方法をまとめておきます。

 

「当たり判定」を行う設定_2D編

・少なくとも一方のオブジェクトに『Rigidbody2D』をアッタッチします
・両方のオブジェクトに任意の『Collider2D』をアタッチする
・両方の『Collider2D』の『Is Trigger』のチェックを外す
・利用できるスクリプトはこちらです。

 

 

「トリガー」を行う設定_2D編

・少なくとも一方のオブジェクトに『Rigidbody2D』をアッタッチします
・両方のオブジェクトに任意の『Collider2D』をアタッチする
・少なくとも一方の『Collider2D』の『Is Trigger』にチェックをつける
・利用できるスクリプトはこちらです。

 

 

「当たり判定」を行う設定_3D編

・少なくとも一方のオブジェクトに『Rigidbody』をアッタッチします
・両方のオブジェクトに任意の『Collider』をアタッチする
・両方の『Collider』の『Is Trigger』のチェックを外す
・利用できるスクリプトはこちらです。

 

 

「トリガー」を行う設定_3D編

・少なくとも一方のオブジェクトに『Rigidbody』をアッタッチします
・両方のオブジェクトに任意の『Collider』をアタッチする
・少なくとも一方の『Collider』の『Is Trigger』にチェックをつける
・利用できるスクリプトはこちらです。

 

 

最後になりましたが、

「当たり判定」の発生を検知したいのに「OnTriggerEnter」を使ってしまったり、

逆に「トリガー」の発生を検知したいのに「OnCollisionEnter」を使ってしまったり、

また、関数や変数名の2Dの有無にも十分気を付けてください。

 

ユニティちゃんライセンス

当記事の画像内で登場する2D・3Dキャラクターは、
ユニティちゃんライセンス条項の元に提供されています

 

これで、『Collider』をマスターする!の解説を終わります。

 

【Unity】UIが表示されない!チェックすべき13のポイント
本日のテーマ

CanvasにUIが表示されなくなったときの
チェックすべき13のポイント

13のポイントをチェックすることで、CanvasにUIが表示されない悩みを解決することができるでしょう。

 

UIが表示されないパターンには、

Unityエディタでどのように表示されるかで以下の3つに分けることができます。

この3つのパターンに分けて、解説していきます。

 

「Scene」と「Game」のどちらにも表示されない画像1image1

この場合、主に「Canvas」と「目的のUI」の設定が原因になっていることが多いです。

 

Check.1

『Canvas』が存在していて、有効になっていること

UIがしっかりとCanvasに属しているか確認してください。UIの親を辿っていき、Canvasがアタッチされたオブジェクトの子(孫)になっていますか?
UIはCanvasに属していないと表示されませんよ。
Canvasが有効(チェックが入っている)になっていることも確認してください。画像2image2

 

<補足>
※説明中に「UIの親オブジェクト」という単語が頻繁に登場しますが、
「UIの親オブジェクト」とは、UIの直接の親だけでなく、UIの親の親、UIの親の親の親と、自分が属するCanvasにたどり着くまでの「すべての親」のことを指しています。ですので「UIの親オブジェクトを確認する」とあった場合には、UIからCanvasにたどり着くまでのすべての親オブジェクトを確認するようにしてください。

 

Check.2

目的のUIが有効になっていること画像3image3

当然ですがUIが有効(チェックが入っている)になっていなければ表示されません。

 

Check.3

目的のUIが画面に映る範囲に配置されていること

もしUIが画面外に配置されているなら、表示されるはずがありません。仮に、UIのx,y座標を両方0にしてみてください。画像4image4もしUIにCanvasを除く親オブジェクトが設定されているなら、そちらの座標も0にしてください。そうすることでCanvasの中央にUIが表示されるようになります。

 

Check.4

目的のUIの親オブジェクトが有効になっていること画像5image5

2同様、UIの親オブジェクトも有効になっていることを確認してください。親オブジェクトが無効になっていると、子オブジェクトも表示されません。

 

Check.5

目的のUIの親オブジェクトのScaleが限りなく小さな値になっていないこと画像6image6

UIの親オブジェクトのScaleが0ないしはそれに近い数値に設定されていないか確認してください。
親オブジェクトのScakeは子オブジェクトにも影響するので、親オブジェクトのScaleが0だと子オブジェクトは表示されなくなります。

 

Check.6

複数のCanvasに属する場合、すべてのCanvasが有効になっているか画像7image7

UIの親オブジェクトをたどっていったとき、複数のCanvasが存在している(複数のCanvasに属している)とき、一つでも無効(チェックが外れている)になっていると、その子にあたるUIは表示されません。

 

Check.7

目的のUIがCanvasGroupに属するとき、そのAlpha値が限りなく小さな値になっていないこと画像8image8

UI自身あるいは親オブジェクトにCanvasGroupがアタッチされているとき、そのAlpha値が0あるいはそれに近い値になっていないかを確認してください。CanvasGroupはアタッチされたオブジェクトの子オブジェクトのUIをまとめて制御するためのものであり、CanvasGroupのAlphaが0に設定されると、それに属する子オブジェクトのAlphaがすべて0に設定されます。

 

Check.8

目的のUIが属するCanvasにCanvasScalerがアタッチされているとき、そのScaleFactor値が限りなく0に近い値になっていないこと画像9image9

UIが属するCanvasにCanvasScalerがアタッチされている場合、そのScaleFactorの値が0に近い値になっていると、UIは表示されません。

 

 

「Scene」には表示されるが…画像10image10

この場合、主に『Canvas』の設定に問題があります。

Canvas」の「RenderMode」別にみていきます。

 

RenderModeが『ScreenSpace-Overlay』の場合

Check.9

GameとCanvasのTargetDisplayが同じになっていること画像11image11

Gameのdisplay設定とCanvasのTargetDisplayが同じでないと、UIは表示されません。TargetDisplayはCamera毎に設定されるものなので、UIの表示を行いたいCameraに指定したTargetDisplayを画像12image12、CanvasのTargetDisplayに設定し、またGame画面で表示を行うためにGameのdisplay設定も同じに設定します。

 

RenderModeが『ScreenSpace-Camera』の場合

Check.10

GameとCameraのTargetDisplayが同じになっていること

最初に、CanvasのRenderCameraに、表示を行いたいCameraが設定されているかを確認し画像13image13、次に、そのCameraのTargetDisplayとGameのdisplay設定が同じになっているかを確認してください。画像14image14

 

Check.11

CanvasのPlaneDistanceの値が小さい、あるいは極端に大きくなっていないこと画像15image15

CanvasのPlaneDistanceが小さい(0に近い値)、あるいは極端に大きな値になっていた場合、UIが正常に表示されません。

 

Check.12

CameraのCullingMaskの設定で、UIのレイヤーが指定されていること画像16image16

CameraのCullingMaskの設定において、Nothingが指定されていたり、UIに設定したレイヤー名(初期では「UI」)のチェックが外れていないかを確認してください。
CullingMaskからチェックが外されたレイヤーは、そのカメラに描画されません。

 

RenderModeが『WorldSpace』の場合

基本的には、UIでないオブジェクトと扱いが同じになるので、しっかりカメラの範囲内にUIが配置されていることと、上記12のCullingMaskでチェックが外れていないことを確認してください。

 

 

「Game」には表示されるが…画像17image17

この場合は、Unityエディタ側の設定の問題です。

Check.13

UnityEditorのLayers設定項目でUIのレイヤーが非表示に設定されていないこと画像18image18

Unityエディタでは、Scene内に表示されるオブジェクトを非表示にできる設定があります。Unityエディタの画面右上の『Layers』で、目のマークをクリックすると非表示にすることができます。UIのレイヤーが非表示設定(目のマークがついていない)になっていないか確認してください。

 

 

最後に1点だけ、

きちんと設定したにもかかわらず、UIが正常に表示されない場合があります。

その場合はUnityEditorを再起動することで正常に表示されることもあります。

 

今までエラーなくできていたのに、急にエラーが出た、

なんてときには、一度UnityEditorの再起動を行うことをお勧めします。

それでエラーが解消されることもあります。

 

以上で、UIが表示されないときにチェックすべきポイントの解説を終わります。