Unityで作る、画面遷移のあるメニュー

UnityのMecanimを使って、画面遷移のあるメニューを実装してみたいと思います。


ソースコードはこちら 
github.com


今回作るメニューの構造

今回作るメニューの構造は、JRPGによくあるタイプの
トップメニュ→キャラステ、アイテム、システムなどに分岐するような構造。

 

トップメニューがあって…

f:id:chicchi0531:20171010001900p:plain

キャラクターステータス画面や、

f:id:chicchi0531:20171010002007p:plain

他のメニューに遷移するようなメニューを作る

f:id:chicchi0531:20171010002110p:plain


 

デモの画面遷移はざっくりこんな感じ

f:id:chicchi0531:20171010011231p:plain

画面遷移の実装パターン

 細かくは色々ありますが、次の2パターンに大別されると思います。

 

・パターン1:マルチシーンエディティングを活用する
・パターン2:オブジェクトの表示非表示で切り替える

 

パターン1

パターン1は、各メニューをSceneとして保存しておき、遷移する際に

SceneManager.LoadScene("シーン名",LoadSceneMode.Additive);

上記のコードで、シーンを追加読み込みして、画面を重ねていく方法。


この方法だと、

・各メニューの独立性が高くなり、他の場面で再利用しやすくなる

というメリットがありますが、

・メニューの数だけSceneファイルを用意しなければならない

というデメリットもあります。
メニューの各項目を、単体で再利用する場面というのはなかなかないと思うので、Sceneを使わないパターン2の方法で実装するか、再利用する部分だけ、パターン1で、しない部分はパターン2という実装をすることになると思います。

パターン2

パターン2は、オブジェクトの表示、非表示を切り替えて実装する方法です。

表示非表示は、SetActiveメソッドを使う方法もありますが、
ここではCanvasコンポーネントのenabledフラグを切り替える方法で行きます。

f:id:chicchi0531:20171010021849p:plain

SetActiveメソッドを使ってしまうと、そのオブジェクトにくっついているコンポーネントが動作しないというデメリットがあるため、
単純に表示非表示を切り替えるだけならCanvasのenableフラグを切り替えた方が、シンプルな実装になると思います。

データドリブンな実装

テスト段階ならスクリプトで素直に

GetComponent<Canvas>().enabled = false;

とかしておけばよいのですが、実際のアプリケーションでは、UIの遷移にアニメーションを付けることが多いです。
そこで、次のようなMecanimを作り、表示と非表示をアニメーションから切り替えられるようにします。

f:id:chicchi0531:20171010022843p:plain

スクリプト

GetComponent<Animator>().SetBool("IsShow",true);

と書いてやることで、表示され、
falseを入れると非表示になるよう組まれています。

実装

実際のトップメニューからの遷移部分のコードです。

Assets/Resources/Scripts/Menu/Top/TopMenu.cs

    public class TopMenu : MonoBehaviour
    {

        [SerializeField]
        private MenuController mMenuController = null;

        [Header("各メニューのキャンバス")]
        [SerializeField]
        private BaseMenu mArmy = null;
        [SerializeField]
        private BaseMenu mItem = null;
        [SerializeField]
        private BaseMenu mTips = null;
        [SerializeField]
        private BaseMenu mSystem = null;

        //内部変数
        private Animator mcAnim = null;

        // Use this for initialization
        void Start()
        {
            mcAnim = GetComponent<Animator>();
        }

        // Update is called once per frame
        void Update()
        {
            if (mcAnim.GetBool("IsShow") && mMenuController.InputEnable)
            {
                if (Input.GetButtonDown("Cancel"))
                {
                    mMenuController.Close();
                }
            }
        }

        //軍拡をクリック
        public void OnClickArmy()
        {
            mArmy.Open();
            Close();
        }

        //アイテムをクリック
        public void OnClickItem()
        {
            mItem.Open();
            Close();
        }

        //Tipsをクリック
        public void OnClickTips()
        {
            mTips.Open();
            Close();
        }

        //システムをクリック
        public void OnClickSystem()
        {
            mSystem.Open();
            Close();
        }

        public void Open()
        {
            mcAnim.SetBool("IsShow", true);
        }

        public void Close()
        {
            mcAnim.SetBool("IsShow", false);
        }
    }

この、Click_XXXというメソッドをボタンをクリックしたときに呼ぶことで、
各メニューを表示し、トップメニューを非表示にしています。

今回は、右クリックを押すとトップメニューへ戻る、といった実装になっているので、トップメニューと、各メニューでは画面遷移の実装が若干違います。
各メニューの実装は以下。

Assets/Resources/Scripts/Menu/BaseMenu.cs

    public class BaseMenu:MonoBehaviour
    {
        //コントローラへの参照
        [SerializeField]
        protected MenuController mController = null;

        //トップメニューへの参照
        [SerializeField]
        protected TopMenu mTopMenu = null;

        //component 
        protected Animator mcAnim = null;

        //閉じれるかどうか
        public bool Closable { get; set; }

        // Use this for initialization
        protected virtual void Awake()
        {
            mcAnim = GetComponent<Animator>();
            Closable = true;
        }

        protected virtual void Start()
        {
            
        }

        // Update is called once per frame
        protected virtual void Update()
        {
            if (mcAnim.GetBool("IsShow") && Closable)
            {
                if (Input.GetButtonDown("Cancel"))
                {
                    Close();
                }
            }
        }

        public virtual void Open()
        {
            mcAnim.SetBool("IsShow", true);
        }

        public virtual void Close()
        {
            mcAnim.SetBool("IsShow", false);
            mTopMenu.Open();

        }
    }

Closableプロパティは、メニューが右クリックで閉じられる状態かどうかを表すプロパティです。
例えば、キャラクターの編成画面で、装備品を選択するポップアップウィンドウを出しているときに右クリックでトップメニューへ戻ってもらっては困るので、ポップアップウィンドウが表示されている間はClosableをtrueにして、トップメニューへ戻ってしまうのを防いだり、ということに使います。



画面遷移に関して、ざっくり説明してきました。
基本的な内容ですが、何も見ずに実装しようとすると意外と躓くところでもあると思うので、
参考の一つにでもしていただければ幸いです。