自作ObjectID OnGUI検索機能

# 自作Objectsを検索する機能

##目的
 * ゲーム内ステータスを持つオブジェクトを便利に管理するため

##基本理念
 * ゲーム内カスタムデータを持つオブジェクトに一意性のIDを待たせる
 * GameObjectsManagerでそれらのオブジェクトを管理する
 * Debug OnGUIでHelperを作成

## 実装手順
 1. ObjectsBaseData.cs作成
 
 ```
 public class ObjectBaseData : MonoBehaviour
{
   public long _id;
   public OBJ_TYPE _type = OBJ_TYPE.type1;
}
 ```
 2.作成したものを、検索対象となるオブジェクトにつける

```
public class ObjectClass : ObjectBaseData
{
}
```

3.GameObjectsManagerを作成

```
//linq追加
using System.Linq;
public enum OBJ_TYPE
{
 type1,
 type2,
}
public class GameObjectsManager : MonoBehaviour
{
  private static GameObjectsManager _instance = null;//シングルトンにしようか。
  private static long _indx = 0;
  private static Dictionary<long , ObjectBaseData> _objDic = new ...
  void SetInstance(GameObjectsManager mgr)
  {
   _instance = mgr;
  }
  void GameObjectsManager Get()
  {
   return _instance;
  }
  void Awake()
  {
    SetInstance(this);
   　_objDic.Clear();//一応初期化しとく
  }
  public long RigisterObject(ObjectBaseData objData)
  {
    while(objDic.ContainsKey(_indx)
    {
     _indx++;
    }
    objDic.Add(indx,_objData);
    return _indx;
  }
  public ObjectBaseData GetObjectByID(long id)
  {
    //検索要素一個なので、Dictionaryのデフォルト機能の方が速い気がする。
    if(objDic.ContainsKey(id))
    {
       return objDic[id];
    }
    return null;
  }
 //////////////////////////////////////////////
 //もちろん、enumでObjectTypeを追加したりは自由です。例えば、Linqを使って
 public List<ObjectBaseData> GetObjectByType(OBJ_TYPE t)
 {
   return objList.Where(v => v.value._type == t).Select(r => r.value).ToList();
 }
}
```
完成したら、Scene上のSystemManagerレベルオブジェクトに追加する。
4. ObjectClassを修正する

```
 void Awake()
 {
   _id = GameObjectsManager.Get(). RigisterObject(this);
 }
```
を追加する。
5. OnGUIを書こう！

```
  //using省略
  public class DebugSearch : EditorWindow
  {
    [MenuItem("Debug/DebugSearch", true)]
    static bool CheckWnd(){return true;}
    [MenuItem("Debug/DebugSearch")]
    static void OpenObjectsSearcher()
    {EditorWindow.GetWindow< DebugSearch >("DebugSearch");}

    List<ObjectBaseData> objList = new ...
    Vector2 scrPos = Vector2.Zero;
    public OBJ_TYPE op;
    public long id;

    void OnGUI()
    {
      GUILayout.BeginVertical("box");
      {
       GUILayout.BeginHorizontal();
       {
           op = (ObjectType)EditorGUILayout.EnumPopup("Select by Type:", op);
           if (GUILayout.Button("Search!", GUILayout.Width(50)))
           {
                    SearchByType();
           }
        }   
       GUILayout.EndHorizontal();   
       GUILayout.BeginHorizontal();
       {
         GUILayout.Label("Search by ID:");
         id = int.Parse(EditorGUILayout.TextArea(id.ToString(),GUILayout.Width(50.0f)));
         if (GUILayout.Button("Search!", GUILayout.Width(50)))// && isSearchFinished)
         {
           SearchById();
         }
       }
       GUILayout.EndHorizontal();
      UpdateList();
      }
      GUILayout.EndVertical();
    }
    void SearchByType()
    {
        objList.Clear();
        objList = GameObjectsManager.Get(). GetObjectByType(op);
    }
    void SearchById()
    {
        objList.Clear();
        var obj = GameObjectsManager.GetInstance(). GetObjectByID(id);
        if (obj != null)
        {
            objList.Add(obj);
        }
    }
    void UpdateShow()//Listの更新
    {
        if (objList == null || objList.Count <= 0) { return; }
        scrollPosition = GUILayout.BeginScrollView(scrollPosition);
        foreach (var obj in objList)
        {
            GUILayout.BeginHorizontal();
            {
                if (obj == null) continue;
                GUILayout.Label(obj._id.ToString(), GUILayout.Width(40.0f));
                EditorGUILayout.ObjectField(obj, typeof(ObjectBaseData), true);
            }
            GUILayout.EndHorizontal();
        }
        GUILayout.EndScrollView();
    }
  }
```
もちろん、この部分はエラーがなければ、上のMenu欄にDebugが出るので、ほっとけば大丈夫。

#補足
* _objDic にはもちろん、該当オブジェクトが消された場合の対応が必要である。例えば、UnRigisterを実装し、Ojbectが破棄されるときに実行する。
* managerの書き方は人それぞれ、普通はシングルトンの親クラスで書くが、ここでは割愛する。
* ここで記載しているソースは、本人実装手順と一例を説明するために、大まかに書いたものである。そのため、そのまま使用すると、動作する保証は全くない。参考まで・