自作Objectsを検索する機能
##目的
- ゲーム内ステータスを持つオブジェクトを便利に管理するため
##基本理念
- ゲーム内カスタムデータを持つオブジェクトに一意性のIDを待たせる
- GameObjectsManagerでそれらのオブジェクトを管理する
- Debug OnGUIでHelperを作成
実装手順
- 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の書き方は人それぞれ、普通はシングルトンの親クラスで書くが、ここでは割愛する。
- ここで記載しているソースは、本人実装手順と一例を説明するために、大まかに書いたものである。そのため、そのまま使用すると、動作する保証は全くない。参考まで・