唸れ俺の挑戦談!VR ADVツールを作った過程解説! – 東京クロノス
豪華開発陣が集まった事を売りにしているしている本作ですが、開発自体は少人数で行っている為プレイ時間が十数時間に渡る本作を作るには可能な限り作業効率を上げる必要がありました。
その一つとして、東京クロノスのメインコンテンツであるキャラクター同士の会話劇等の演出を作る為のツール「Uranus」を制作しました。今後同じジャンルのゲームを作りたいと思う人がいる事を期待して、今回はこのツールがどの様にして現在の形に落ち着いたか、そしてそもそも何故制作したのかという過程を紹介して行きたいと思います。
核となる要素の洗い出し
まず制作にあたり、会話劇を作るのに最低限必要な要素を洗い出しいくと下記の様になりました:
– プレイヤーの位置や向き指定
– キャラ操作(配置、モーション、等)
– テキスト表示(セリフ&地の文)
– 背景指定
– サウンド指定

これだけあれば取りあえずは会話場面を作れるであろうという事で上記を満たす制作環境を考えて行きます。
既存ツールを見てみる
さてテキストアドベンチャー系のゲームを作る開発環境は既存の物が色々とあります。Oculus Goも対象にしたクロスプラットフォームのVRゲームを制作するという前提の元、今作はUnityを使用させて頂いていますが、Unityで開発する上で演出制作に参考に出来そうな物は無いかと見まわしてみました。結果、短く纏めると下記の様なカテゴリー分けになりす:
【スクリプト言語】
Lua、 Squirrel、等。RPGとかだと結構使われる手段
【ノベルゲーム用のスクリプト環境】
NScripter、吉里吉里、等
【ノベルゲーム固有の開発ソフト】
ティラノビルダー、ノベルツクール、等
【Unityアセット】
宴、Fungus、Adventure Creator
Excelベースでやってみる
既存ツール色々とありますね。何が良いかは正直何を作るか、どの様に作りたいかによるとしか言えないので、試作を作りながら試してみる事にします。まずはノベルゲーム系では鉄板なアセットである「宴」と同じ手法、Excelベースでやってみる事にしましょう。
ゲーム業界人なら皆大好きExcel(諸説あり)を使用する理由としては、宴の手法でもあり、エクセル自体は操作覚える事は少なく、ゲーム業界で良く使用するやつでもあり、シナリオも翻訳を考えると管理がExcelになりそうでしたので一回試してみました。

この様なExcelファイルをScriptableObjectに変換し、実行時に1行1行処理して行く様に実装してみました。

最初の試作。当時キャラは「ピンクマン」でした
やってみた結果は・・・辛い!!
辛い箇所としましては、主に全てが1画面に収まる2Dでなく3Dの演出を作る必要があり、エクセル上で配置や回転指定をする事が結構想像力を使う上にUnityとExcelを行き来する必要が生まれ時間がかかるトライ&エラーな作業になってしまいました。
更に演出を組んでいる期間ずっとExcelの画面を眺めている事になるので、これも作業者にあまり優しくない環境でした・・・えくせる、つらい。
Timeline/カットシーン系ツールは?
ではUnityのTimelineやカットシーン系のアセットでやるのはどうかとも考えてみたのですが、課題として
– プレイヤーの入力待ちが定期的に入る
– 要素が増えて行くとタイムライン系のGUIが見辛くなる
というのがあった為、今回は見送りました

