5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

MonoBehaviour用のSingletonに別れを告げる

Posted at

基底クラスを消費するSingletonがあまり好みでないので、以下のようなServiceLocator的に参照を得るスタイルを試している。

ComponentLocator.cs
public class ComponentLocator {
	static ComponentLocator instance;
	public static ComponentLocator Instance {
		get {
			if (instance == null) {
				instance = new ComponentLocator();
			}
			return instance;
		}
	}

	Dictionary<Type, WeakReference> cache = new Dictionary<Type, WeakReference>();

	public TComponent Get<TComponent>() where TComponent : Component {
		Type compType = typeof(TComponent);

		WeakReference compRef;
		if (cache.TryGetValue(compType, out compRef)) {
			var target = compRef.Target as TComponent;
			if (target) {
				return target;
			} else {
				Uncache(compType);
			}
		}

		var comp = GameObject.FindObjectOfType<TComponent>();
		if (comp) {
			Cache(comp);
			return comp;
		}

		GameObject go = new GameObject(compType.Name, compType);
		comp = go.GetComponent<TComponent>();
		if (comp) {
			Cache(comp);
			return comp;
		}

		return null;
	}

	// 初回のFindObjectOfTypeも回避したければ、Script Execution Orderを引き上げた後、Awake()でCache()を呼んでおく。
	public void Cache(Component comp) {
		cache[comp.GetType()] = new WeakReference(comp);
	}

	public void Uncache(Type compType) {
		cache.Remove(compType);
	}

	public void ClearCache() {
		cache.Clear();
	}
}

こう使う。

void Awake() {
	foo = ComponentLocator.Instance.Get<Foo>();
}

void Update() {
	foo.bar();

	// まぁ、Getは長命なコンポーネントならコスト小さいので以下でもよい。
	ComponentLocator.Instance.Get<Foo>().bar();
}

対象のコンポーネントはシーンに置いといてもいいし、なければ呼び出し時に作られる。
シーンをまたいで存在しうるかはComponentLocatorでは関知しないので、必要ならコンポーネント実装側でDontDestroyOnLoadすること。

このスタイルが気に入っているのは、Singletonっぽいなと思いつつも考えるの後回しにしてて、とりあえずインスタンスはひとつしかないからAwake内でFindObjectOfTypeして使う。という怠惰な姿勢と合うこと。かな。

5
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?