🧑💻 はじめに(自己紹介)
はじめまして!
Quiitaで初めて記事を投稿します。
『チームぶんたん』のカバかもんと申します。
シナリオライターとして活動していましたが、
なんの因果か最近はUnityによるゲーム開発とノベルゲーム制作に携わることが多くなりました。
さて、『Unityでノベルゲームや普通のゲームにアドベンチャーパートを導入したい方々』に向けて、今回私がご紹介したいテクニックが……こちら!
【Unity × 宴】ADV会話中に別シーンへ遷移し、会話を再開する方法
💡 この記事は「実務でハマった問題の解決方法」をまとめたものです
🎯 この記事でできること
- ADV会話の途中でミニゲームへ遷移
- ミニゲーム終了後に会話を再開
- シナリオを分割せずに実装
❗ よくある問題
Unityではよくあること。
シーンからシーンに遷移するときに…
会話 → シーン切替 → 会話状態が消える
👉 なんと!会話の途中から再開できないということが起こりうるんです!
すっごく不便だと思いませんか?
だって、ノベルゲームとはいえ会話の途中でちょっとしたミニゲームとか導入したいときがありますよね?
例えば素敵なヒロインが……
「耳かきしてあげるね♡」
ってムフフな展開があったとして、耳かきをしてもらう3Dシーンを作成しても、
「気持ちよかった~?」
って、会話の途中から再開できないんですよ?
この現象に、困ったなーって途方に暮れた開発者は一人や二人じゃないと思うんです。
でも大丈夫!!
簡単に導入できるシーンからシーンへの切り替えの方法をこれから伝授いたしますので、ぜひご覧ください。
🎥 実際の挙動はこんな感じです
✅ 解決方法(結論)
LoadSceneMode.Additive を使うことで
👉 シーンを共存させることが出来ます!
>C#
SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
🛠 使用技術
(もっときちんとテーブルみたいにしたい)
| 技術 | 用途 |
|---|---|
| Unity | ゲーム基盤 |
| 宴などのスクリプトソフト | ADV 制御 |
| C# | ロジック |
🚀 実装の流れ
① ADVシーンを作る
ADVパートを運用するシーンに下記のオブジェクトが存在していることを確認してください:
『宴』であれば通常、全部揃っています
- Managers
- AdvEngine
- AdvEngine Starter
- EventSystem
- Canvas-AdvUI
- Canvas-System UI
② 3Dシーンを作る
例:Scene3
- 3Dオブジェクト
- Main Camera
- 戻るボタン
このシーン単体で再生できるか必ず確認しましょう
③ Build Settings に登録
ADVパートを運用するシーンと、切り替えたいシーンの2つをBuild Settingに登録してください
ここを忘れると100%動きません!
🧩 コア実装
🟦 ① GameLoader.cs(遷移担当)
🎯 役割
- ADVカメラをOFF
- 3DシーンをAdditiveで読み込み
💻 コード
📄 GameLoader.cs(クリックで展開)
using System.Collections;
using UnityEngine;
using UnityEngine.SceneManagement;
public class GameLoader : MonoBehaviour
{
public GameObject advCamerasRoot;
public void OnLoadSceneAdditive(string sceneName)
{
StartCoroutine(LoadScene(sceneName));
}
IEnumerator LoadScene(string sceneName)
{
if (advCamerasRoot != null)
advCamerasRoot.SetActive(false);
yield return SceneManager.LoadSceneAsync(sceneName, LoadSceneMode.Additive);
Scene loadedScene = SceneManager.GetSceneByName(sceneName);
if (loadedScene.IsValid())
{
SceneManager.SetActiveScene(loadedScene);
}
}
public void ResumeAdvCameras()
{
if (advCamerasRoot != null)
advCamerasRoot.SetActive(true);
}
}
💡 ポイント
Additiveロードによって
👉 ADVシーンが消えない
🟩 ② ReturnToAdvButton.cs(復帰担当)
🎯 役割
- 会話再開
- カメラ復帰
- シーン削除
※現状、ボタンをクリックするようにADVシーンに戻るようにしていますが、
そのうちゲームの進行具合によって自動的に遷移する
などの仕組みを組みたいと思っています!
💻 コード
📄 ReturnToAdvButton.cs(クリックで展開)
using UnityEngine;
using UnityEngine.SceneManagement;
using Utage;
public class ReturnToAdvButton : MonoBehaviour
{
[SerializeField] private string sceneName = "Scene3";
public void ReturnToAdv()
{
var engine = Object.FindFirstObjectByType<AdvEngine>();
if (engine != null)
engine.ResumeScenario();
var loader = Object.FindFirstObjectByType<GameLoader>();
if (loader != null)
loader.ResumeAdvCameras();
SceneManager.UnloadSceneAsync(sceneName);
}
}
👉 ReturnToAdvButton.csをGitHubで開く
💡 ポイント
ResumeScenario() → 会話再開
UnloadSceneAsync() → メモリ対策
🟨 ③ AdvCommandJump3D.cs
🎯 役割
シナリオから呼び出す
📝 使用例
カスタムコマンド『Jump3D』を作ります。
そして『宴』であればシナリオファイルにて、別のシーンへ遷移したいタイミングで、
・Commandに『Jum3D』
・Arg1に『任意のシーン名』
(完全一致させること:今回は便宜上、「Scene3」としています)
と記述します。
すなわち、下記画像の通りです。
📄 AdvCommandJump3D.cs(クリックで展開)
using UnityEngine;
using Utage;
public class AdvCommandJump3D : AdvCommand
{
string sceneName;
public AdvCommandJump3D(StringGridRow row, AdvSettingDataManager dataManager)
: base(row)
{
sceneName = ParseCellOptional<string>(AdvColumnName.Arg1, "");
}
public override void DoCommand(AdvEngine engine)
{
var loader = Object.FindFirstObjectByType<GameLoader>();
if (loader == null)
{
Debug.LogError("GameLoader が見つかりません。Managers に GameLoader を付けてください。");
return;
}
loader.OnLoadSceneAdditive(sceneName);
}
}
👉 AdvCommandJump3D.csをGitHubで開く
🟥 ④ UtageCustomSceneCommand.cs
🎯 役割
👉 自作コマンドを宴に登録
📄 UtageCustomSceneCommand.cs(クリックで展開)
using UnityEngine;
namespace Utage
{
public class UtageCustomSceneCommand : AdvCustomCommandManager
{
public override void OnBootInit()
{
AdvCommandParser.OnCreateCustomCommandFromID += CreateCustomCommand;
}
public override void OnClear()
{
}
public void CreateCustomCommand(string id, StringGridRow row, AdvSettingDataManager dataManager, ref AdvCommand command)
{
switch (id)
{
case "Jump3D":
command = new AdvCommandJump3D(row, dataManager);
break;
}
}
}
}
👉 UtageCustomSceneCommand.csをGitHubで開く
📜 シナリオの記述
ここは『宴』などのスクリプトソフトで楽させてもらいます
👉 シナリオファイル をダウンロードする
※ [Start]シートをご参照ください
肝となるコマンドはこちらです!
- Jump3D Scene3 (自作のカスタムコマンド。AdvCommandJump3D.csで作成し、UtageCustomSceneCommand.csで使えるように登録しました)
- PauseScenario (『宴』に標準で備わっているコマンド。シナリオの進行を止めることができる)
⚠️ ハマりポイント
❌ EndScenarioを使うと……
👉 会話が終了してしまう
✅ PauseScenarioを使うと……
👉 再開できるようになります!
🎥 カメラ競合するという問題
ADVシーンも遷移先のシーンも、通常であればカメラを1つずつ持つことになりますが……
今回の処理では遷移先のシーンを読み込んでも以前のシーンを消さない(unloadしない)ようにしているため、
両方のシーンのカメラが残っていると、描画が壊れます
だから……
→ ADVカメラをOFFにする必要があるんです
🧠 メモリ問題
Additiveの機能を使うと、遷移先のシーンも遷移元のシーンも両方が残ることになります。
だから……
→ UnloadSceneAsync()が必須なんです!
✨ この方法のメリット
- シーンを遷移する前と後とでシナリオを分割する必要がなくなります
- 会話がどこまで進行したかを保持できます
- 『宴』と『Unity』公式の方法で実装しているので、シンプルかつ拡張しやすいです
🎉 まとめ
- Additiveでシーン共存
- PauseScenarioで停止
- ResumeScenarioで復帰
👉 これで
🎮 会話 → ミニゲーム → 会話復帰
が実現できます!
🔗 おわりに・お問い合わせ
ADVゲームのシナリオ制作・実装のご相談を承っています。
「こういうことできる?」といった段階でも大歓迎です。
👉 https://buntan-works.jp/#contact
お気軽にご相談ください!
📌 次回予告
ADVパートを作るのに必要な
- 『Unity』とスクリプトソフト(『宴』や『Naninovel』)をインストールして、ゲーム用プロジェクトを作成する
をご紹介したいと思います。
お楽しみに!
🙏 参考
Unity公式 Additiveロード
https://docs.unity3d.com/jp/2020.3/ScriptReference/SceneManagement.LoadSceneMode.Additive.html