社内ツール制作!ツールの目標と対象ユーザー決め
ここまで検討して来ましたが、既存のUnityアセットでもある程度の簡易性と東京クロノスに合った仕様の物が無い為、それなら作って見るかとエディターの試作を作る事に舵取りをします。
ツールを作るにあたり、まずゲーム制作同様対象ユーザーを決めて内容を決める必要があった為、誰が使う想定かを最初に考えて行きます。当時(というよりも終盤付近まで)は演出/イベント専任の担当が居なかったのと演出を作る為の人数が足りていなかった為、対象をディレクター、プロデューサー、シナリオライターにし、ゲーム制作やツールの経験でもない人が触っても極力制作出来る様にしようと方向性を決めました。
要望洗い出し
対象の利用者を決めましたので、今度はどの様な環境で制作したいかを相談して行きました。要望としてディレクターから出たのが下記になります。
【Unity内で完結したい】
エクセルの時の様に他のソフトと行き来せず、全てUnity内で完結したい。画面を分けたり切り替えたりが少しとはいえ手間かつ時間がかかるので、それを避けられる様な作りになっていると嬉しい。
【テキストベースよりGUIベース】
スクリプトナンモワカラン
【ポチポチボタン押すだけで作れると嬉しい】
文字画面を見続けるのでなく、感覚的にボタンを押すレベルで簡単に演出を作れると嬉しい。
【1テキストウィンドウ毎に演出を付けて行ける様にしたい】
プレイヤーの入力でテキストが先に進むのに合わせて演出を作れる様に出来ると作りやすい。
でした。これらを踏まえると、機能はある程度限定的にして極力シンプルに扱えるものを目指す方向性を決定出来ました。
ツールのGUI参考
いざエディターを作る前に、今度はGUIのレイアウトで参考になる物は無いかと見た結果「ティラノビルダー」というツールがGUIが凄く分かりやすく、こういう方向性なら必要な要素を満たせそうだったので、思いっきり参考にしました。

ティラノビルダー: https://b.tyrano.jp/
ティラノビルダー凄い!先人の功績に圧倒的感謝・・・!
この辺を参考にしてラクガキしてたらこんな感じになりました

ほぼそのままですね!
・・・はい、すみません。上の方に書いてあるのはシナリオのデータと演出のデータをどう扱おうか考えていたメモです。基本的にはエクセルの時同様1行1行処理をして行く様にする予定で、それらを一つ一つの「コマンド」として視覚的に一覧化しつつ、追加も簡単に出来る構造を目指したいので、この基準で行きました。
作ってみた
上記を元に実際にUnityのエディター拡張で作って見たら結果的にこうなりました

左側が追加出来るコマンド、真ん中がコマンド一覧、右側がコマンドの詳細でこの辺はティラノビルダーやラクガキと同じです。実際に作り始めて意識したのがコマンドを出来るだけぱっと見で誰が何をするかを判断出来るようにする事で、その為にコマンドの左側にまずキャラのアイコンやコマンド種類のアイコンを置き視認性を上げる様にしました(と言いながらアイコンやコマンドの色が雑なのは反省点です・・・)。
それで少し試した後にキャラ操作系のコマンドはキャラのアイコンが無いと誰かパッと見で分かりにくいのでキャラアイコンを操作系コマンドにも上乗せで追加しました。
シナリオ読み込み
演出を作るにあたり、まず基盤となるシナリオを読み込んでそこに演出を付け足していく必要があります。なので、実際にシナリオを読み込んで演出を作り始める手順を紹介します。
まず、シナリオのテキストと誰が喋っているかのデータが入っているScriptableObjectを読み込みます。

データを読み込んだらそれらを1個1個別のコマンドに変換して行きます。この時点で演出に最低限必要なマップの指定等も生成されます。この中に後は演出で行いたい操作を追加して行って制作をします。作った演出ファイルはまた別のScriptableObjectに保存しています。
プレビュー機能
このエディターを使いやすい物にするにはコマンドを演出一覧に追加や編集したら即変更を確認出来る環境を用意する必要性を感じたので、プレビュー機能を追加する事にしました。
プレビュー機能で必要な要件としては
– マップ読み込み
– コマンドを選択したらその場面が再現される
– 数値等を変更したら即時反映される、
と想定し、作業を開始しました。

