使い勝手のいいフラグ管理方法を考えたい。
要件
- シングルトンでフラグを管理するクラス
- インスペクタでフラグの状態がすぐに分かる
<enum, bool>
なDictionary変数でフラグ情報の保持
やること
インスペクタでDictionaryを見るためにSerializableDictionary アセットをインポートする
このアセットの SerializableDictionary Exampleシーンを元にする。
追加するファイル
MyFlagManager.csを追加
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using UnityEngine;
public class MyFlagManager : MonoBehaviour
{
private static MyFlagManager instance = null;
public static MyFlagManager Instance
{
get
{
if (instance == null)
{
instance = FindObjectOfType<MyFlagManager>();
if (instance == null)
{
instance = new GameObject("MyFlagManager").AddComponent<MyFlagManager>();
}
}
return instance;
}
}
void Awake()
{
if (Instance == this)
{
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
[SerializeField]
FlagBoolDictionary m_enumBoolDictionary;
public IDictionary<Flag, bool> EnumBoolDictionary
{
get { return m_enumBoolDictionary; }
set { m_enumBoolDictionary.CopyFrom(value); }
}
private void Start()
{
ResetFlags();
}
void Reset()
{
ResetFlags();
}
void ResetFlags()
{
EnumBoolDictionary.Clear();
foreach (var i in Enum.GetValues(typeof(Flag)).Cast<Flag>())
{
EnumBoolDictionary.Add(i, false);
}
}
public enum Flag
{
Key1,
Key2,
Key3,
}
}
InstanceとかAwakeとかはシングルトンのための設定。
Start()でEnumの要素でDictionaryを初期化しているけど無くても良さそう。(実行時にどんなフラグがあるかがインスペクタから一覧で見えて便利というだけ)
Enum Flagに管理したいフラグをどんどん追加していく。
MyExample.csを追加
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
public class MyExample : MonoBehaviour
{
// Start is called before the first frame update
void Start()
{
bool a = MyFlagManager.Instance.EnumBoolDictionary[MyFlagManager.Flag.Key1];
Debug.Log(a);
}
// Update is called once per frame
void Update()
{
if (Input.GetKeyDown(KeyCode.Space))
{
MyFlagManager.Instance.EnumBoolDictionary[MyFlagManager.Flag.Key2] = true;
}
}
}
MyFlagManagerの動作確認用のスクリプト。
MyFlagManager.csとMyExample.csを適当なオブジェクトにアタッチ。
編集するファイル
UserSerializableDictionaries.csに以下の行を追加
[Serializable]
public class FlagBoolDictionary : SerializableDictionary<MyFlagManager.Flag, bool> {}
UserSerializableDictionaryPropertyDrawers.csに以下の行を追加
[CustomPropertyDrawer(typeof(FlagBoolDictionary))]
実行
スペースキーを押すとKey2がTrueに変わるはず。
補足
MyFlagManagerをアタッチした際になぜかDictionaryのsetterの部分でエラーが出る。
NullReferenceException: Object reference not set to an instance of an object
MyFlagManager.ResetFlags () (at Assets/SerializableDictionary/Example/MyFlagManager.cs:59)
MyFlagManager.Reset () (at Assets/SerializableDictionary/Example/MyFlagManager.cs:54)
UnityEditorInternal.InternalEditorUtility:HierarchyWindowDragByID(Int32, HierarchyDropMode, Transform, Boolean)
UnityEngine.GUIUtility:ProcessEvent(Int32, IntPtr, Boolean&)
そのためアタッチ時の Reset() によるインスペクタへの値の反映がうまく効かない。
ほぼ見た目の問題なので、気になるならアタッチしたオブジェクトのインスペクタからMyFlagManagerのResetを選択してDictionaryのリセットを掛ける。
参考:
One thought on “ゲームのフラグ管理を考える”