SceneAでボタン1(plus)、2(minus)があり、plusを押すとSceneBに移動して加算する。minusを押すと移動して、減算する。
UnityのUIボタンを使って、シーン遷移する方法は理解できている。
例えばSceneAでセーブボタンを押すと、SceneBに遷移してセーブをする。
SceneAでロードボタンを押すと、SceneBに遷移してロードをする。
2つのボタンともに同じシーンに切り替えるが、それぞれ動作が異なる機能を実装します。
本記事では、このような複数のボタンを押していずれも同じ画面に遷移して、
別々の処理を実行する方法を紹介します。
- Unityでシーン切り替えのやり方を知りたい。
- 複数ボタンで同じシーンに切り替えるが、それぞれ動作が異なるプログラムを作りたい。
シーン切り替え
初めにシーン切り替えについて紹介します。
そもそもゲームを開発する際に、シーン切り替えはゲーム開始シーン(タイトル画面)とゲームプレイシーンそれからゲームオーバーシーンの最低でも3つが必要になります。
シーン切り替えに必要なコードは、次の通りになります。
using UnityEngine.SceneManagement; //シーン切り替えに必要な名前空間
SceneManager.LoadScene("シーン名");
シーン切り替えには「using UnityEngine.SceneManagement;」の名前空間が必要です。
そして、「SceneManager.LoadScene(“シーン名”);」にシーン名を入力してシーン遷移をします。
ここではUIボタンを押して「SceneA」・「SceneB」のシーン切り替える汎用的な動作を実装します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//追加
using UnityEngine.SceneManagement;//シーン切り替えに必要
public class SceneMove : MonoBehaviour
{
public Button SceneA;
public Button SceneB;
public void MoveA()
{
SceneManager.LoadScene("SceneA");
}
public void MoveB()
{
SceneManager.LoadScene("SceneB");
}
}
UIボタンを使用するので、「using UnityEngine.UI;」を追加します。
また、メソッド「MoveA」・「MoveB」の定義をして、シーン切り替えをします。
スクリプト「SceneMove」をHierarchyウインドウの項目にアタッチして、ボタンを適用します。
さらに、ボタン「SceneA」にはMoveB。
ボタン「SceneB」にはMoveAをInspectorウインドウのOn Click()に紐づけて下さい。
実際の動作はこちらになります。
2つのボタンはともに1つのシーンに切り替え、別の動作(足し算・引き算)
先ほどは、ボタンを使ってシーン移動を確認しました。
ここからは、本記事の最終目標の動作を作成していきます。
2つのボタンを「SceneA」に用意し、どちらも「SceneB」に切り替える。
「SceneA」の片方のボタンを押して、「SceneB」のボタンを押すと数字が加わる。
「SceneA」のもう一方のボタンを押して、「SceneB」のボタンを押すと数字が減る。
1.1.ソースコード
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//UIボタンとUIテキストで必要
using UnityEngine.SceneManagement;//シーン切り替えに必要
public class SceneMove : MonoBehaviour
{
static int i;
static bool flag;
public Text num;
public Text Situ;
public Button Plusbtn;
public Button Minusbtn;
public Button Counter;
void Update()
{
num.text= i.ToString();
if (SceneManager.GetActiveScene().name == "SceneB" && flag == true)
{
Situ.text = "Plus";
}
else if (SceneManager.GetActiveScene().name == "SceneB" && flag == false)
{
Situ.text = "Minus";
}
}
public void MoveA()
{
SceneManager.LoadScene("SceneA");
}
public void Plus()
{
SceneManager.LoadScene("SceneB");
flag = true;
}
public void Minus()
{
SceneManager.LoadScene("SceneB");
flag = false;
}
public void Count()
{
if(flag == true)
{
i++;
}
else if(flag == false)
{
i--;
}
}
}
UdemyでUnityを学習
Udemyは、オンデマンド式の学習講座です。
趣味から実務まで使えるおすすめの講座を紹介します。
- 【Unity C# ゲーム開発超入門】7つのミニゲームを作っておぼえる!UnityとC#講座
Unityで頻出の機能を実際のゲーム作りで学習。
何か作りたい、今後の開発で役立てたい初心者におすすめ
- 【Unity C# ゲーム開発初心者レベルアップ】7つのトランプゲームを作っておぼえる!UnityとC#講座
トランプやボードゲーム作りに特化している講座。
テーブルゲームを作りたい人におすすめ。
- 【全行程を網羅!最初に学びたい総合学習】Unityワールド制作講座
Unityワールド制作の全工程を学習できる講座。
RPGを作りたい人におすすめ。
- Unity ゲーム開発:インディーゲームクリエイターが教える C#の基礎からゲームリリースまで【スタジオしまづ】
C#の文法やApp StoreとGoogle Playへゲームをリリース方法を解説。
ゲームを出品したい人におすすめ。
1.2.解説
初めに、名前空間に、UIボタンとUIテキストを作るための「using UnityEngine.UI;」・シーン切り替えするための「using UnityEngine.SceneManagement;」を追加します。
これらを入力を忘れると使用できないので、注意してください。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;//UIボタンとUIテキストで必要
using UnityEngine.SceneManagement;//シーン切り替えに必要
続いて、変数を定義します。
「i」は、静的(static)なint型変数で、後にこの変数を文字列に変換します。
「flag」は、True・Falseの真偽値を代入する静的(static)なbool型変数です。int型で変数を0,1にして真偽を分ける方法でも代用可能です。
※変数を静的(static)にすることで、シーン切り替えをしてもその値をそのまま引き継ぐことができます。
「num」・「Situ」はUIテキストで、「num」はSceneAで数字を表示します。「Situ」はSceneBでプラスかマイナスかを表示します。
「Plusbtn」・「Minusbtn」・「Counter」「Back」はUIボタンで、「Plusbtn」・「Minusbtn」はそれぞれ数字の加算・減算をします。「Counter」は押すと、数字を1ずつ加減をします。「Back」は、SceneBからSceneAにシーン切り替えをします。
static int i;
static bool flag;
public Text num;
public Text Situ;
public Button Plusbtn;
public Button Minusbtn;
public Button Counter;
public Button Back;
ここで、ボタンそれぞれに要素を追加します。
関数Plus()・Minus()はSceneBに遷移して、Plus()はbool型変数「flag」をTrue(真)にして、Minus()はFalse(偽)にします。各関数はそれぞれ、UIボタン「Plusbtn」・「Minusbtn」に紐づけます。
関数Count()はbool型変数「flag」がTrue(真)つまり、SceneAで「Plusbtn」が押されたときに加算して、「flag」がFalse(偽)つまり、SceneAで「Minusbtn」が押されたときに減算します。関数Count()はUIボタン「Counter」に紐づけます。
関数MoveA()はSceneBからSceneAに遷移します。
public void Plus()
{
SceneManager.LoadScene("SceneB");
flag = true;
}
public void Minus()
{
SceneManager.LoadScene("SceneB");
flag = false;
}
public void Count()
{
if(flag == true)
{
i++;
}
else if(flag == false)
{
i--;
}
}
public void MoveA()
{
SceneManager.LoadScene("SceneA");
}
最後に、Update()内にて、UIテキスト「num」に変換したint型変数「i」を表示します。
また、SceneBが加算なのか、減算なのか一目で分かるようにします。
次のコードはif文と組み合わせることで、そのシーンのみでしか処理されないようになります。
SceneManager.GetActiveScene().name == "シーン名"
SceneBかつbool型変数「flag」がTrue(真)であるとき、UIテキスト「Situ」は”Plus”と表示されます。
SceneBかつbool型変数「flag」がfalse(偽)であるとき、UIテキスト「Situ」は”Minus”と表示されます。
void Update()
{
num.text= i.ToString();
if (SceneManager.GetActiveScene().name == "SceneB" && flag == true)
{
Situ.text = "Plus";
}
else if (SceneManager.GetActiveScene().name == "SceneB" && flag == false)
{
Situ.text = "Minus";
}
}
以上までが1つ目のスクリプトになります。Hierarchyウインドウの項目にアタッチしてください。
さらに、InspectorウインドウのOn Click()に紐づけて下さい。
「1.1.ソースコード」での不具合を改善
上記のスクリプトのみでプログラムを稼働するとシーンを切り替えても、前のUIが残ってしまいます。
そこで、本スクリプトは「DontDestroyOnLoad」を使用して、
シーンを切り替えてもUIと変数を保持しつつ適切な表示を実装します。
DontDestroyOnLoad
「DontDestroyOnLoad」はオブジェクトがシーンの切り替え(ロード)時に破棄されないようにするために使用されます。
通常新しいシーンがロードされると、現在のシーンに存在するすべてのオブジェクトは破棄されますが、
DontDestroyOnLoadを使用すると、特定のオブジェクトを破棄せずに次のシーンに持ち越すことができます。
以下にDontDestroyOnLoadの簡単なコードを示します。
using UnityEngine;
public class MyScript : MonoBehaviour
{
private void Start()
{
// このオブジェクトをシーンの切り替え時に破棄しないように設定する
DontDestroyOnLoad(this.gameObject);
}
}
このスクリプトは、Startメソッドで現在のゲームオブジェクトを取得し、
DontDestroyOnLoadメソッドを呼び出しています。
これにより、現在のゲームオブジェクトはシーンの切り替え時に破棄されず、
次のシーンでも存在し続けます。
2.1.ソースコード
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
public class DontDestroyOnLoad: MonoBehaviour
{
public GameObject Obj;
void Start()
{
DontDestroyOnLoad(Obj);
}
void Update()
{
if (SceneManager.GetActiveScene().name == "SceneA")
{
Obj.gameObject.SetActive(false);
}
if (SceneManager.GetActiveScene().name == "SceneB")
{
Obj.gameObject.SetActive(true);
}
}
static public DontDestroyOnLoad instance = null;
void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
}
2.2.解説
初めに、名前空間へ同様にシーン切り替えするための
「using UnityEngine.SceneManagement;」を追加します。
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
続いて、変数を定義します。
ゲームオブジェクト「Obj」を作り、関数Start()に「DontDestroyOnLoad(Obj)」として、
ゲームオブジェクト「Obj」をシーン遷移で消えないようにします。
public GameObject Obj;
void Start()
{
DontDestroyOnLoad(Obj);
}
ここで、インスタンスを作ります。
「instance = null」として関数Awake()にて、
「instance == null」の時は「gameObject」は消さず、それ以外は消します。
static public DontDestroyOnLoad instance = null;
void Awake()
{
if (instance == null)
{
instance = this;
DontDestroyOnLoad(gameObject);
}
else
{
Destroy(gameObject);
}
}
最後に関数Update()にて、
ゲームオブジェクト「Obj」をSceneAの時は非表示、SceneBの時は表示にします。
void Update()
{
if (SceneManager.GetActiveScene().name == "SceneA")
{
Obj.gameObject.SetActive(false);
}
if (SceneManager.GetActiveScene().name == "SceneB")
{
Obj.gameObject.SetActive(true);
}
}
以上までが2つ目のスクリプトになります。
Hierarchyウインドウの項目に新しいGameObjectを作成してアタッチしてください。
ゲームオブジェクト「Obj」にUIをアタッチすると、適応されます。
まとめ
今回は、複数のUIボタンで1つのシーンに切り替えて、それぞれ別の動作を作りました。
シーンを切り替えても変数を保持するためには静的な(static)変数を使う必要があります。
また、UIテキスト・UIボタンをシーン遷移しても保持するには、
DontDestroyOnLoadを使う必要があります。