シーン内のUIに宴のシナリオ再生を埋め込む


投稿日:2024年4月30日 | 最終更新日:2024年5月29日

概要

宴のシナリオ再生で使用するテキスト(メッセージウィンドウ)や、キャラ表示などは基本的にAdvEngine以下のオブジェクトになります。
拡張することで既存のUIオブジェクト以下に宴のシナリオで再生するキャラなどを表示することも可能です。
つまり、シナリオ再生の埋め込み(Embed)が可能になります。

サンプルイメージ

埋め込み機能の使い方

メッセージウィンドウ

デフォルトのMessageWindowをコピーするなどして、新しいメッセージウィンドウを作成してください。
基本的には、メッセージウィンドウを複数使用する場合とやり方は同じです。
作成したメッセージウィンドウを、シーン内の任意の場所に置きます。

メッセージウィンドウをAdvEngineに設定

AdvEngine>UI>MessageWindowManagerオブジェクトの、AdvUguiMessageWindowManagerコンポーネントの「Message Window List」にウィンドウを追加してください。

レイヤー

シーン内の任意の場所にUnityのUIのCanvasオブジェクトを作成します。
これは宴のレイヤーに相当するオブジェクトになります。

AdvGraphicLayerInSceneコンポーネントの追加と設定

AdvGraphicLayerInSceneコンポーネントをAddComponentし、各種設定をします。
各項目の内容は、レイヤーシートのリファレンスと同じです。
基本的には「LayerType」で「Bg」「Character」「Sprite」などのタイプの設定だけをすればいいです。
レイヤーシートにしかない項目のうち、X,YやScaleなどはRectTransformコンポーネントの値、LayerMaskはGameObjectのLayerの値に相当しますので、通常のUIと同じように任意に設定してください。
「Root Objects」は基本的にはNoneでも構いません。
このオブジェクト直下ではなく別のオブジェクト以下に表示したい場合は、「Root Objects」にルートとなるオブジェクトを設定してください。

マスキング等の拡張

UnityのRectMask2DなどのMaskコンポーネントを使うことで埋め込み範囲外に表示されないようにマスキングすることができます。
その他、UnityのUI系のコンポーネントを使って任意の拡張が可能です。

レイヤーをAdvEngineに設定

作成したCanvasオブジェクトを、AdvEngine>GraphicManager>LayerListに追加設定してください。

Layerシートに登録

Canvasオブジェクト名がそのまま宴のシナリオ上で設定するレイヤー名になりますので、Canvasオブジェクトに任意の名前を設定してください。
その後、宴のLayerシートに、レイヤーとして設定します。
LayerNameに同一の名前を設定し、Typeを「Dummy」としてください。

バックログと選択肢を埋め込み設定

バックログと選択肢は基本的には一度に一種類しか使えません。

一つしか使用しない場合でUIの位置だけシーン内の別の場所に移動する場合

AdvEngine>UI以下にあるSelectionとBackLogオブジェクトをシーン内の任意に場所に移動するだけです。
UIのレイアウト調整等は手動で行ってください。

複数を切り替えて使用する場合

UI画面に合わせて選択肢やバックログを切り替える場合は、まず各UIに選択肢やバックログのオブジェクトを作成します。
作成したUIの埋め込み設定と解除の切り替えはプログラムから行います。(後述)

AdvEngine以下からコピーして作成し、任意のUI以下に置いくてださい。
UIのレイアウト調整等は手動で行ってください。

selectionの使用するプレハブも、コピーして新しく作ったプレハブを設定してください。

backlogのプレハブの同様です。

クリック判定の設定

基本的には、宴の会話シーンの判定はクリック判定は「一番奥」になっているので、
RaycastRargetがオンになっている背景UIなどがあるとクリックが効きません。
メッセージウィンドウなど任意のUIに対して、クリック検知を追加してください。
詳細はこちらも確認してください。クリック検知をカスタム

シナリオの書き方

基本的には各表示コマンドでのレイヤーの指定と、テキストのメッセージウィンドウの指定だけすれば、通常のシナリオの書き方と同じように使えます。

ただし、フェードやイメージエフェクトなどカメラにかける効果などは画面全体にかかかってしまうので注意してください。
また、ShakeコマンドでGraphic全体を対象にするコマンドも、GraphicManagerとの親子関係がなくなっているため正常に動作しなくなるので注意してください。

プログラムから埋め込み設定をする

AdvEngineと埋め込みたいオブジェクトが別のシーンにある場合などでインスペクター経由で設定できないときは、
以下のようにプログラムを使って動的に設定することも可能です。
動的に埋め込みを設定した場合は、埋め込みオブジェクトが破棄されたときなどにリークしないように埋め込みを解除するようにしてください。

埋め込みを設定

レイヤーとメッセージウィンドウの埋め込みサンプル
AdvUguiMessageWindowManager>Message Window ListやAdvEngine>GraphicManager>LayerListに設定済みの場合はプログラムで設定する必要はありません。
(同一シーンなどになくてプログラムから設定する場合を想定しています)


            //宴のレイヤーを埋め込む
            advEngine.GraphicManager.EmbedLayer(layer);
            //メッセージウィンドウを埋め込む
            advEngine.MessageWindowManager.EmbedWindow(messageWindow);

選択肢とバックログの埋め込みサンプル
選択肢とバックログはプログラムからしか切り替えできません。

            if(advEngine.UiManager is AdvUguiManager advUguiManager)
            {
                //現在の選択肢があるなら閉じる
                if (advUguiManager.CurrentSelection != null)
                {
                    advUguiManager.CurrentSelection.Close();
                }
                //選択肢を埋め込む
                advUguiManager.SetEmbedSelection(selection);

                //現在のバックログがあるなら閉じる
                if (advUguiManager.CurrentBacklog != null)
                {
                    advUguiManager.CurrentBacklog.Close();
                }
                //バックログを埋め込む
                advUguiManager.SetEmbedBackLog(backlog);
            }

