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

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

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

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

Unity

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

Q&A

解決済

1回答

1634閲覧

Unity2D ステージ解放処理

FCB

総合スコア8

C#

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

Unity

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

0グッド

0クリップ

投稿2017/11/08 02:59

Unityにて横スクロールアクションゲームを作っています。

ステージ選択画面においてステージ解放処理を行いたいです。
sceneCountでクリア画面をロードした場合、countの値を増やして
switch文で条件分岐させ、countの値でステージ選択ボタンを解放しようと思っています。

###1.ボタンを非表示にさせ、switch分の処理による解放の関連付け

###2.sceneCountのスクリプト(ステージは4種類あります。)

現在書いているスクリプトはこちらになります。

C#

1public void LoadScene(){ 2Debug.Log(SceneManager.sceneCount); // 1 3SceneManager.LoadScene(1, LoadSceneMode.Additive); 4Debug.Log(SceneManager.sceneCount); // 2 5SceneManager.LoadScene(1, LoadSceneMode.Additive); 6Debug.Log(SceneManager.sceneCount); // 3 7SceneManager.LoadScene(1, LoadSceneMode.Additive); 8Debug.Log(SceneManager.sceneCount); // 4 9}

###3.どのシーンのゲームオブシェクトにスクリプトをつければいいのか

現在はこのような構成になっています。
・選択画面 (switch文)
・クリア画面 (sceneCount)

###4.sceneCountとswitch文の関連付け

こちらの4つを教えていただきたいです。
C#、Unity共に初めて扱うので分かりやすくスクリプト付きで説明していただけると助かります。

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

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

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

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

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

fiveHundred

2017/11/08 03:49 編集

以下の内容について、追記か返答をお願いします。 ・sceneCountが何のことを指すのか分かりません。これは自前のスクリプトでしょうか? ・「2.」でのスクリプトで何をしようとしているのが分かりません。また、「SceneManager.LoadScene(1, LoadSceneMode.Additive);」でどんなシーンをロードしようとしているのかも分かりません。 ・「4.」の関連付けとは具体的にどのようなことを指しているのでしょうか?
FCB

2017/11/10 01:17

説明不足で申し訳ございません。ゲームクリア画面をつくっており、ゲームクリア画面をロードした回数でステージの開放をしたいと思っています。sceneCountでロードした回数をswitch文で分岐させたいと思っています。現在はゲームクリア画面にsceneCountを書いており、ステージ選択画面にswitch文によるステージ解放処理のスクリプトを書いています。
FCB

2017/11/10 02:00

特定のシーン(ゲームクリア画面)が何回読み込まれたかを調べたいときはsceneCountではないのでしょうか?sceneCountが『現在ロードされているシーンの合計数。』と出てきたのでよくわからなくなってしまいました。
guest

回答1

0

ベストアンサー

「質問への追記・修正の依頼」の通り、よく分からない点が多いのですが、以下のソースで何か過不足などはありますでしょうか?
(選択画面のゲームオブジェクトにアタッチしてください)

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5 6public class StageSelect : MonoBehaviour 7{ 8 // Inspectorからシーン上のボタンを登録しておく 9 public Button[] ButtonArray; 10 11 void Start() 12 { 13 // countの値を取得 14 int count = /*countの値*/; 15 16 for (int loop = 0; loop < ButtonArray.Length; loop++) 17 { 18 if (loop < count) 19 { 20 // ボタンの有効化 21 ButtonArray[loop].gameObject.SetActive(true); 22 23 // ボタン押下時の処理 24 int stageNo = loop; 25 ButtonArray[loop].onClick.AddListener(() => { taskOnClick(stageNo); }); 26 } 27 else 28 { 29 // ボタンの無効化 30 ButtonArray[loop].gameObject.SetActive(false); 31 } 32 } 33 } 34 35 void taskOnClick(int stageNo) 36 { 37 /* stageNoに応じてステージのシーンをロードする処理 */ 38 } 39}

追記:
そもそも「解放」の意味自体の認識が合っているか分からなくなってきました。

  • 進行に合わせてステージをアンロックする(第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での押下時の処理は不要です。

それらを踏まえたうえで、スクリプトを書くとすると以下のようになります。

・クリア画面のゲームオブジェクトにアタッチ

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4 5public class ClearCount : MonoBehaviour 6{ 7 // クリア回数 8 // staticにすることで新しいシーンを読み込んだ時でも削除されなくなる 9 public static int Count = 0; 10 11 void Awake() 12 { 13 // クリア回数をカウントする 14 Count++; 15 } 16}

・ステージ選択画面のゲームオブジェクトにアタッチ

C#

1using System.Collections; 2using System.Collections.Generic; 3using UnityEngine; 4using UnityEngine.UI; 5 6public class StageSelect : MonoBehaviour 7{ 8 // Inspectorからシーン上のボタンを登録しておく 9 public Button[] ButtonArray; 10 11 void Start() 12 { 13 // countの値を取得 14 int count = ClearCount.Count; 15 16 for (int loop = 0; loop < ButtonArray.Length; loop++) 17 { 18 // ボタンの有効化・無効化 19 ButtonArray[loop].gameObject.SetActive(loop < count); 20 } 21 } 22}

ただ、上記はあくまで質問の内容に添っただけなので、例えば「ステージ1を2回クリアした」場合については考慮していません。
また、セーブも行っていないため、アプリを終了するとステージ1からやり直しになります。

投稿2017/11/08 06:17

編集2017/11/14 07:39
fiveHundred

総合スコア9774

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

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

FCB

2017/11/10 03:29

ゲームクリア画面をロードした回数でステージの開放をしたいと思っています。 それであれば、どこかに変数(初期値0)を用意しておき、ゲームクリア画面をロードしたときに、その変数を+1すればよいです。 そしてその変数の値を、switch文のあるスクリプトに渡せばよいです。 ------------------------------------------------------------------------------------------------------------- ご返答誠に有難うございます。 fiveHundredさんが仰っている内容は理解でき、理屈も納得できました。 ただ、全くのど素人でスクリプトの書き方が分かりません。 お手数ですが、スクリプトを参考に教えて頂けませんか。 今考えている内容としては、ゲームクリア画面のスクリプトに変数を置き、 ステージ選択画面のスクリプトにゲームクリア画面で置いた変数を呼び出し、 switch文に変数を渡し、条件を分岐させようと考えています。 後、ステージは合計で4つあり、それぞれゲームオブジェクトで作ってあります。 そこで一つ疑問ですが、上記に質問している、switch文のスクリプトは ステージごとに書くのですか?それとも、新しくGameobjectを作り、そこにスクリプトを追加する方法が良いですか? 宜しければ教えていただけないでしょうか。
fiveHundred

2017/11/10 04:31

> ただ、全くのど素人でスクリプトの書き方が分かりません。 > お手数ですが、スクリプトを参考に教えて頂けませんか。 具体的にどこが分からないのでしょうか? 「全て書いて」だと丸投げになってしまうので、一度自分で書いてみて、分からないところを質問するのがよいと思います。 > 後、ステージは合計で4つあり、それぞれゲームオブジェクトで作ってあります。 > そこで一つ疑問ですが、上記に質問している、switch文のスクリプトは > ステージごとに書くのですか?それとも、新しくGameobjectを作り、そこにスクリプトを追加する方法が良いですか? 私はステージをシーンで作ってあると思っていたので、「選択画面に書いた、ステージのシーンを呼び出す」ためのswitch文のつもりで書きました。 (この文脈だとプレハブなのかシーンに直接配置したものかが分かりませんが)ゲームオブジェクトで作ってあるということであれば、「選択画面に、ステージのゲームオブジェクトを有効化(あるいは生成)する」スクリプトを書けばよいです。 この場合、その選択画面のスクリプトに配列を定義し、それにInspector上でステージのゲームオブジェクトを入れておいておけば、switch文も必要ないかもしれません。
FCB

2017/11/14 05:26

返信おそくなってしまい、申し訳ございません。 二人でプロジェクトをしているのでお互いに理解できていないことがあり 質問がごちゃごちゃになってしまいました。大変申し訳ないです。 > 後、ステージは合計で4つあり、それぞれゲームオブジェクトで作ってあります。 こちらはゲームオブシェクトでといっていましたが、シーンでステージを4つ作っています。 ------------------------------------------------------------------------------------------------------------------ using System.Collections; using System.Collections.Generic; using UnityEngine; public class stage : MonoBehaviour { public void stage1 () { Application.LoadLevel ("stage1"); } public void stage2() { Application.LoadLevel ("stage2"); } public void stage3 () { Application.LoadLevel ("stage3"); } public void stage4 () { Application.LoadLevel ("stage4"); } } ------------------------------------------------------------------------------------------------------------------ 今はステージ選択画面に上記のスクリプトをつけており、 InspectorのOn Clickにてロードの処理を行っています。 ですので、この処理に追加でButtonの無効化をつけ、 Scene<clear>をロードした回数で解放していくという処理を行いたいです。 ------------------------------------------------------------------------------------------------------------------ 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 = 0/*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に応じてステージのシーンをロードする処理 */ SceneManager.LoadScene("stageNo1"); SceneManager.LoadScene("stageNo2"); SceneManager.LoadScene("stageNo3"); SceneManager.LoadScene("stageNo4"); } } ------------------------------------------------------------------------------------------------------------------ fiveHundredさんに教えていただいたスクリプトを元に作成してみました。 コメントアウトに書いてある通りに書いたので間違いも多いと思いますが確認お願い致します。 ープロジェクトの構成ー Scene <clear> <over> <sentaku> <stage1> <stage2> <stage3> <stage4> <sentaku> → stage1Button  stage2Button  stage3Button  stage4Button というような構成になっています。 fiveHundredさんがおっしゃる ・進行に合わせてステージをアンロックする(第1ステージをクリアしたら第2ステージを解放する) ということをやりたいと思っています。 あまり質問の答えになっていないと思いますが、よろしくお願い致します。 長くなって申し訳ございません。
fiveHundred

2017/11/14 07:39

回答に追記したので、確認してください。
FCB

2017/11/15 03:17

回答ありがとうございました。 すごく丁寧に説明して頂き分かりやすかったです。 fiveHundredさんが書いてくださったスクリプトをアタッチしたのですが 一つだけわからないことがありました。 プロジェクト自体は動くのですが、 ステージ選択ボタンの無効化ができませんでした。 ------------------------------------------------------------------- // Inspectorからシーン上のボタンを登録しておく public Button[] ButtonArray; ------------------------------------------------------------------- Inspectorにボタン登録はどうやってするのでしょうか? また、この部分はスクリプト上でも登録しておくのでしょうか? よろしくお願いいたします。
fiveHundred

2017/11/15 03:47

1. StageSelectスクリプトをステージ選択画面のゲームオブジェクトにアタッチする 2. アタッチしたStageSelectスクリプトに「Button Array」という項目があるので、その中の「Size」を4に書き換え、Enterを押す 3. すると「Element 0~3」が出てくるので、シーン上に配置してあるボタンを「Element 0~3」にドラッグ&ドロップする スクリプトの変更は不要です。
FCB

2017/11/16 02:56

出来ました! 詳しく説明していただきありがとうございました! 本当に助かりました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問