ページ 11

「次の選択肢までスキップ」の仕組み(ノベルゲーム)

Posted: 2014年8月20日(水) 09:17
by ぺりお
はじめまして。ぺりおと申します。

現在DXライブラリを使用してノベルゲームを作成しているのですが、
シナリオを「次の選択肢までスキップ」させる機能の良い仕組みが思いつかないため、
相談いたします。

ゲーム自体は一般的なノベルゲームで、クリックでシナリオを読み進め、
選択肢によってキャラクターの好感度を上げ、これによりシナリオが分岐します。

シナリオは、ゲーム本体とは別にシナリオを記述したファイル(以下シナリオファイル)があり、
シナリオファイルには画面に表示するメッセージ・セリフや、
画像や音声のロード、表示、解放などの命令を記述します。
(シナリオファイルは、予めメモリにロードしておくので、
一行ごとにファイルから読み込むようなことはしません。)

また、どのシナリオファイルの何行目は、過去に実行したことがあるかどうか、
という情報をセーブデータとして持っています。
(これを利用して、Ctrlキー押下時には既読行をノーウェイトで
処理させる機能を既に実装しています。いわゆるCtrlスキップ機能です。)

ここで新たに、ゲーム中に特定のボタンを押すと、「次の選択肢までスキップ」させる
機能を作成したいと思っています。
仕様は以下の通りにします。
・現在のシナリオ位置から、次に出現する選択肢の箇所までシナリオ位置を移動させる
・スキップ可能なのは既読行のみ。もしスキップ途中で未読行が出現したら
選択肢に到達しなくても未読箇所でスキップを停止する

これを実現するために「次の選択肢までスキップ」を実装しましたが、
どうしても速度が出ず困っています。

次のように実装しました。
「次の選択肢までスキップ」中は、通常と同じように一行ずつシナリオを処理する。
(好感度によるシナリオ分岐なども通常通り行います)
スキップ中は、高速化のため画像や音声のロード、表示や再生は行わない。
ただしシナリオに従い、ロードすべきファイル名や、表示中/再生中の状態を記録しておく。
(途中に画像・音声の開放命令があれば、ロード状態を取り消します)
スキップが完了したら、記録した画像・音声のファイル名をもとに、これらをまとめてロードする。
同様にして、記録した表示中・再生中の情報に従い、表示や再生を行い、スキップ処理が終了します。

ところがこの方法では、シナリオ中のロードや描画処理などを省略しているとはいえ、
(最後に整理してまとめて行っていますが)
どうしてもスキップ対象の行数だけ、シナリオを処理する必要がでてきます。
スペックにもよりますが、仮に1万行シナリオを進めるとしたら、
かなりの処理時間が発生してしまいます。
(ロード画面を出してプレイヤーを待たせることもできますが、
どちらにしても待ち時間は誤魔化せません)

選択肢ごとにセーブデータを作っておき、これをロードさせる方法も考えましたが、
選択肢の出現回数が多いと現実的ではありません。
(好感度によってシナリオを分岐させる都合上、同じシナリオ位置にいても、
いつでも次の選択肢が同じとは限りませんし、未読箇所で停止する仕組みに対応できません)

「次の選択肢までスキップ」機能を高速化したいと思っていますが、
どのように実装するのが良いでしょうか。
皆様の知恵をお貸しいただければと思います。
よろしくお願いします。

Re: 「次の選択肢までスキップ」の仕組み(ノベルゲーム)

Posted: 2014年8月20日(水) 09:50
by softya(ソフト屋)
こういう速度問題は処理のネックが分からないので、まず計測が必要です。
・純粋なシナリオ処理
・読み込み処理
・それ以外の部分
のそれぞれの速度を計測しましょう。
計測した上で、更に絞り込んでネックを探します。
対策は、まずそれらの数値を見た上で判断すべきかと思います。

Re: 「次の選択肢までスキップ」の仕組み(ノベルゲーム)

Posted: 2014年8月20日(水) 10:01
by usao
なぜ遅いのか? がわからないと何とも言えません.
例えば,
「シナリオファイルの記述を実行時に1行1行解析して何をするのかを判断しているために遅い」とかいう話であれば
じゃああらかじめいくらか解析した結果のファイルを作っておいてそれを使えばどうですか? ということがあるかもしれませんし.
オフトピック
>「次の選択肢までスキップ」中は、通常と同じように一行ずつシナリオを処理する
スキップ処理時も それ以外の場合と「同じペースで」一行ずつシナリオを処理する とかいうオチではないですよねさすがに.
(メインループ内で毎回1行分処理してるだとかそんな)

Re: 「次の選択肢までスキップ」の仕組み(ノベルゲーム)

Posted: 2014年8月20日(水) 19:33
by ぺりお
softya(ソフト屋)様、usao様

ご回答ありがとうございます。
質問の意図としては、一万回も解析処理を回したくないけど良いアイデアはないか?
というものでしたが、
確かに処理のネックになっている箇所の調査は必要ですね。
(まだ調査はしていませんが、画像の表示、消去、開放の度に、
ロード済みのデータを検索し対象データのフラグ操作をしているため、
特にこの検索処理で時間がかかっていると思っています。)
(キャラクターの表情が細かく切り替わるので、シナリオの半分は
画像操作の命令で占められています)
そもそも一万回も回す必要がなくなれば、計測するまでもなく早くなるのは
明らかじゃないか。という考えでしたが、さすがに浅はかすぎましたね…すみません。

usao様

予め解析した結果のファイルを作っておく方法は、こちらでも考えたのですが、
(予めシナリオを選択肢まで進めておいたセーブデータを作っておき、
スキップ時にはこれをロードするような方法を考えました)
開発段階ではシナリオの行数も内容も刻々と変わっていき、
(予め作っておいたデータはすぐに無意味になってしまいます)
また選択肢の数も膨大になることから現実的ではないですし
未読箇所で停止させることが困難です。

何か良い方法があればいいのですが、本当に別の方法を取るべきか調べるため、
まずは解析からですかね。

(あと、スキップ時は、さすがに毎回メインループでの処理はしていません。
1秒間に60行しか進められないのは、遅すぎますし…)

Re: 「次の選択肢までスキップ」の仕組み(ノベルゲーム)

Posted: 2014年8月20日(水) 19:43
by softya(ソフト屋)
usaoさんの様にコンパイルか何か前処理を加えてやれば早く出来る可能性は高いですが、ネックがわからないと意味のないものになりかねません。
なので、まず分析かと思います。

Re: 「次の選択肢までスキップ」の仕組み(ノベルゲーム)

Posted: 2014年8月21日(木) 19:14
by ISLe()
ノベルゲームはあまりプレイしないのですが、わたしがプレイしたものでは次の選択肢までスキップも既読スキップと同様の処理が行われるものばかりでしたが。

シナリオデータにシーンの区切りが分かるようなマークを含めて、選択肢が含まれるシーンかどうかのフラグを先頭に埋め込んでおき、スキップ時にはシーンごと飛ばすというのが効率的ではないかと思います。
選択肢の部分だけ別シーンという分け方のほうが楽かもしれないです。

リソース管理を非同期で設計しておけば、シーンの切り替わり時に無駄な確保・解放をしないようにもできます。