埋め込みを解除

レイヤーとメッセージウィンドウの埋め込み解除のサンプル


            //宴のレイヤーの埋め込身を解除
            advEngine.GraphicManager.RemoveEmbedLayer(layer);
            //メッセージウィンドウの埋め込みを解除
            advEngine.MessageWindowManager.RemoveWindow(messageWindow);

選択肢とバックログの埋め込み解除サンプル


            if (advEngine.UiManager is AdvUguiManager advUguiManager)
            {
                //埋め込み選択肢を解除
                advUguiManager.ReleaseEmbedSelection();

                //埋め込みバックログを解除
                advUguiManager.ReleaseEmbedBackLog();
            }

サンプルコード

動的に埋め込み機能を設定・解除するサンプルプログラムです。


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

namespace Utage
{
    //任意のUIにAdvEngineを埋め込み表示するためのサンプルプログラム
    public class SampleAdvEngineEmbed : MonoBehaviour
    {
        // ADVエンジン
        // ADVエンジンが別シーンにある場合は、外部プログラムからAdvEngineを設定すること
        public AdvEngine AdvEngine
        {
            get => advEngine;
            set => advEngine = value;
        }
        [SerializeField] AdvEngine advEngine;

        //キャラ等を表示するレイヤー(UiCanvas)
        [SerializeField] List<AdvGraphicLayerInScene> layers;
        //メッセージウィンドウ
        [SerializeField] AdvUguiMessageWindow messageWindow;

        //選択肢
        [SerializeField] AdvUguiSelectionManager selection;

        //バックログ
        [SerializeField] AdvUguiBacklogManager backlog;

        bool IsEmbed { get; set; }

        //埋め込み表示のセットアップ
        public void Embed()
        {
            StartCoroutine(CoEmbed());
        }

        //埋め込み表示のセットアップの非同期版
        //AdvEngineの初期化が終わるまで待ってから埋め込み表示を行う
        public IEnumerator CoEmbed()
        {
            //AdvEngineがまだ準備できていない場合は、初期化を待つ
            while (AdvEngine.IsWaitBootLoading)
            {
                yield return null;
            }
            //埋め込みのセットアップ

            //キャラ等を表示するレイヤー(UiCanvas)を埋め込む
            foreach (var layer in layers)
            {
                AdvEngine.GraphicManager.EmbedLayer(layer);
            }
            if(messageWindow != null)
            {
                //メッセージウィンドウを埋め込む
                AdvEngine.MessageWindowManager.EmbedWindow(messageWindow);
            }

            if(AdvEngine.UiManager is AdvUguiManager advUguiManager)
            {
                //現在の選択肢があるなら閉じる
                if (advUguiManager.CurrentSelection != null)
                {
                    advUguiManager.CurrentSelection.Close();
                }
                //選択肢を埋め込む
                advUguiManager.SetEmbedSelection(selection);

                //現在のバックログがあるなら閉じる
                if (advUguiManager.CurrentBacklog != null)
                {
                    advUguiManager.CurrentBacklog.Close();
                }
                //バックログを埋め込む
                advUguiManager.SetEmbedBackLog(backlog);
            }
            IsEmbed = true;
        }

        //埋め込み表示の開放
        public void RemoveEmbed()
        {
            if(!IsEmbed) return;

            IsEmbed = false;
            if (AdvEngine == null) return;

            //AdvEngineがまだ残っているなら、埋め込み表示を解除
            foreach (var layer in layers)
            {
                AdvEngine.GraphicManager.RemoveEmbedLayer(layer);
            }

            if (messageWindow != null)
            {
                AdvEngine.MessageWindowManager.RemoveWindow(messageWindow);
            }

            if (AdvEngine.UiManager is AdvUguiManager advUguiManager)
            {
                //埋め込み選択肢を解除
                advUguiManager.ReleaseEmbedSelection();

                //埋め込みバックログを解除
                advUguiManager.ReleaseEmbedBackLog();
            }

        }

        private void OnDestroy()
        {
            if (IsEmbed)
            {
                //リークしないように、破棄時に埋め込み表示を解除
                RemoveEmbed();
            }

        }
    }
}

その他の拡張

プログラムから指定のシナリオを再生する方法などは、会話シーンとして宴の使うを参考にしてください。
ページ送りなどのクリック判定を調整したい場合は、クリック検知をカスタムを参考にしてください。

注意点

埋め込み系のオブジェクトはAdvEngine以下にないため、シーンの階層構造に依存したプログラムが動作しなくなる可能性がある点に注意してください。
たとえば、GetComponentInParent(親オブジェクト以上からコンポーネントを探す)系や、GetComponentInChild(子オブジェクト以下からコンポーネントを探す)系の処理が通用しなくなります。
レイヤーやメッセージウィンドウのデフォルトのプログラムではそのような処理がないようにしているつもりではありますが、もし階層構造に起因するなんらかの不具合があった場合はQ&Aなどにご連絡ください。

埋め込み機能は基本的にはノベルゲームではなく、会話シーンとして使う場合の拡張機能として考えています。
ノベルゲームとしてのセーブロードを使う場合は、埋め込みUIが設定されているかとかUI遷移がセーブ時の状態と同じかなどは考慮されていないため注意してください。

UIを重ねて表示する場合、AdvEngineが新しいシナリオを再生する場合は、シナリオがクリアされたり進んでしまうことになります。
「前の画面の埋め込みシナリオを維持して、次の画面の埋め込みシナリオを再生する」ということはできないので注意してください。