ゲーム化!tomo_manaのブログ

ゲーム化!tomo-manaのブログ

Unityでゲームを作る方法について紹介しています

Unity学習#17 (Unity 2019.4.1f1) リストをメニュー画面に組み込む

今回は、第14回と第16回で作成したリストを、メニュー画面(第13回)の中に組み込みます。
今回は思ったよりあっさり動きましたが、課題が残りました。

構成

これまでに作ったメニューの要素と関係性を以下にまとめます。

これまでの構成(修正前)

第14回第16回で、単純なリストをScrollViewで作成しました。
また、第13回で、Submit を押したら次の画面を表示する単純なメニューをPanelで作成しました
(次の画面への参照だけを持つC#スクリプト Window.cs を付けてあります)。

Hierarchyウィンドウでは以下の関係になっています。

f:id:tomo_mana:20200923223906p:plain
修正前(InputSystem と Stack で作ったメニュー)

修正後

メニューの要素(ListItem、QueryUse)にリスト(ScrollView)をぶら下げます。

f:id:tomo_mana:20200923223831p:plain
修正後(メニューの要素に ScrollView をぶら下げる)

最初は、ScrollView (ScrollViewController) に、メニュー (Window) を 継承か実装させようと思いましたが、うまくいきませんでした。最終的に、ゲームオブジェクトの性質を使って親子関係にしたら、すんなりと動きました。

構成の変更

ScrollView の移動と複製

ScrollView を ListItem と QueryUse にぶら下げます。

(1) Hierarchyウィンドウで、ScrollView の行 を ListItem の行にドラッグ&ドロップ
(2) ScrollView の行を右クリック > Copy
(3) QueryUse の行を右クリック > Paste

この辺りは本当に直感的です。

コードの修正

Window

ScrollView の親ゲームオブジェクトになる ListItem と QueryUse (Window.csが付いている)を修正します。Window.cs に、ScrollView への参照と、ScrollView への Navigate() の伝達を追加します。(子オブジェクトの取得は第14回の補足2にまとめてあります)

Window.cs

using System.Collections;
using System.Collections.Generic;
using UnityEngine;

public class Window : MonoBehaviour
{
    // 次のウィンドウ
    [SerializeField] Window windowNext;
    private ScrollViewController child;
    
    // Start is called before the first frame update
    void Start()
    {
        child = gameObject.transform.GetChild(0).gameObject.GetComponent<ScrollViewController>();
    }
    
    public void Navigate(Vector2 value)
    {
        if( child != null ){
            child.Navigate(value);
        }
    }
    
    public void SetActive(bool b){
        gameObject.SetActive(b);
    }
    
    public Window Next(){
        // リスト要素毎にNextを持つ。その種類のWindowNextを返す。
        // 今はwindowのテストのため、windowNextをそのまま返す
        return windowNext;
    }

    // Update is called once per frame
    void Update()
    {
        
    }
}

Window の付いたゲームオブジェクトの Image を無効化

Window の付いたゲームオブジェクトには、もともと表示テスト用にImageが付いていたので、一旦無効化します。
(今後使いそうな気もするので、削除はせず、チェックだけを外します)
(1) Hierarchyウィンドウで、ListItem を選択
(2) Inspectorウィンドウで、Image の左のチェックボックスのチェックを外します。
※QueryUse も同じ。

動作テスト

以下を確認できました。
●最初のリストが表示されること
●最初のリストでSubmitを押した時に、次のリストが表示されること
●リストを持たない3番目のメニューの表示までを行えること

f:id:tomo_mana:20200923233902p:plain
動作テスト

少し気持ちを盛り上げるために、適当にアイテム名を入れています。
そのうち、もう少しかっこよくしたいなぁ・・・

残課題

今回の方法では、いくつか不具合があることが分かりました。次回以降に修正します。
● リストを表示した時に、最初の1個目のアイテムが選択表示にならない(NullReferenceExceptionが出ている)
● 2つ目のリストが選択状態になった時に、1つ目のリストの選択状態が解除される(どれを選択していたか分からなくなる)

前回の判断で、EventSystemを使用したのですが、それは Deselect / Select イベントを発行したかったからでした。今回のように複数のリストを表示する場合は、前のリストの選択状態を保持できる仕組みが必要そうです。

→ 第21回の記事で、上記の不具合修正を行いました。
tomo-mana.hatenablog.com

次回やること

ステータスの作成とアイテムリストの作成

今回、分からなかったこと

今後の調査のために、以下を残しておこうと思います。

継承 (Extend) での失敗

継承での場合、親クラスで実装された子クラス側でもオーバーライドがうまくできませんでした。(Window を ScrollViewController に継承した時に、Navigate() のオーバーライドができません)

インターフェース (interface/Implement) での失敗

インターフェースでの場合、同じインターフェース型を返す関数型を実装できないようでした。
interface として定義できますが、実装した時に Less Accessible の警告が出て、コンパイルが通らないようでした。(Window を IWindowElement インタフェースとして定義した時に、IWindowElement Next() がインターフェースとしては作成できますが、ScrollViewController に実装した時にLess Accessibleエラーが表示されます)

→ 第19回の記事で、継承とインターフェースについて調べた内容をまとめました。
tomo-mana.hatenablog.com