i-school - アイテム取得処理の実装例
 特定のボタンを押した際にアイテムを取得する機能の実装例です。

 アイテムに触れたら自動的にアイテムを取得するタイプの実装方法ではありません。









設計


 特定のボタンを押した際に、コライダーを持つ見えないゲームオブジェクトをプレイヤーの周囲に展開し、
そのコライダーの範囲内にあるゲームオブジェクトを精査して、アイテムであった場合には取得するという機能です。

 具体的なアイテムの効果などは含みませんので、その部分については別途、実装をおこなってください。

 アイテムの判定方法について、ここでは複数のアプローチを提示します。
取得時の機能(コライダーの展開部分)は、すべて同じ機能を利用しています。

 なお記事自体は3D用ですが、2Dでも応用可能です。


1.タグによる判定方法


 もっとも一般的で、実装が容易な方法です。



 <= クリックすると開きます。




 事前にタグを作成し、検出される側(アイテム側)にタグを設定しておく必要があります。
また、タグによる判定は文字列であるため、大文字小文字の区別がありますので、間違えないように作成してください。

 構文内では、if 文によるネスト(入れ子構造)を深くならないように、continue をしています。

 条件が成立したら、という形で処理を作るだけではなく、条件が成立しなかったら、という形で処理を作ることが出来ます。


<Physics.OverlapSphere メソッド>


 Unity の Physics クラスに用意されているメソッドの1つです。球体形のコライダーを一時的に生成し、他のコライダーとの侵入判定を行うことができます。
判定結果として、Collider 配列型の戻り値を持ちます。

 他にも .OverlapBox メソッド、OverlapCapsule メソッドがあり、それぞれに形状が違います。戻り値はいずれも Collider 配列型で同じです。


// キャラクターを中心に、radius を半径とした円形のコライダーを作成し、その範囲内にあるすべてのコライダーを検出して配列にする
Collider[] hitColliders = Physics.OverlapSphere(transform.position, radius); 

 OverlapSphere メソッドを実行すると、第1引数の位置を始点に、第2引数の値を半径とした円形のコライダーを展開します。
このとき、このコライダーの範囲内にある、別のゲームオブジェクトのコライダーを検出し、それらをまとめて配列に入れて戻り値として提供します。

 そのため今回のように、コライダー配列型の変数を用意しておくことで代入し、以降の処理で利用していくことが出来ます。

 このメソッドには OverlapSphereNonAlloc メソッドも用意されており、こちらの方がガベージを生成しない分優れていますが、事前に配列の長さを指定しなければなりません。
利用方法を理解できてきたら、リファクタリングして処理の置き換えにチャレンジしてみるとよいでしょう。


参考サイト
Unity 公式スクリプト・リファレンス
Physics.OverlapSphere
Unity 公式スクリプト・リファレンス
Physics.OverlapSphereNonAlloc



 2D用も用意されてます。
メソッド名は OverlapSphere ではなく、OverlapCircle メソッドと OverlapCircleNonAlloc メソッドです。


参考サイト
Unity 公式スクリプト・リファレンス
Physics2D.OverlapCircle
Unity 公式スクリプト・リファレンス
Physics2D.OverlapCircleNonAlloc


2.レイヤーによる判定


 先ほど利用している Physics.OverlapSphere メソッドの引数には第3引数と第4引数があり、こちらには初期値が代入されています。
そのため、第2引数まで指定すれば利用できるようになっています。

 第3引数にはレイヤーの指定ができるため、その場合、Physics.OverlapSphere メソッドを実行すると、メソッドの範囲内にある、指定したレイヤーのみを配列として取得出来ます。
そのため、if 文による判定を省略できます。


 <= クリックすると開きます。




 事前にレイヤーを作成し、インスペクターで検出したいレイヤーを指定します。
また、検出される側(アイテム側)にレイヤーを設定しておく必要があります。

 利点としては、Physics.OverlapSphere メソッドで検出されるコライダーをふるいにかけて、指定したレイヤーの情報のみで戻り値を作成できることです。
そのため、配列の中身はすべて指定したレイヤーのコライダーのみであることが保証されるため、タグとは異なり、if 文による判定が不要になっています。


3.クラスによる判定方法


 前述のレイヤーをベースに、処理の実用的にして効率化をおこなった構文です。


 <= クリックすると開きます。




 アイテム処理の抽象化をベースに、ItemBase クラスを取得できるかを確認しています。
タグやレイヤーでの判定の場合、アイテムの効果を利用するタイミングで別途、アイテムのクラスの取得(GetComponent メソッド)が必要になりますが
こちらのアプローチであればすでにクラスを取得しているので GetComponent メソッドが不要です。(すぐに命令が出せます。)

 できる限り、タグやレイヤーでの判定ではなく、クラスでの判定を行うようにします。
そしてレイヤーについては、活用できる部分では上手く組み合わせていきましょう。


<発展形>イベント駆動型による実装例


 UniRx の機能を利用して、ボタンの判定をイベント駆動型にリファクタリングしたものです。
アイテムの判定方法は【3.クラスによる判定方法】を採用しています。


 <= クリックすると開きます。




 Update メソッド内で処理していたボタンの押下確認処理を Start メソッド内でのボタンの購読処理にリファクタリングしています。


まとめ


 このようにアイテムの判定方法だけでも複数のアプローチがあります。
色々な方法を実装し、学習しておくことでスキルの幅が広がります。