ノベル・アドベンチャー独自構築【Unity】

絶対調味ロジック

Unityノベルパートを作っていきます。
しかしノベルゲームエンジンではないので、作り方(構築方法)がまったく分かりません。

ノベル特化のテンプレート(正攻法)はあるみたいですが、シナリオ管理で外部データ立ち絵管理にマネージャーなどなど効率よく大量のデータを扱いやすくするための組み方らしいです。

まったく分からない、そして個別に演出も加えていくであろうことと視覚的にどこがどのシーンなのかを分かりやすくするためなどで、いったん効率は度外視し独自の構築をしていこうと思います。
(後にAIに相談することになりますが、AIいわく「個人・小規模・プロトタイプ・短編」ならまだいいが、大規模・長編になると地獄を見ますよ、と言われる構築です…)

独自構築(ノベルゲームエンジンしか触ったことがない素人)

いままで「ノベル制作ゲームエンジン」しか触ってきたことがないので、Unityオブジェクト指向型という開発方法でノベル・アドベンチャーゲームをどうやって作っていけばいいのか分かりません。
セーブロードはもちろんのこと、バックログや早送りなどのシステム面の機能実装も考えると頭は真っ白です。

とにかく自分が分かりやすくないと意味がない。分かりやすいといえばノベルゲームエンジンでの開発方法
なので、ノベルゲームエンジン風の構築方法を取り入れてみようと考えながらやってみました。

Unity用ノベルアセットの「」もメジャーアップデートの時に購入しています。
立ち絵とかに個別のエフェクトなどをかけるにはどうしたらとか、自由度を上げようと解析を試みたところで心が折れてそのままになりました。

自由度を求めると、結局Unity自体に詳しくないと無理だなぁと痛感したのを記憶しています。

シーン方式

