質問: Unityにて横スクロールアクションゲームを作っています。 ステージ選択画面においてステージ解放処理を行いたいです。 sceneCountでクリア画面をロードした場合、countの値を増やして switch文で条件分岐させ、countの値でステージ選択ボタンを解放しようと思っています。 ### 1.ボタンを非表示にさせ、switch分の処理による解放の関連付け ### 2.sceneCountのスクリプト(ステージは4種類あります。) 現在書いているスクリプトはこちらになります。 ``` public void LoadScene(){ Debug.Log(SceneManager.sceneCount); // 1 SceneManager.LoadScene(1, LoadSceneMode.Additive); Debug.Log(SceneManager.sceneCount); // 2 SceneManager.LoadScene(1, LoadSceneMode.Additive); Debug.Log(SceneManager.sceneCount); // 3 SceneManager.LoadScene(1, LoadSceneMode.Additive); Debug.Log(SceneManager.sceneCount); // 4 } ``` ### 3.どのシーンのゲームオブシェクトにスクリプトをつければいいのか 現在はこのような構成になっています。 ・選択画面 (switch文) ・クリア画面 (sceneCount) ### 4.sceneCountとswitch文の関連付け こちらの4つを教えていただきたいです。 C#、Unity共に初めて扱うので分かりやすくスクリプト付きで説明していただけると助かります。
回答: 「質問への追記・修正の依頼」の通り、よく分からない点が多いのですが、以下のソースで何か過不足などはありますでしょうか? (選択画面のゲームオブジェクトにアタッチしてください) ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class StageSelect : MonoBehaviour { // Inspectorからシーン上のボタンを登録しておく public Button[] ButtonArray; void Start() { // countの値を取得 int count = /*countの値*/; for (int loop = 0; loop < ButtonArray.Length; loop++) { if (loop < count) { // ボタンの有効化 ButtonArray[loop].gameObject.SetActive(true); // ボタン押下時の処理 int stageNo = loop; ButtonArray[loop].onClick.AddListener(() => { taskOnClick(stageNo); }); } else { // ボタンの無効化 ButtonArray[loop].gameObject.SetActive(false); } } } void taskOnClick(int stageNo) { /* stageNoに応じてステージのシーンをロードする処理 */ } } ``` 追記: そもそも「解放」の意味自体の認識が合っているか分からなくなってきました。 * 進行に合わせてステージをアンロックする(第1ステージをクリアしたら第2ステージを解放する) * ボタンをシーンに配置し、そのシーンを呼び出す形でボタンを生成し、ボタンを押下したらそれらのシーン全てを削除する 私は前者だと思って先ほどの回答をしました。 もし後者であれば、ボタンをシーンに配置するのではなく、ボタンをプレハブ化してそれを生成するのがよいと思います。 この場合、新しいシーンを呼び出す際に`SceneManager.LoadScene()`を`LoadSceneMode.Additive`無しで実行すれば、全てリセットされます。 この方法が難しい場合は、配列やリストにプレハブから生成したボタンを格納し、適当なタイミングでそれらをまとめて削除してしまえばよいでしょう。 コメントを受けて追記: > > ゲームクリア画面をロードした回数でステージの開放をしたいと思っています。 > > > それであれば、どこかに変数(初期値0)を用意しておき、ゲームクリア画面をロードしたときに、その変数を+1すればよいです。 そしてその変数の値を、switch文のあるスクリプトに渡せばよいです。 > > 特定のシーン(ゲームクリア画面)が何回読み込まれたかを調べたいときはsceneCountではないのでしょうか?sceneCountが『現在ロードされているシーンの合計数。』と出てきたのでよくわからなくなってしまいました。 > > > いま使われているシーンの数です。 例えば、 1. 起動時に最初のシーン0がロードされるので、このときはsceneCount=1になります。 2. 次に`SceneManager.LoadScene(1, LoadSceneMode.Additive);`とすると、シーン0とシーン1があるので、sceneCount=2になります。 3. もう一度`SceneManager.LoadScene(1, LoadSceneMode.Additive);`とすると、シーン0と2つのシーン1があるので、sceneCount=3になります。 4. この後に`SceneManager.LoadScene(1);`とすると、全てのシーンを削除してから、新たにシーン1がロードされるので、sceneCount=1に戻ります。 いずれにしろ、`SceneManager.LoadScene(1, LoadSceneMode.Additive);`を使っている意味がよく分かりませんでした。 `SceneManager.LoadScene(1, LoadSceneMode.Additive);`とすると、前のシーンが残ったままになってしまいます。 自分で管理するのであれば問題ないですが、そうでなければ`LoadSceneMode.Additive`無しで実行し、毎回リセットしてしまった方がよいと思います。 この場合、sceneCountは常に1になりますが、前述の変数を使えば問題ありません。 また、前述の変数を格納しているスクリプトなど、リセット時に削除したくない物については、`DontDestroyOnLoad();`を使えばよいです。 コメントを受けて追記2: `Application.LoadLevel ();`と`SceneManager.LoadScene();`はどちらもシーンの切り替えを行う関数です。 `Application.LoadLevel ();`は非推奨になっている古い関数なため、stageクラスにある、`Application.LoadLevel ();`は全て`SceneManager.LoadScene();`に直した方がよいでしょう。 また、stageクラスでボタン押下時にステージを呼び出す処理をしているので、StageSelectでの押下時の処理は不要です。 それらを踏まえたうえで、スクリプトを書くとすると以下のようになります。 ・クリア画面のゲームオブジェクトにアタッチ ``` using System.Collections; using System.Collections.Generic; using UnityEngine; public class ClearCount : MonoBehaviour { // クリア回数 // staticにすることで新しいシーンを読み込んだ時でも削除されなくなる public static int Count = 0; void Awake() { // クリア回数をカウントする Count++; } } ``` ・ステージ選択画面のゲームオブジェクトにアタッチ ``` using System.Collections; using System.Collections.Generic; using UnityEngine; using UnityEngine.UI; public class StageSelect : MonoBehaviour { // Inspectorからシーン上のボタンを登録しておく public Button[] ButtonArray; void Start() { // countの値を取得 int count = ClearCount.Count; for (int loop = 0; loop < ButtonArray.Length; loop++) { // ボタンの有効化・無効化 ButtonArray[loop].gameObject.SetActive(loop < count); } } } ``` ただ、上記はあくまで質問の内容に添っただけなので、例えば「ステージ1を2回クリアした」場合については考慮していません。 また、セーブも行っていないため、アプリを終了するとステージ1からやり直しになります。