見出し画像

Singletonっていう凄いやつを知った(Unity、C#)

Unityでデータ共有したい!
結果、Singletonパターンというデザインパターンにたどり着いたのでここに残す


知識の整理のために書いてます。
この内容はFacebookの「Unityユーザー助け合いどころ」で教えてもらったことです。(Facebookで私を助けてくれた方、本当にありがとうございます)

1.データ共有!!

全ては以下URLに書いてある。
自分は読んだだけだと意味が理解できなかった…
理解できなかったことを書く

どこでもデータ共有
つまり、
1.データ(変数)を1つのオブジェクト(クラス)にまとめる
2.そこへのアクセスでデータを管理!

ってこと。
それを実現するためにSingletonっていうデザインパターンを使う。

2.Singletonとは?

Singleton パターン(シングルトン・パターン)とは、オブジェクト指向のコンピュータプログラムにおける、デザインパターンの1つである。
~中略~
そのクラスのインスタンスが1つしか生成されないことを保証するデザインパターンのこと

  Wikipedia Singleton パターン   より

はい、大切なのは

クラスのインスタンスが1つしか生成されないことを保証する
つまり、

共有したいクラスのインスタンスが1つ
(以下instanceとする)

あるクラス(class A)がinstanceを編集

他のスクリプト(class B)からinstanceを見る

class Aで編集したことが維持されてる!

ってこと。まあ、インスタンスが1つしかないから、当たり前だけど、これでデータ共有ができるのだ!

3.C#スクリプトでは…

先程説明したことをどうC#で実現するのか、、
1.データ共有 のURLに載ってるコードの通り。
その重要な部分は

public class DataManager : MonoBehaviour {
	private static DataManager instance;

	public static DataManager Instance{
		get{
			if( null == instance ){
				instance = (DataManager)FindObjectOfType(typeof(DataManager));
				if( null == instance ){
					Debug.Log(" DataManager Instance Error ");
				}
			}
			return instance;
		}
	}

	void Awake(){
	    //省略
	}
}

これのInstanceっていうプロパティ!

4.仕組み

2行目
private static DataManager instance;

ここで共有したいクラス型のインスタンスを宣言
このインスタンスがSingletonでのただ1つのインスタンスだ。
privateでstaticなことが重要である。

プロパティ部分
public static DataManager Instance{
get{   //省略
   return instance;

get-onlyプロパティである。そして戻り値が先程のprivateでstaticなインスタンスだ。

これで
2行目で作ったインスタンス(instance)はプロパティ(Instance)によってのみ取得可能である。

なぜならinstanceはprivateであるため外部から触れられない。また、get-onlyなプロパティによりinstanceの内容を書き換えることもできないからだ。

5.スクリプト全体を見る/使ってみる

1.データの共有 で書いたURLのスクリプトを少し編集する。
int型のtest という変数を共有する、

public class DataManager : MonoBehaviour {

    //共有する変数
    public int test;

    //データの共有に使うインスタンス
	private static DataManager instance;

    //インスタンスを取得できる唯一のプロパティ
	public static DataManager Instance{
		get{
            //nullチェック
			if( null == instance ){
				instance = (DataManager)FindObjectOfType(typeof(DataManager));
				if( null == instance ){
					Debug.Log(" DataManager Instance Error ");
				}
			}
			return instance;
		}
	}
    
    //シーン間でもインスタンスのオブジェクトが1つになるようにする
	void Awake(){
		GameObject[] obj = GameObject.FindGameObjectsWithTag("DataManager");
		if( 1 < obj.Length ){
			// 既に存在しているなら削除
			Destroy( gameObject );
		}else{
			// シーン遷移では破棄させない
			DontDestroyOnLoad( gameObject );
		}
	}
}

ほかのスクリプトから参照は以下のように

//代入
DataManager.Instance.test = 3;

//取得
int huga = DataManager.Instance.hoge;

6.「使う」を詳しく

代入、についてはじめスクリプトをみたとき、何をやっているのか私はわからなかった。(Facebook で教えてもらった)

<代入>
DataManager.Instance
ここで、まず、インスタンスを取得する。インスタンスは読み込み専用(readOnly)である。なので、ここには代入は不可である。

.test = 3;
次にここで、先程取得したインスタンスを参照して、test 変数に3を代入する。
インスタンスはreadOnlyだが、test変数はpublicである。
なので、test変数はreadOnlyにはならない。参照だから、
インスタンスという住所はreadOnlyだけど、中身の変数はpublicなのだ!

7.まとめ

データ共有したい!
がきっかけで、Singletonパターンというデザインパターンをしることができた。

Singletonは言語によって様々な実装方法があるが、unityC#における実装方法を理解できた。

Singletonによるデータ共有はstatic変数より使いやすいのではないかと思っている。

「Singletonっていう凄いやつを知った(Unity、C#)」終

いいなと思ったら応援しよう!