読者です 読者をやめる 読者になる 読者になる

(:3[kanのメモ帳]

個人ゲーム開発者kan.kikuchiのメモ的技術ブログ。月木更新でUnity関連がメイン。

MonoBehaviourを継承し、初期化メソッドを備えたシングルトンなクラス【Unity】

Unity

このエントリーをはてなブックマークに追加

この記事でのバージョン
Unity 5.3.4f1 Personal


はじめに

さて、今回はシングルトンなクラスのお話。

そもそもシングルトンとは、以下のようなデザインパターンの一つです。

Singletonパターンを用いると、そのクラスのインスタンスが1つしか生成されないことを保証することができる。

Singleton パターン - Wikipedia


何かを管理するマネージャークラスなど、インスタンスが複数あると困る場合に使われる手法で、

MonoBehaviourがStaticにできないため、Unityでもよく使われます。




今回は上記記事を参考に、自分なりにシングルトンなクラスを作成してみました。

なお、タイトル通りAwakeやStart以外に初期化メソッドを備えています!


SingletonMonoBehaviour

早速コードから!

なお、ジェネリックってなんぞ?な方はこちらの記事を読むとよりわかり易いと思います。




このSingletonMonoBehaviourを継承することで、シングルトンパターンのクラスを実装できます。

using UnityEngine;

public class Manager : SingletonMonoBehaviour<Manager>{

  //初期化メソッド(初アクセスまたはAwake時のどちらか一度だけ実行される)
  protected override void Init(){
    base.Init ();

    /*初期化処理を色々と*/
  }

}


使い方は以下のような感じで、

Instanceにアクセスすることで、メソッドの実行などが行えます。

Manager.Instance.Hoge();


他のクラスからFindでインスタンスを探す必要もありませんし、

Inspectorからアタッチする必要もありません。


しかも初アクセス時またはAwake時にインスタンスを生成し、初期化するので

いつアクセスしても大丈夫!


ただし、シーン内に二つ以上存在する時やシーン内に存在しないのにアクセスするとエラーになります。

エラーでなく、片方を削除したり、新しく生成した方がいいんですかね?要検討。


Awakeは使わない

SingletonMonoBehaviourの初期化処理はAwakeではなくInitで行います。

なお、InitはAwake時かその前の初アクセス、どちらか一度しか行われません。


間違って初期化処理を書かないように

Awakeはsealedしてるので、継承先でoverrideするとエラーが出ます。

まぁ、overrideしなきゃ普通に使えちゃうんですけどね……。


Init


そもそも、なんでInitがあるかという所なんですが、

「アクセスした時に初期化が必ず完了してるため、いつでもアクセスできる」

という実装にしたかったからです。


参考記事のようにAwakeでもアクセス可能なものはありますが、

この時、シングルトン側のAwakeに初期化処理が実装されていて、かつ、Awake前にアクセスすると、

シングルトン側の初期化処理が済んでいないことになります。


なので、結局Awake以降(Startとか)にアクセスしなくてはならなくなるので、

そこを改良しようとしたらこのような形になりました。


静的コンストラクタ

初期化に静的コンストラクタを使う方法も考えたのですが、

あまりUnityでの開発時に使われてなさそうなので試してません。

コンストラクターの代わりに Awake を使用してください。これはコンポーネントの serialized ステートはコンストラクト時点では定義されていないためです。



初期化に静的コンストラクタを呼ぶと死ぬ。エディタでは死ななくてもビルド後のiOSとかAndroidとかで死ぬ。




おわりに

Overrideを使わなければ継承先でAwakeを使えたり、

初期化処理のためだけでにMonoBehaviourWithInitというクラスを作っていたり、

納得のいった形ではないのですが、自分の力ではこれが精一杯でした……。


なにかもっと良い方法があればご一報を!


------追記


全てのシーンに存在し、かつ、一つしかいないマネージャー的な存在

の実装方法についても記事にしたので、こちらも参考にどうぞ!