Naninovelは、非常に多機能で柔軟なビジュアルノベル支援アセットです。
このアセットは、「NaniNovelスクリプト」(.nani)という独自のスクリプトを使用してゲームを作るため、厳密には「ノーコードのアセット」ではないのですが、基本的にC#の知識なくこのアセットのみでビルドまで行うことを前提としています。
そのため、既存のゲームの一部にNaniNovelを組み込んでC#から制御しようとすると、一工夫必要です。その手順を紹介します。
なお、基本的な情報は公式ドキュメントにガイドがありますし、公式のサンプルプロジェクトもあるのですが、より柔軟な方法を解説する記事です。
手動で初期化する
始めに、この記事を参考に、NaniNovelを自動で初期化させないよう設定します。
設定ウィンドウの[Naninovel] - [Engine]にある「Initialize On Application Load」と「Show Title UI」のチェックマークを外す
CameraとEventSystemをDisableにする
次に、ゲーム起動時など早い段階で初期化を行いますが、場合によっては前述の記事だけで解決されない問題が発生します。
初期化を行うとCameraとEventSystemを含むNaniNovelオブジェクト一式がシーン内に生成されるため、もし既存のシーンにCameraやEventSystemが存在している場合は
- 「AudioListnerが二つ存在する」という警告が発生
- 「EventSystemがシーン内に二つ存在する」という警告が発生
- NaniNovel側のCameraのせいで画面が真っ暗になる
- 画面全体を覆うボタンUIをDisableにしないとマウスがNaniNovel以外に機能しなくなる。
など、色々と不都合があるのです。
そのため、初期化後にNaniNovel側のCameraとEventSystemをDisableにする必要があります。
まずイベントシステムについては、PlayerSettings -> NaniNovel -> Input -> [Spawn Event System]と[Spawn Input Module]をDisableにするだけでOKです。元々シーンに配置しているものだけ使えば良いですからね。
続いて、カメラと画面全体を覆うメッセージ送りボタン(ContinueInputUI)をDisableにする処理ですが、これは「アクティブにも非アクティブにもできる」という汎用的な処理にしたほうが後々便利です。そのため、処理内容は次のようになります。
- 既存のCamera、EventSystemがシーン内に存在するなら、それをアクティブ切り替え。
※私の環境だけかもしれませんが、なぜかCamera.mainを使用するとエラーになったため、オブジェクト名とこの記事を参考に、非アクティブなオブジェクトも含め探す方法を採用しています。 - ICameraManagerを使ってNaniNovelカメラをアクティブ切り替え。
- IUIManagerを使ってNaniNovelの画面全体を覆うボタンをアクティブ切り替え。
コード例は次のとおりです。
- 初期化
- アクティブ切り替え
とりあえずこれでNaniNovelの初期化はするけど、既存のゲーム画面に変化は起こさないということを実現できました。
- 初期化は一度行えばOKで、シーンを切り替えた後に再度初期化する必要はありません。
- 初期化時に生成されたNaniNovel関連のオブジェクトはDontDestroyOnLoadで保持されるため、シーンを切り替えても残ります。
- 一度初期化した後に初期化しようとしてもエラーにはなりません(NaniNovel側がガードクローズで二度目以降の初期化を防いでいるため)。
NaniNovelスクリプトをC#から呼び出す
続いて、特定のNaniNovelスクリプトをC#スクリプトから個別に呼ぶ方法です。
これは簡単で、前述のコードを一部流用して
これだけでOKです。
NaniNovelスクリプトを終了する
で、NaniNovelスクリプトの会話が終わったらどうすればよいのかというと、次のことができれば概ねなんとかなりそうです。
- NaniNovelスクリプトが終了したことをC#側で受け取る
- どのNaniNovelスクリプトが終了したのかをC#側で受け取る
- NaniNovelオブジェクト一式を非アクティブにする
NaniNovelではカスタムコマンドといって、自分でコマンドを新設できるシステムが用意されています。
そこで、このようなクラスを用意します。
このクラスはオブジェクトにアタッチする必要はなく、作っておくだけでNaniNovelスクリプト内でコマンドとして使用できます。
これでNaniNovelスクリプトが正常に終了させ、ついでにどのスクリプトが終了したのかも検知することができました。