任意のInterfaceを実装したクラスを取得するメソッドを実装しました
こんにちは、ここあです。
前回、インタフェース活用例でちらっとお話した、自前の拡張メソッドを紹介したいと思います。
これに関しては、前回の記事で紹介したものと違い、インタフェースについて調べてるときにどこかで見た気がしますが……?
もしかしたら誰かが同じような実装をしているかもしれませんが、備忘録として書いておこうと思います。
実装詳細
きっかけ
今回紹介するメソッドですが、複数シーンを同時に運用している関係上、各シーンごとのオブジェクトを、各管理クラスが明確に把握した状態で運用できるように、考えた結果行きついた答えのひとつです。これを関数の呼び出しのみで行いたかった為に実装しました。
前回の記事Unityゲーム開発で役立つインタフェース活用例 - ここぷろ!で紹介した通り、拡張メソッドになります。
ジェネリクスを使い、任意のインタフェースを実装した、全てのクラスを取得してくる拡張メソッドです。
処理手順
基本的にシーンが生成された直後のAwake()のタイミングで動かすことを前提として作っています。
- まず、存在する全てのコンポーネントがアタッチされたオブジェクトを取得。
- as演算子により、指定のインタフェースにアップキャストできるか判定。
- ゲーム動作中のメモリを少しでも確保するために、念のため可変長のListから、固定長配列に格納して返しています。
このメソッドは、Manager等の管理クラスから呼ばれることになる為、使いやすさを考慮してstaticメソッドとして定義しました。
使用する場合は、以下の様に一行の関数呼び出しで使えるようになっています。
// 格納配列変数宣言 private IMasterObj[] masterObjArray; // オブジェクト取得 var masterObjArray = InterfaceUtils.FindObjectOfInterfaces<IMasterObject>();
実装コード
using System.Collections.Generic; using UnityEngine; /// <summary> /// Interface便利クラス /// </summary> public class InterfaceUtils { /// <summary> /// 特定のインタフェースがアタッチされたオブジェクトを見つける /// </summary> /// <typeparam name="T"> 探索するインタフェース </typeparam> /// <returns> 取得したクラス配列 </returns> public static T[] FindObjectOfInterfaces<T>() where T : class { List<T> findList = new List<T>(); // オブジェクトを探索し、リストに格納 foreach (var component in GameObject.FindObjectsOfType<Component>()) { var obj = component as T; if (obj == null) continue; findList.Add(obj); } T[] findObjArray = new T[findList.Count]; int count = 0; // 取得したオブジェクトを指定したインタフェース型配列に格納 foreach (T obj in findList) { findObjArray[count] = obj; count++; } return findObjArray; } }
終わりに
使う場面は限られるかもしれませんが、ある程度の一括管理などをしている場合には、結構いい感じに使えるんじゃないかなと思います。
私の場合は特にUpdateも、なるべくUnity本来のコールバックを使用しない形での実装を目指しているので、重宝しています。
まだ改善できる箇所があるような気がしているので、よりよい実装があれば教えて頂けるとありがたいです。
それでは、今回はこの辺りで。