のにっき

UnityとWindowsフォームアプリの意識の違い

今回は、つい最近Unityで組み込みやってて
同時並行でWindowsフォームアプリでツールを作っていた時に
ハッ!としたことについてお話します。
一週間前にハッとしてから今まで内容をまとめようと
業務をほっぽり出して考えたのですが、全く考えがまとまらなかったので
意味の分からない部分が多々あると思います。
お手数をお掛けして申し訳ありませんが、くみ取ってください。。。

シーンではなく、オブジェクトに対してスプリクトを作る!

さっそく意味不明なタイトルです・・・
Windowsフォームアプリの仕様としまして、

  • オブジェクトのイベント関数は一つのクラスファイル(【例】Form1.cs)にまとめる
  • オブジェクトを呼び出すとき、必ずフォームをベースとして呼び出さないといけない

上記2つの仕様があります。この仕様に慣れると、
Unityの組み込みの自由度に、無意識のうちに枷を付けてしまうことになります。
Unityに出来てWindowsフォームアプリでできないこと・・・
『 オブジェクトに対してクラスファイルを設定できる 』です!

・・・だからなんなのか?
例として、ボタンを押すとエラー画面が出る簡単なアプリを作るとします。

f:id:apuridasuo:20190523161123p:plain
図:仕様説明
この仕様を、「Windowsフォームアプリ的思考(個人的)」と
「Unity的思考(個人的)」の2パターンで組み込んでみます。

Windowsフォームアプリ的思考の組み込み

▼ Test01_Main.cs

    //==============================================
    // 変数
    //==============================================
    public static GameObject Obj_Err;
    public static Text Txt_Value;

    //==============================================
    // 起動時イベント
    //==============================================
    void Start()
    {
        Obj_Err = GameObject.Find("Canvas/Panel_Error").gameObject;
        Txt_Value = Obj_Err.transform.Find("Value").GetComponent<Text>();
        Obj_Err.SetActive(false);
    }

上記ソースを空オブジェクトに設定します。
シーン起動時に、
シーン内で変更を加えるオブジェクトを全て変数に定義することで
オブジェクトをまとめて管理できます。

▼ Test01_Tap.cs

    //=============================================
    // エラー画面表示イベント
    //=============================================
    public void Tap_ErrorWindow_Open()
    {
        Tst_Main.Obj_Err.SetActive(true);
        Tst_Main.Txt_Value.text = "エラーの内容!";
    }
    //=============================================
    // エラー画面閉じるイベント
    //=============================================
    public void Tap_ErrorWindow_Close()
    {
        Tst_Main.Obj_Err.SetActive(false);
    }

上記ソースが、「エラー画面の表示開始・終了」の処理です。
ボタン等のイベントで呼び出す関数をまとめて一つのファイルにしておく事で、
ボタンに設定するスプリクトファイルが共通化されます。
後は、各ボタンにInspectorウィンドウから設定します。

以上が、Windowsフォームアプリ的思考で組み込んでみたパターンです。
特徴としましては、

  • オブジェクトの管理を1シーンでまとめて行っている(Test01_Main.cs)
  • イベント関数の管理を1シーンでまとめて行っている(Test01_Tap.cs)

1シーンごとにまとめる方が見やすいし管理しやすい!。という考え方が
フォームアプリの組み込み方に毒された意固地な思考なんです。
※決して悪くはないとも思っています・・・

Unity的思考の組み込み

「Test02_Main.cs」は作りません
▼ Test02_Tap.cs

    //==============================================
    // エラー画面表示イベント
    //==============================================
    public void Tap_ErrorWindow_Open()
    {
        Test02_ErrCntrl.SetOpenErrMsg("エラーの内容!");
    }

エラー画面を出力するボタンの関数のみ記入しておきます。
共通オブジェクトとしてまとまらなかった
オブジェクトのイベントをこのファイルにまとめます。

▼ Test02_ErrCntrl.cs

    // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    //
    //			変数定義
    //
    // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    //===============================================
    // 変数
    //===============================================
    public static GameObject Obj_Err;
    public static Text Txt_Value;

    // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    //
    //			イベント関数
    //
    // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    //=============================================
    // 起動時
    //=============================================
    void Start ()
    {
        Obj_Err= gameObject;
        Txt_Value = transform.Find("Value").GetComponent<Text>();
        Button Btn_Ok = transform.Find("Btn_Ok").GetComponent<Button>();
        Btn_Ok.onClick.AddListener(Tap_OkButton);
        Obj_Err.SetActive(false);
    }

    // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    //
    //			サブルーチン関数
    //
    // ■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□■□
    /*********************************************************************
       メソッド       : Tap_OkButton
       概要           : OKボタンタップ
    **********************************************************************/
    public void Tap_OkButton()
    {
        Obj_Err.SetActive(false);
    }
    /*********************************************************************
       メソッド       : SetOpenErrMsg
       概要           : エラーパネル表示処理
    **********************************************************************/
    public static void SetOpenErrMsg( string str_Msg_Set)
    {
        Obj_Err.SetActive(true);
        Txt_Value.text = str_Msg_Set;
    }

上記ファイルは、エラー画面のパネルに設定します。
エラー画面のパネル以下のオブジェクトを1つにまとめて管理しています。
シーンごとにまとめるのではなく、同カテゴリのオブジェクトごとにまとめる!
これが、Windowsフォームアプリに出来なくてUnityにできる組み込み方だと思います。

Unity的思考の組み込み方の利点

ではこの組み込み方のなにが良いのでしょうか?
まとめて管理したほうが見やすそうでは?そんなことないです!
オブジェクトごとにまとめる利点を思いつくだけまとめました。

  • 1つの cs ファイルで完結させることができる

1つのシーンには、様々な役割を持つオブジェクトがたくさんあります。
まとめて管理しようとすると、管理変数が膨大な数になってしまい、
どれがどれか分かりずらくなってしまいます。
1つの役割ごとにcsファイルをまとめることで
変数の中身も分かりやすく、
ほかのcsファイルとのつながりが最小限のやり取りで済みます!
※この辺の説明が上手くまとまらなかったんです・・・すみません((´;ω;`)

  • 役割でまとめることで、別シーン・別プロジェクトでも使えるプレハブが作れる

1シーンでまとめると、似たような役割のオブジェクトを
別シーンで作りたいとき、スクリプト部分が移行できないです。
しかし、1つの cs ファイルで完結できていればそのcsファイルは
別のシーンでも問題なく動くのです!
より自由度の高いプレハブを作ることができるのです!

以上が、今回ハッ!としたことです。
これに気付いた時、洗脳が解けた感覚がしましたー
無意識のうちに組み込み方にダメな癖がついていて、
頭の固い自分の脳みそをぶんなぐってやりたいです。。。