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#)」終