2011年3月7日月曜日

やりたいことがあるときは

どうも、deltaですよ。しばらくブログ記事を書いてなかったので、そろそろまた技術ネタを書く時期ですね。



ビジュアルノベルは、コンピュータープログラムとしてみた場合、本気で考えないといけない「機能」というのはそれほど多くない。小さな違いはあるかも知れないけど、ユーザーエクスペリエンスという点では、どれも非常によく似ている。そのこと自体は何の問題もない。そもそも最初から極端な違いなんてないからだ。「ビジュアルノベル」という言葉自体がその体験の定義になっている。実際、既存のVNエンジンを使う理由のひとつは、ビジュアルノベルという形態に期待される機能が一揃い用意されているからだ。VNはプログラムを作るのが極端に難しいわけではないけど、こんなに狭いフィールドでは車輪の再発明をする理由は少ない。だからといって、開発者が何も考えてなくても許されるわけじゃない。VNのユーザーエクスペリエンスにおける仕様の多くは、慣例的にそのようになっている。そして、慣例というのは必ずしも正しいわけじゃない。(間違ってるわけでもないけど)もし開発者がありきたりなものでは満足できないと思ったら、エンジンや慣習がどうなっていようが、やりたいようにやっていいし、そうすべきなのだ。

そうした機能のひとつが「既読テキストを読み返す手段」だ。これは何らかの形で可能になっていないといけない。そして、これにはまさに慣例が存在している。ほとんどのVNで私が目にしたのが、上下にスクロールできるリストの形でバックログを表示する方式だ。私たちが使っているエンジンであるRen'Pyは、「ロールバック」と呼ばれる別の形式を取っている。(これに対して、最初に述べた形式は「リードバック」と呼ばれる)ロールバックはインタープリタの状態をまるまる以前の時点に「巻き戻す」ことができる。これは間違いなく技術的には優れた形式で、実装するのはずっと難しい。Ren'Pyの売りのひとつでもある。読者はテキストだけではなく、文脈まで--キャラの表情、音、アニメーション、すべて込みで、画面全体を以前の状態で見ることができる。

さて、これにはひとつ問題がある。Ren'Pyの標準機能ではこの形式しかサポートされていない。そして開発者というのは選択肢を求めるものだ。これには様々な理由が考えられる。自分のゲームに「本物の日本製ゲームっぽさ」を出したいとか。物語的に、これまでとは異なる手法を使いたいとか。もっと(私にとってだけど)重要なのは、Ren'Pyはインタープリタの状態を丸ごと巻き戻す。このとき、それ以前に発生したプレイヤーの入力は選択肢の選択を含めて、すべて破棄される。ここで仕様上の判断が必要になる。リードバック/ロールバックというのは、実際には何を意味するのか? Ren'Pyは、エンジンはゲームをプレイヤーに表示するためのツールでしかなくて、できる限り選択肢を読み手に委ねる、という思想に立っている。意図的に設計された体験ではなくて、「リーダーアプリケーション」というわけだ。ロールバック支持論として頻繁に出てくるのが、「読み手はゲームのセーブ・ロードができるじゃないか、まさかそれも禁止ってことはないよな?」というものだ。私に言わせれば、これは妥当な主張とはいえない。まず、一般的なビデオゲームでゲームデザイナーが「セーブしまくり」とでも言うべき行動をできなくすることはありうる。KSではそういう制限はしていないけど、物語上の、さもなければ今までだれも考えたことがないような理由がどこかにあるかも知れない。(余談だけど、KSではセーブ・ロード機能にも手を加えている。デフォルトのRen'Pyは日本製のVNで見られる「セーブスロット」の仕組みを丸パクリしている。これ自体はバッテリーでデータを保存していたファミコンゲームの仕組みから取られたものだ。ちょっと最新とは言いがたいので、KSでは2004年頃からSourceのゲームで採用されているシステムを使っている。21世紀に生きてて良かったね。)

結論はこうだ。私はKSにおけるテキストのバックログを、主人公の記憶と考えている。そして記憶というのは不変のものだ。ロールバックをするとき、プレイヤーは「インタープリタの巻き戻し」を行っているのではなくて、プレイヤーがすでに見た光景を読み直しているのだ。これは暗黙に、選択のやり直しができないことを意味する。もちろんセーブと再ロードはできるけど、単にマウスのホイールを回すのに比べれば、セーブ・ロードはずっと意識的・意図的に行われる、重大な行為だ。

理由がどうあれ、何かが「本質的に優れている」からというだけで、ゲーム開発者が制約を受ける理由はない。カラー映画が作れるのだから、白黒の映画を作ってはいけないと言うようなものだ。ゲーム内でのプレイヤーの相互作用を制約することは、何らかの理由で、デザイン上の目的になりうる。そしてもし開発者がそのようにしたいのなら、そうできるようになっているべきだ。Ren'Pyにはロールバック以外のバックログ機能はないけど、自分で機能を作り込める程度にはオープンで柔軟だ。

KSのAct 1には私自身が設計したリードバック機能が実装されている。ロールバックもできる(あればうれしい機能には違いない)けど、選択肢まで戻るとロールバックが止まる。つまり選択肢を越えて巻き戻すことは絶対にできないようになっている。これなら一度選んだ選択肢は変えられない。ロールバックできなくなったテキストを表示したいときは、リードバックが使える。この仕組みは明らかに不完全なので、決して満足はしていなかった。自分が欲しかったのは、選択肢はやり直せないけど好きなだけ戻れるロールバックだと思った。なのでそれを実装した。

私が作ったものはちょっと複雑なので、ここで詳しく説明はしない。Ren'Pyはロールバックとは独立した「プレー一周単位」でのメモリという概念がない。これがまさに必要な機能で、問題を難しくしている理由だ、とだけ言っておこう。Ren'Pyには「ストア」(プレー一周単位のデータを保持できるが、完全にロールバックされる)と「パーシスタント」(ロールバックはされないが、インストールされたゲームについてグローバルとなる)という機能しかない。結局私は、プレーの周回が始まるたびにユニークなIDを生成してストアに保存し、このIDをパーシスタントに保存されているデータベース内のインデックスに使う、という実装をする羽目になった。実際にはそれほどややこしくはないけど、それでも自分で考えついて作り込まなくてはいけなかったのは確かだ。もしかしたら最終的にリリースされるKSには含まれないかも知れないけど、評価のためにはこれをやってみるしかなかった。自分が欲しいものについて考え、そして少なくとも実際に検証する。それがここでの教訓、そして私がこの文章を書いている理由だ。エンジンや慣習がそうなっているというだけで、最初から自分に制限をかけてしまってはいけない。それが自分以外の誰も気にしなさそうな、とても小さなことであってもだ。みんながやっているからというだけで、何かをやってはいけない。ただし、様々な相反するアプローチから、一番いいものを選ぶ用意はしておくこと。最終的には、自分で「もっといい」もの、さもなければどちらよりも適切なものを思いつけるかも知れない。

みんながそれに文句を言い出さない限りは、だけどね。そのときは振り出しに戻ってやり直しだ。

P.S. 絵についてはAuraの方が手が早かったんだけど、climaticも混ざりたいと言ってきた。なので最後まで読み終えた人へのご褒美に、彼のイラストをどうぞ。

- delta

0 件のコメント:

コメントを投稿