質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

Q&A

解決済

1回答

1729閲覧

unity(C#)のシングルトン(get○○、set○○を使う場合)がうまくいかない

iceice

総合スコア2

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Unity

Unityは、Unity Technologiesが開発・販売している、IDEを内蔵するゲームエンジンです。主にC#を用いたプログラミングでコンテンツの開発が可能です。

0グッド

0クリップ

投稿2020/06/10 14:05

前提・実現したいこと

unityのC#で、「シーンAでスコアなどを表示、シーンBでスコアを10加算、シーンAにもどると加算された後の値に変わっている」など変数の値をシーン間で相互にやりとりできるようになりたく、シングルトンについて勉強しはじめました。
検索してみるとシングルトンではDontDestroyOnLoadを使う場合とget○○、set○○を使う場合がある印象を受けました。DontDestroyOnLoadを使う場合についてはあるサイトのスクリプトをコピーして実行するとうまくシーン間で値のやりとりができたのですが、get○○、set○○を使う場合について、 https://qiita.com/mczkzk/items/e20a8ee8a722a51ca1f8
のサイトを参考にさせていただいたのですが、思うようにできず、どうすれば良いか分かりません。どのようにすればうまくいくか教えていただきたく質問いたします。

(具体的には、シーンAとシーンBを用意し、それぞれに以下のスクリプトをつけています。また、各シーンでボタンを押すともう一方のシーンに遷移するようにしています。最初にシーンAからBへ移り、StartSinking関数をつけたボタンを押すとスコアが0から10に変わりsetされ、その後シーンAにもどるとDebug.Logの結果が0から10に変わっており、再びシーンBに移りStartSinking関数をつけたボタンを押せば前の結果がのこっていて10にさらに10足していくようになると思ったのですが、
実際にはシーンB内でボタンを複数回押せば10,20,,,と増えていきますが、その後シーンAに移った際のシーンAのDebug.Logや、再びシーンBに移ったさいにボタンを押した結果はまた0からになっており、値がうまく保持されていません。)

発生している問題・エラーメッセージ

なし

エラーメッセージ

該当のソースコード

C#

1<シングルトンクラス> 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class EventManager : MonoBehaviour { 7 8 private static EventManager mInstance; 9 private int num = 0; 10 11 public static EventManager Instance { 12 get { 13 if (mInstance == null) { 14 GameObject obj = new GameObject ("EventManager"); 15 mInstance = obj.AddComponent<EventManager> (); 16 } 17 return mInstance; 18 } 19 set { 20 21 } 22 } 23 24 25 26 27 public void setScore( int n ) { 28 this.num = n; 29 } 30 public int getScore() { 31 return this.num; 32 } 33 34}

C#

1<シーンAのオブジェクトにつけているもの> 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class ScoreManager : MonoBehaviour { 7 //シーンA 8 EventManager eventManager; 9 10 void Awake () 11 { 12 eventManager = EventManager.Instance; 13 } 14 15 void Update() 16 { 17 var score = eventManager.getScore(); 18 Debug.Log (score); 19 } 20} 21

C#

1<シーンBのオブジェクトにつけているもの> 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5 6public class EnemyHealth : MonoBehaviour { 7 //シーンB 8 EventManager eventManager; 9 10 void Awake () 11 { 12 eventManager = EventManager.Instance; 13 } 14 15 public void StartSinking () //ボタンにとりつけ 16 { 17 18 var currentScore = eventManager.getScore(); 19 Debug.Log (currentScore); 20 currentScore += 10; 21 eventManager.setScore(currentScore); 22 } 23} 24

C#

1<シーン遷移用> 2using System.Collections; 3using System.Collections.Generic; 4using UnityEngine; 5using UnityEngine.SceneManagement; 6 7public class button : MonoBehaviour { 8 9 // Use this for initialization 10 void Start () { 11 12 } 13 14 // Update is called once per frame 15 void Update () { 16 17 } 18 19 public void ToB(){//ボタンにつける 20 SceneManager.LoadScene ("B"); 21 } 22 23 public void ToA(){//ボタンにつける 24 SceneManager.LoadScene ("A"); 25 } 26 27} 28

試したこと

ネット上で検索しましたが、DontDestroyOnLoadを使わない場合についてはあまり情報が得られず、シングルトンとは別でgetter/setterについても検索してみましたが知識不足で解決方法が分かりませんでした。

補足情報(FW/ツールのバージョンなど)

ここにより詳細な情報を記載してください。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

シングルトンとシーン間での変数維持は別の話です。
シングルトンは「**そのシーン上で(そのタイミングで)**そのクラスのインスタンスが必ず1つであることを保証するデザインパターン」でしかありません。
また、getter/setterは変数やメソッドの取り扱いの話であり、これを使っているからシングルトンというわけでもありません。(=シングルトンでないクラスでもgetter/setterを持っていい)

なのでシーン間での変数維持をしたい場合は(シングルトンであるか否かに関わらず)DontDestroyOnLoadを使う・static変数を使う・セーブロードをする等が必要です。

投稿2020/06/11 00:14

sakura_hana

総合スコア11427

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

iceice

2020/06/11 07:21

ご回答ありがとうございます。 シングルトンとシーン間での変数維持は別の話なのですね。完全に混乱していました。 教えていただいた内容から自分なりに以下のように整理したのですが、このような理解で大丈夫でしょうか。重ねての質問で恐縮ですが、これも全然違うということでしたら再びご指摘いただけると幸いです。よろしくお願い致します。 ・シーン間での変数維持をしたい場合はあくまで<方法1:static変数を使う>または<方法2:DontDestroyOnLoadを使う>を基本にする。(セーブロードについてはまだ全く分からないため省略させていただきます。) ・方法2のとき、DontDestroyOnLoadが複製して存在しないように、シングルトンを利用していることがある。 ・方法1、2いずれにおいても、getA関数やsetA関数はなくても変数の値の変更や取得はできる。 ・つまりgetA関数、setA関数はシーン間での変数共有には特に必要ない。シングルトンは方法2のときのみ使う。
sakura_hana

2020/06/11 08:07

概ねいずれも合っています。補足として、 ・つまりgetA関数、setA関数はシーン間での変数共有には特に必要ない。 →必須ではないですが使ってもいいです。 getter/setterの話も、シングルトンやシーン間での変数維持とは別の話です。(クラスの「カプセル化」について調べると理解が進むと思います) ・シングルトンは方法2のときのみ使う。 →方法1の時でも使ってもいいです。というか処理内容次第ではシングルトンにした方がいい場合もあります(複数の同じ処理を行わせないことで負荷軽減する等)。
iceice

2020/06/11 09:20

さっそくご返信を下さり感謝致します。概ね合っているとのことで安心しました。 補足についてもとても勉強になりました。 理解を深められるよう頑張ります、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問