当時のメモ書き
実装のアプローチとしましては、作業用のシーンを用意し、Uranusを開いた時のそのシーンへ遷移します。そのシーン内にキャラやカメラ等を事前に用意しておき、必要に応じてアクティブにしたり変更を加えて行っています。マップに関してはマップロードとアンロード用のボタンを用意し、必要に応じて使用するようにしています。
選択したコマンドを反映するにはまず動かす事を優先して一番上から選択したコマンドまでの全てのコマンドを順番に処理して行き、作業用シーン内にあるカメラやキャラをそれらで操作しました。

これから

選択後にこれに
エディター拡張するエディター拡張
エディターを作ったのは良いのですが、最初からゲームの仕様が完全に決まっている訳も無く、途中からどんどんコマンドを追加して行く必要が出ました。完全に設計ミスですが、エディター上に出すコマンド群は基本的にスクリプトに記載されており、加えて触る必要があるスクリプトが複数有ったり新規にスクリプトを追加する必要があった為コマンドの追加が手間になっていました。
この手間を失くす為に新しいコマンドを追加する時必要な要素を選択して一括で自動で追加する、エディター拡張を拡張するエディター拡張を制作しました。
各コマンドは全て個別のクラスになっているので、まず自動化する箇所の一つとして新規にコマンドを追加する際にはコマンド用のスクリプトテンプレートを用意してそこから手軽に作れる様にしました。

その上で、追加したファイルをGUI上にドラッグ&ドロップして設定を入れるだけで新規コマンドをエディターに追加するエディター拡張を制作する事で作業を自動化しました。

各種項目を記入しGenerateボタンを押すと新規スクリプトの作成と既存のスクリプトへの追記が行われます。
新規追加のクラスはテンプレートを用意し、記入に従ってString.Replace()を使用してテキストをテンプレートの物から実際に追加するスクリプトの物へ変換していっています。ファイル名はGUI上に表示されている物がそのままファイル名になっています。

新規スクリプトテンプレート

作成されたスクリプト
既存のスクリプトへの追記はスクリプト内にここに追記するという目印をコメント内に記載し、それを検索して追加する方法を取りました。

今回は[end]という文字列を目印とし、それが含まれている行の1個上に新規コマンドの情報を追記しています。上記画像ではインデントが崩れているので自動追加分が分かりやすいかも知れません。
これでコンパイルが走れば追加したコマンドがエディターに追加され使える様になっています。こうやって手作業を何とか減らして効率化を目指して制作を進めて行きました。
クソ実装 vs シリアライズの壁
エディターの基本的な話は終わりましたが、一つ作業効率的に影響受ける要素が残っていました。ここも完全に設計ミスというかアホな実装をした結果なのですが、エディター拡張を行う際PropertyDrawerのようにUnityで用意されている機能を使用せずに制作した為、スクリプトのコンパイルやゲーム実行等でシリアライズが走るタイミングでエディターの中身がリセットされてしまい、作業途中の物が毎回無くなってしまいました orz
これを作り直しを行わず無理やり回避する為に(非推奨!本当はちゃんと作り直しましょう)ScriptableSingletonを使用しました。ScriptableSingletonはエディターが生きている限り残るオブジェクトです。EditorWindowを継承したメインのウィンドウクラス内のOnDisable()内で現在開いているファイルや選択しているコマンドの位置等を保存し、OnEnable()内でそれらを元にもしエディタがリセットされている状態なら開き直す仕組みを入れて解決しました。

制作途中の演出は実行時に一時ファイルに保存し、Uranusからゲームを起動した際にはその演出ファイルからゲームが始まる様にデバッグ機能として仕組みを入れています。上記のOnDisable()で一時保存する際はこの一時ファイルに現状を保存する事で作業途中の演出の復帰を果たしています。
これらにより演出を組んで実行して検証し、また停止後に直ぐ演出組みに戻れる仕組みを用意出来ました。
—
今回の話は以上になります。
途中からはいかにダメな実装してしまったかの恥を晒す感じにはなってしまいましたが、アイツはこんなふうにやったんだと同じようなゲームを作ることを考えている人の参考になれば幸いです。
もしこれを読んで「もっと良いエディターの案あるぜ!」という方がいらっしゃいましたら是非語りましょう!