スクリプトが上から読み込まれていくのはUnityも同じです。
ノベルゲームエンジンでの制作経験を活かし、同じようになるように構築を考えてみました。

  • 素材(立ち絵・背景)など表示するであろう物を空オブジェクト内にまとめておく(すべて非アクティブ状態
  • 空オブジェクトを「シーン」と命名し、その時に表示したい立ち絵セリフを呼び出す。
  • この方法でシーンを増やしていき、キャラクター同士の会話やその合間の演出などを差し込んでいきます。

この方法でノベル部分を作ったとして、システム機能面の実装ができるのか分かりませんが、
ノベルゲームエンジン風の構築にはなっていると思われます。

コマンド方式

そしてもう1つ、ノベルゲームエンジンと言えば「コマンド」でしょう。
素材に対して「移動」「回転」「拡大」や「表示」「非表示」などさまざまな「コマンド」を適用することによって、演出が可能となります。

Unityでは「スクリプト」をオブジェクトにアタッチすることにより、そういうことが可能となります。
そこで単純な効果スクリプトを作成し、それを「コマンド」と見立てて保存しておこうという構築です。

例えば「x軸移動コマンド」の場合は、「x軸移動スクリプト」を作成し、ファイル名を「Move_x」とし保存しておきます。
スクリプト記述は移動することのみなのでとてもシンプルな記述になります。
適用の際には、オブジェクトにアタッチして、設定値を変更などして完了です。

とりあえず実行スクリプトを分けておけば、何を適用するか・何を適用しているか、が分かりやすくなるかなと。

複数のコマンドや複雑な処理がしたい場合は、それに合わせたスクリプトを別に組んでいきます。
できるだけ流用できるように、汎用性が高くなるように組んでおくと、これまた分かりやすくなると思います。

ちなみにC#スクリプトはまったく分からないため、都度AIに記述してもらっています。

立ち絵を組み立てる

目パチ口パク仕様の「立ち絵」を組み立てていきます。
今回の登場人物は3名+3ポーズなので6種類くらい作っていくことになります。

口パク

口パク」は事前に切り分けておいて、口から下のスプライト部分を採用します。
これも「スプライトシート」でやった方がデータとしても読み込み負荷としても軽くなりそうですが、そこらへんはいったん無視しておきます。

口パク」部分は「Animation」と「Animator」で制御します。
パクパクしているアニメと閉じている1枚絵を表示し続けるアニメを変数スイッチで切り替えられるように構築します。

開発中に混乱を極めたので、図解として残しておきます。

  1. パクパクしている「Animation」の「Animator」を編集する。
  2. 口を閉じている1枚絵の「Animation」と「Animator」も作っておく。
  3. 1の「Animator」に2の「Animation」をドラッグして登録する。
  4. 右クリック・コンテクストメニューを使い、デフォルト先やお互いのトランジションを追加していく。
  5. 左側の「変数」は「bool」型(true/false)のスイッチ型にしておく。

パラパラアニメの作り方は【3D】2Dパラパラアニメ【Unity6】で詳しく解説しています。

目パチ

目パチ」の方は「スクリプト」で制御しています。
どうしてアニメでの制御をしなかったのかというと…
ランダム時間」を簡単に指定できるようにしたかった、というのが理由だったと思います。
(以前の開発スクリプトを流用しているため思い出しながら作業をしています。)

インスペクターにて、使用画像の指定・ランダム時間幅やアニメのスピードを決められるようにスクリプトを組んでいます。
直観的に変更できるので良い仕様だと思います。
あと、アニメーターを使用するよりもスクリプトのほうが動作が軽いっぽいですね。

目パチは基本3枚で表現してきたので、スクリプト生成時に「3枚指定できるように」とでもしてたと思います。

簡単スナップ方法

目パチ」「口パク」を合わせる際は、3Dモードをいったん2Dモードに変更します。

ツールを「Rect Tool」に変更し「V」キーを押しながらポイントを移動させると、スナップさせることができます。

パーツができたら、一応プレハブ化しておきます。
ちょっと色が暗いのは、「影」付与設定をしたためライトの影響が出ているからです。(おそらくライトが裏にあるため)

影に関しては【3D】2Dスプライトに影をつける【BRP】で詳しく解説しています。

UI(User Interface)

UIは、現時点で必要な最低限の「名前」「メッセージウィンドウ」「待機絵」を実装しておきます。

まずは日本語フォントを登録して、日本語テキストを使用できるようにします。

登録方法は日本語フォント設定 TextMeshPro【Unity6】で詳しく解説しています。

UIは、2Dカメラアングルで「Canvas」内にUI専用オブジェクトで配置していきます。

メッセージの「待機絵」を今回は「テキスト」にしているため、点滅アニメテキストカラーを指定しています。
余韻なく点滅させるために、そのアニメ範囲に「Constant」を適用しています。

会話方法

会話は「スクリプト」を使って、しゃべらせています。
CSVファイルでの一括管理ではなく、都度そのシーンに配置したキャラクターにアセットして、インスペクター上で入力しています。オリジナルシナリオはWindows付属のただの「メモ帳」に書いています。

使用している会話システムスクリプトは以前の開発の遺産です。
当時も会話システムをどうしようか悩んでいて、機能を1つずつ追加していっているのが分かります。
会話時に必要な機能を、直観的に、できるだけ設定を変更可能にしてもらいました。

今回はVer20にして(確かクリックでのスキップ挙動がおかしかったの直してもらった)実装です。
これは「コマンド」というより「システム」よりになると思います。

  • 会話が始まるまでの時間
  • 表示するUIメッセージウィンドウセット
  • 表示するメッセージウィンドウ
  • 表示するキャラクターネームのテキスト
  • 表示するメッセージテキスト
  • メッセージウィンドウの可変有無
  • メッセージの左右マージン数値設定
  • キャラクターネーム
  • 増減可能なセリフ枠と対応ボイス(ここではポポポ音)
  • 口パクさせるキャラの「Animator」を指定
    裏でセリフが終わったら止まるようになっている(bool型でのオンオフ)
  • セリフのスピード調整
  • 待機絵の指定
  • 進めるためのボタン指定(画面クリックで進めるために画面サイズのボタンを指定している)
  • クリック連打でスキップしていく仕様
  • セリフがすべて終わった後に、次はどのオブジェクトをアクティブにするかの指定

キャラクターにしゃべらせるたびに設定しますが、おかげでシーン毎に詳細な演出をすることができるようになっています。

メッセージウィンドウを指定できるようにしているのは、たぶんキャラ毎に吹き出しを変えたいとき用だと思います。
当時にそこまで考えて実装していたのかと思うと、意外とやるではないかとなります。
いまのところ各設定は、ほぼ共通なので手間がかかるだけになっていますが…(笑

変化形コマンド用アセット「DOTween」

スクリプトでオブジェクトの「移動」「回転」「拡大縮小」などの変化を適用させることができますが、
Unity定番アセットである、変化に用いる時に便利な「DOTween」をインストールしておきます。

  • コード量が減る(10行くらいでの変化を専用コード1行で書ける)
  • 簡単コードなのでミスしにくくなる
  • 機能が豊富(ループや遅延・連鎖などが簡単)
  • 最適化されている

時間の節約」と「コードの信頼性」が最大のメリットらしいです。

DOTween」を使用してのスクリプトを書いてもらい、「コマンド」として保存していきます。

今回は新たに、絶対座標での「ポジション」「ロケーション」「スケール」の任意変化と「変化時間」「イージング」の指定ができるように「Cmd_Move_xyz」というスクリプトを書いてもらいました。

変化スクリプトには特に「イージング」を選べるようにしておくと便利かと思います。
イージングとは、動きに加速・減速を付けて自然な変化にする技術です。

変化スクリプトはイラストはもちろん、カメラにも適用できるので、カメラワークも好きなようにできます。

DOTweenのイージング一覧を世界一詳しく&分かりやすく説明する
上記のサイトで、それぞれの加速・減速の動きが詳しく紹介されていますので、参考にさせてもらいましょう。

待機の方法

今回の構築での、演出としての「待機」を記述しておきます。
シーンとシーンの間に間を取りたいときの方法です。(移動などの後に少し読み込むのを待ってほしいときとか?)

あくまで自己流ですが、「待機時間」と「待機後にアクティブにするオブジェクト」を指定できるようにしたスクリプトをアタッチし、指定のオブジェクト以下を非アクティブにしておくというものです。
(そもそも構築上ゲーム開始時はシーン1以外は非アクティブ状態にしなくてはなりません)

待機時間が過ぎるまで、下のプログラムをアクティブにしないので「待機」できている、というわけです。

上記画像では、カメラ移動とドアが開くオブジェクトがある03シーンです。
カメラ移動後に1秒待ってからドアを開くようにしています。

例でのアタッチしているスクリプトは、オブジェクト破壊指定や効果音設定もできる複合的なものです。
イベントスクリプトとして、演出時に同時に必要な設定要素を盛り込んでいる感じですね。
追加で「アクティブ・非アクティブ」にするオブジェクト指定も欲しいと気がつきました。

ノベルパート1デモ完成

とりあえずノベルパートの「」にはなったかと思います。
01シーン」からスタートして「12シーン」でフィニッシュになります。
作業途中では、カメラ位置やキャラクター位置の確認でシーンを行ったり来たり、オブジェクトを点けたり消したりと、やっぱり大変な構築でした。
しかしやりたいようにはできましたので、ヨシとします。

動画を見てもらうと分かりますが、
右側のヒエラルキー部分で、しっかりと上シーン(オブジェクト)から下シーン(オブジェクト)へ流れていっているのが確認もできます。

皮だけでもノベルパートができあがったのでホッとしています(*´ω`*)
あとは同規模の「ノベルパート」が2つ、
探索パート」が1つ、「論争パート」が1つ、とゲーム性の核が2つ残っています。

使用メモリなどについて軽く

作業をしていると、Unity使用メモリ2Gを超えていました。
Unityはじめ、ブラウザ・画像ソフト・コードソフトと必要なもの広げているだけで15G近くまで使用しています。

前まではここまで占領されるなんてことなかったと思うので、MAX16Gでもきつくなってることに驚きです。
なんかブラウザで使用されているメモリ量も年々上がっている気がするし…Windowsおまえもな…

そんなこんなも含めて、作業中に疑問に思ったメモリ関連や立ち絵位置関連などをAIに聞いて脱線もしていました。

「立ち絵の位置の確認をどうしよう?」とか「立ち絵のプレハブを複数立てたときと1つに絞ってそれを移動させるテクニックの時の場合の負荷に関して」とかメモリ関連にもつながるようなことを聞いています。

実際に「Profiler」で測ったものをAIに見せて分析もしてもらったりとか…
実機プレイでのメモリ使用量とかも気になりますし。
(メモリ使用はできるだけ控えるにこしたことはない!と以前習ったので気になってしかたがない)

このメモリに関しては記事にしていますので、興味がある方は見てみてください。
Unityエディターとビルド後のメモリについて(素人目線とAI)

コメント