ゲーム化!tomo_manaのブログ

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

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

Unity学習#30 戦闘シーンへのドライバモジュール追加 (Unity 2019.4.4f1)

今回は、戦闘シーンについて考える合間に、シーンを使ったサブシステム化を試します(シーンを使ってデバッグ用のドライバモジュールを追加します)。マネージャーシーン無しでもデバッグできるようにすることで、シーン毎の作業分担だけでなくシーンの結合(マージ作業)も容易になります。


前回の実装では、戦闘シーンはマネージャーシーンから呼び出すために最適化されていました。戦闘シーン単体で動かす場合は、マネージャーの代理になるドライバがあると便利です。

(前回の記事)
tomo-mana.hatenablog.com

ドライバモジュールの追加

前回作ったシーン構成に、以下のようなドライバモジュールを追加します。

f:id:tomo_mana:20210306001700p:plain
Manager または Battle から BattleDriver を加算ロード

ドライバの役目

ドライバはシーンを仮想化します。ドライバはマネージャーからは戦闘シーンに見え、戦闘シーンからはマネージャーシーンに見えます。ドライバはマネージャーの代わりにセーブデータの受け渡し、戦闘シーンのアクティブ化の切り替え、アクティベート時の敵生成指示を行います(デバッグ用)。

以下のように、段階的にシーン間のやりとりをドライバに置き換えていきます。

f:id:tomo_mana:20210306220741g:plain
Driverへの置き換え

通常のシーケンス

前回のシーン構成(通常起動)は、マネージャーを使ってフィールドと戦闘を切り替えます。
(戦闘シーンをデバッグするために、フィールドを歩き回る必要があります)

f:id:tomo_mana:20210306001356p:plain
シーケンス - ManagerScene

ドライバ起動時のシーケンス

ドライバを追加した場合、通常起動のほかに、戦闘シーン単体で起動した場合は戦闘シーンだけを繰り返す、といったデバッグが可能になります。

f:id:tomo_mana:20210306221916p:plain
シーケンス - BattleSceneDriver

ドライバの拡張性

ドライバを追加することで、デバッグ専用機能を入れることができます。

将来的に以下のデバッグモードを追加したいと思っています。
⚫︎連続戦闘モード:戦闘終了時、次の戦闘を生成
⚫︎デバッグ専用キー:デバッグ専用のキーを受け付けて、戦闘中でも次の戦闘に強制的に切り替える、HP全快、ゾンビモード(HP0でも死なない)など、デバッグに必要なモードを追加します。


今回は、単純に戦闘シーンを単体で起動したときにドライバから戦闘シーンをアクティベートしてもらうだけのコードを追加します。そのほかは必要に応じて追加していきます。

ドライバシーンの追加

各プロセスの細かい手順は前回書いたので、今回は概要だけ書きます。
(1) Scene の作成、"BattleSceneDriver" にリネーム。
(2) File > BuildSettings に追加
(3) BattleSceneDriverシーン:Emptyゲームオブジェクトの作成(Service
(4) Serviceゲームオブジェクト:スクリプト作成、追加
(5) Cameraゲームオブジェクトを無効化します。


追加された BattleSceneDriver は、Service だけを持ったシンプルな構造です。

f:id:tomo_mana:20210306223216p:plain
Hierarchy - BattleSceneDriver

(追加したコード)

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.SceneManagement;
using UnityEngine.EventSystems;

public class BattleSceneManagerService : MonoBehaviour
{
    bool initialized = false;
    
    // Start is called before the first frame update
    void Start()
    {
        if( !SceneManager.GetSceneByName("BattleScene").isLoaded ){
            SceneManager.LoadSceneAsync("BattleScene", LoadSceneMode.Additive);
        }
    }

    // Update is called once per frame
    void Update()
    {
        if( !initialized ){
            if( SceneManager.GetSceneByName("BattleScene").isLoaded ){
                Scene scene = SceneManager.GetSceneByName("BattleScene");
                
                // フィールドシーンをアクティベート
                SceneManager.SetActiveScene(scene);
                
                // カメラON
                GameObject[] gameObjects = scene.GetRootGameObjects();
                foreach( GameObject g in gameObjects ){
                    if( g.GetComponent<Camera>() != null ){
                        g.SetActive(true);
                        break;
                    }
                }
                
                // イベントシステムを有効化
                foreach( GameObject g in gameObjects ){
                    if( g.GetComponent<EventSystem>() != null ){
                        g.SetActive(true);
                        break;
                    }
                }
                
                // キャンバスを有効化
                foreach( GameObject g in gameObjects ){
                    if( g.GetComponent<Canvas>() != null ){
                        g.SetActive(true);
                        break;
                    }
                }
                initialized = true;
            }
        }
    }
}

戦闘シーン(修正)

前回作成した戦闘シーン(BattleScene)を開き、以下を修正します。
(1) Emptyゲームオブジェクト追加(Initializer
(2) Initializerオブジェクト:スクリプト作成、追加


戦闘シーンも、中身はこれからなので、今のところ Initializer のみです。

f:id:tomo_mana:20210306223147p:plain
Hierarchy - BattleScene

(追加したコード)

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

public class BattleSceneInitializer : MonoBehaviour
{
    // Start is called before the first frame update
    void Start()
    {
        /*
            マネージャーシーンが居ない(デバッグモード)の場合、
            デバッグマネージャー(BattleSceneManager)を起動する
         */
        if( !SceneManager.GetSceneByName("ManagerScene").isLoaded ){
            if( !SceneManager.GetSceneByName("BattleSceneManager").isLoaded ){
                SceneManager.LoadSceneAsync("BattleSceneManager", LoadSceneMode.Additive);
            }
        }
    }

    void Update()
    {
    }
}

動作テスト

(1) 戦闘シーンを単体で起動します。ドライバシーンが起動されて、戦闘シーンがアクティベートされることが確認できました。
(2) マネージャーシーンから起動します。前回同様、フィールドと戦闘シーンが起動されて、フィールドがアクティベートされることが確認できました。
(3) 念のため、ドライバシーン単体での起動も確認します。戦闘シーンが起動されて、戦闘シーンがアクティベートされます。

(以下は、戦闘シーン単体で起動したときのHierarchyウィンドウ)

f:id:tomo_mana:20210306222923p:plain
動作テスト - BattleSceneから起動

これで、戦闘シーン単体のデバッグができそうです。

次回

戦闘画面の構成

(以上)