プロフィール写真

ゲームエンジン「吉里吉里1~3」開発者

W.Dee

ソフトウェアエンジニア。学生だった1999年、ゲームエンジン「吉里吉里」シリーズおよびスクリプト言語「TJS」、シナリオシステム「KAG」の開発を開始する。その後も、ソフトウェア系企業に一貫して在籍する。

X:@wdko GitHub:w-dee

1990年代末から2000年代にかけて、PCゲーム市場を席捲したアドベンチャーゲーム。特にノベルゲームと呼ばれるジャンルにおいては、当時のクリエイターを支えたツールとして「NScripter」というノベルゲームエンジンが広く知られていました。

他にも、同じくらい有名なエンジンがあります。歴史的ヒット作『Fate/stay night』にも採用されたゲームエンジン「吉里吉里」シリーズです。1999年に公開されたこのツールは、①エンジン本体、②独自スクリプト言語「TJS」、そして「TJS」にて構築された③ノベルゲーム制作システム「KAG(※1)」という、3層構造の特殊なアーキテクチャを特徴としていました。

開発者のW.Deeさんは、その後もさらなる軽量化や最適化を求めて、後継ソフトの「吉里吉里2」、そして「吉里吉里3」とアップデートを重ねます。しかし、「吉里吉里3」の開発は途中で停止。W.Deeさんはプロジェクトの最前線から身を引き、ソースコードは有志による「吉里吉里Z」(2013年に正式版公開)へと引き継がれました。

なぜ既存のツールを使わず、①実行環境そのもの ②独自のスクリプト言語、さらに ③シナリオ記述システム に及ぶ複雑な構造を1人でつくり上げたのか。そして、一時代を築いたプロダクトを、なぜ手放すに至ったのか

「技術的な挑戦としては十分に満足しています」と語るW.Deeさんに、吉里吉里という巨大なシステムに捧げた日々と、その裏側にあった開発思想についてお聞きしました。

(※1)KAG:KiriKiri Adventure Game System。吉里吉里のコアエンジンの上で動作し、マークアップ方式の言語でアドベンチャーゲームのシナリオや演出を制作できるシステム。

「吉里吉里」・「TJS」・「KAG」の主要な歴史
1999年
「吉里吉里1」とシナリオエンジン「KAG1」を開発。当初はJScriptベースで動作。その後、同年に独自スクリプト言語「TJS1」を実装。「KAG1」は「KAG2」へと進化し、エンジンと言語、シナリオシステムが一体化する。
2000年
次世代スクリプト言語「TJS2」を実装。
2001年
アーキテクチャを刷新した「吉里吉里2」および「KAG3」を開発。
2005年
「吉里吉里3」の開発を開始。
2013年
有志による「吉里吉里Z」が公開される。

「どのように使われるかわからない」ツール:『Fate/stay night』に注視した理由

――「吉里吉里」というプロジェクトがスタートした当時の開発環境や動機についてお聞かせください。

W.Dee:「吉里吉里」は、もともと自分自身がゲームを制作するために開発したエンジンです。主に、アドベンチャーゲームを制作しようと考えていました。

――なぜ既存のゲームエンジンを使わず、自作することを選んだのでしょうか?

W.Dee:当時の私には、そもそも既存のエンジンを利用するという発想がありませんでした。 当初の最大の目的は「ゲームを制作すること」でしたが、そのためのエンジンをつくるという「技術的な探求」そのものも、大きな動機になっていたからです。

なので自然と「必要なものは自分でつくる」という選択を取ることになりました。

――アドベンチャーゲーム制作が目的だったとのことですが、完成した「吉里吉里」本体は汎用性が高いですよね。アドベンチャーに特化した部分は「KAG」が担う一方で、コアエンジン自体は工夫次第でアクションゲームすらつくれます。なぜこのような仕様に?

W.Dee:「こういう機能が必要になるかもしれない」「こういう演出もやりたい」と考え続けている段階が長く続き、その過程で蓄積されたアイディアが、結果として「吉里吉里」の汎用性につながっていったのだと思います。

また、アドベンチャーゲーム制作が主目的とはいうものの、そもそもこのジャンル自体、実はかなり定義が曖昧で幅があると思うのです。

――というと?

W.Dee:アドベンチャーゲームは、単純なテキスト表示を主体とするものだけではなく、戦略ゲーム的な要素や、アクションゲーム的なミニゲームを含む作品まで含まれます。そうしたゲームの制作にも対応しようとすると、どうしてもエンジンには柔軟性や汎用性が必要になります。

――シナリオやテキストを表示するだけのツールにしてしまうと、多様なニーズに応えられなくなってしまうわけですね。

W.Dee:これに加えて、開発時に「せっかく自分でエンジンを開発するのであれば、それを公開し、他の方にも利用してもらいたい」と考えたことも大きかった。他の方にも使ってもらうという前提において、特定用途専用の構造にしてしまうと、応用範囲や拡張性が制限されてしまうため、自然とより汎用的な方向へ進んでいきました。

そしてこの「他人も使う」という前提は、アーキテクチャの構造にも大きな影響を与えています。

――詳しく教えてください。

W.Dee:「吉里吉里」シリーズは初期から一貫して「ゲームエンジンの開発が中断されても、ゲームの開発は継続できるべきである」という設計思想のもとで開発をしてきました。

これは、「吉里吉里」があくまで個人の趣味として開発されたエンジンであることに由来しています。商業開発であれば、体制や契約によって開発の継続性はある程度担保されますが、個人開発においては、どんな理由にせよ、ある時、開発が停止する可能性があります。

そうした前提に立つと、「エンジンの保守が止まったせいで、その上で進んでいるゲーム制作まで巻き込んで止まってしまう」という事態が発生するのは避けるべきだと考えました。

そのため、大きく2つの要件をアーキテクチャに組み込みました。ひとつは、有事の際に私以外でも開発を継続できるよう、エンジンはオープンソースとして公開し、誰でも改良や拡張に参加できる形を取ること。

もうひとつは、「C++などで書かれたゲームエンジン本体というコア部分に手を入れなくても、ゲーム制作を完結できるようにする」ことです。

そのため、エンジンは可能な限り柔軟に設計し、スクリプトや外部定義によって挙動をコントロールできるようにしました。スクリプトで挙動を変えられる設計にしておけば、コアエンジンのソースコードをコンパイルできない非プログラマーでも、ゲームの仕様変更や拡張を容易に行えるので。

このようにして「他の方も使う、汎用性の高いゲームエンジン」として「吉里吉里」の開発を進めました。しかしこうなってくると、別の前提も考慮しなければならなくなりました。

――それは何でしょうか?

W.Dee:「どのように使われるかわからない」という大前提です。

ゲームエンジンとして汎用性を持たせる以上は、特定の用途だけでなく、あらゆる使われ方に対応できる必要があります。そのため、「どのような使われ方をしても、できるだけキビキビと動作すること」もひとつの目標としました。

もちろん、すべての利用形態を事前に想定することは不可能であり、ある程度の割り切りは必要になりますが。

――その「割り切り」の中で、特に苦労した技術的な課題は何でしたか?

W.Dee:「実行の安定性の追求」と、「低スペックPCへの対応」です。90年代末期の開発当時に普及していた典型的なPCの性能は、例えて言うと「Socket 370(※2)世代のCeleron 400MHz、メモリ64MB程度」といった構成です。MP3やVorbisの音声を再生するだけでもCPU使用率が10パーセント超を占めるような時代であり、現在の感覚からすると非常に限られた計算資源しかありませんでした。

このような環境を前提とすると、設計にはまた新たに、いくつかの重要な要件が生まれます。まず、ターゲットとなる最低スペックに確実に合わせることです。特に、環境によって動作が左右されやすいグラフィックス(GPU)のハードウェアアクセラレーションには極力依存しない設計としました。

次に、その制約の中で可能な限り軽量に動作すること。さらにその上で、ゲームエンジンとしての柔軟性を確保する必要もありました。これらは互いに強いトレードオフの関係にあります。軽量化を追求すれば柔軟性が犠牲になりやすく、柔軟性を高めれば実行コストが増えやすい。そうした相反する要求のバランスを取ることは、当時において大きな技術的チャレンジでした。

(※2)Socket 370:1998年にインテルが発表したCPUソケットの規格。Pentium IIIやCeleronなどのプロセッサで採用された。

――ハードウェアアクセラレーションに頼らずに軽量化と柔軟性を両立させるとなると、相当なチューニングが必要になりますよね。

W.Dee:はい。相反する要求ではありますが、基本的な処理については可能な限り最適化を行う、という方針を取りました。

特に当時の環境で、グラフィックスのハードウェアアクセラレーションに頼らない設計とした以上、画像処理の重いピクセル演算もすべてCPU単体で担う必要があり、そこが最大のボトルネックになることは明らかでした。

そのため、描画や画像操作に関わる処理については、速度面でのアセンブリ言語を用いた最適化などに重点的に取り組んでいます。

こうした方針は、「吉里吉里1」から「吉里吉里2」に至るまで一貫しています。

――そうしてリリースされた「吉里吉里」からはいくつものヒット作が生まれ、アドベンチャーゲームやノベルゲームの文化を支えたひとつのインフラだったように思います。こうした盛り上がりを、開発者としてはどのように受け止めていましたか?

W.Dee:まず、やはり『Fate/stay night』については、特に強く注視していました。

理由としては、「吉里吉里2」(Fate/stay nightで採用された)が大規模な商業作品で実際にどのように動作するのかについて、掲示板やユーザーからの反響を通じて大量の実運用データが得られたためです。その反響の大きさは、正直、想定していた範囲をかなり超えていました。冷静に受け止められるような規模ではなかったと思います。

一方で、このツールが大規模に普及するにつれ、興味深い現象も見えてきました。

――なんでしょうか。

W.Dee:当時「吉里吉里2」自体の安定動作性は、かなりの精度で実証されていました。それにもかかわらず、「ロジック上は起こりえない」不具合報告が多数寄せられるようになったのです。

解析を進めていくと、その一部はソフトウェアではなく、ハードウェア側の信頼性に起因していることが分かってきました。例えば、HDD上やメモリ上で発生する突発的なビット反転です。

――ビット反転というと、宇宙線などの影響でデータが勝手に書き換わってしまう現象でしょうか? そのような稀な現象が、実際に報告として上がってくるほどのユーザー人口だったことが伺えます。

W.Dee:大量のユーザー環境にさらされることで、この他にもさまざまな問題が表面化してきました。当時のPC環境は、現在ほど安定してはいなかったので、なおのことでした。

それにしても、「吉里吉里2」では、先ほどの話の通り環境依存性の強いハードウェアアクセラレーションには極力頼らず、比較的保守的な設計を取っていました。それでもなお、不具合報告が多数寄せられたわけです。

今振り返りますと、もしも当時からハードウェアアクセラレーションを多用していた場合、安定動作の確保は相当困難だったかもしれません。

――ちなみに、当初ご自身でつくろうとしていたゲームはどうなったのでしょうか?

W.Dee:当初構想していたゲーム制作自体は、構想段階で中断しており、未完のままになっています。

逆に言えば、もしそのゲームが完成していたら、「吉里吉里」もそこで成長を止めていた可能性はあります。「まだ見ぬ機能」を想像しながらエンジン開発を優先し続けたからこそ、あのような汎用性を有するに至ったのだと思います。

「言語レイヤー」から自作した真意

――「吉里吉里」では、既存のスクリプト言語や仕組みを流用するのではなく、言語レイヤーからすべて自作するというアプローチを取りました。C++などで書かれたコアエンジンに、独自のオブジェクト指向スクリプト言語「TJS」、そしてその上で動くシナリオ記述システム「KAG」が密結合しているという特殊な構成です。なぜ、このような形に?

W.Dee:設計方針を模索する中で、結果的にあのような形に行き着いたのです。

たとえば「あらかじめエンジン側に機能を実装し、それを外部のスクリプト言語から操作する」という設計も考えられました。実際、「吉里吉里1」の最初期には、Windowsのコンポーネントである「JScript」をスクリプトエンジンとして採用していました。

しかしこの方式ではスクリプト言語とエンジン本体との間に「インターフェース」が介在するため、呼び出しやデータの受け渡しにおいてさまざまなロスが生じることに気がつきました。このオーバーヘッドを避けるため、言語とエンジンをより密接に統合する方向へと舵を切りました。

その結果、「吉里吉里1」(TJS1版)および「吉里吉里2」では、独自のスクリプト言語である「TJS」のオブジェクトシステムをインフラストラクチャーとして採用し、その上にエンジン全体を構築しています。

「TJS」のオブジェクトシステムには、メソッドの呼び出し方法、オブジェクトの寿命管理、文字列の扱いなど、基本的な実行モデルが一体として定義されています。「吉里吉里」は、この共通基盤の上に成り立っているのです。

――それにより、「ロス」を軽減できる?

W.Dee:はい。この構造では、「スクリプト言語とエンジン本体の間に本質的な境界は存在しない」ということになります。例えば、「吉里吉里」で扱われる文字列はそのまま「TJS」の文字列であり、エンジン側のクラスの多くは「TJS」から直接利用可能な形で定義されています。

つまり「スクリプト側のオブジェクト」と「エンジン側のオブジェクト」という区別はなく、同一のオブジェクトシステムの中で統一的に扱われます。その結果、データの受け渡しやメソッド呼び出しは極めてシームレスに行われ、インターフェースに起因するコストや複雑さを大きく低減できました。

――ではそれに付随して、「KAG」が生まれた経緯についてもお聞かせください。「本体」や「TJS」と、シナリオエンジン「KAG」を分けるという「関心の分離」のような構造は、どのような設計哲学から生まれたのでしょうか?

W.Dee:「KAG」は、「ゲームシステムプログラミング」と「シナリオ記述」という、異なるエンジニアリングのレイヤーを分離する、という考え方から生まれました。

多くのゲームエンジンでは、シナリオスクリプトをエンジン本体が直接解釈する構造になっています。ここでいうシナリオスクリプトとは、キャラクターのセリフや画像表示、演出などを記述するものです。例えば、

[登場人物A] セリフ
[登場人物B] セリフ

のような形式です。

このような記述は人間にとって非常に分かりやすい反面、エンジンが直接解釈する構造では柔軟性に欠けます。ゲームの仕様変更があるたびにエンジン側に手を入れる必要が生じてしまい、「エンジンに手を入れなくてもゲーム制作ができるようにする」という「吉里吉里」の設計思想に反してしまいます

一方で、以下のようにプログラム的に記述する方法も考えられます。

drawCharacter(CH_X, CH_Y, CHARA_A);
drawText(TEXT_X, TEXT_Y, "セリフ");
wait();
clear();
drawCharacter(CH_X, CH_Y, CHARA_B);
drawText(TEXT_X, TEXT_Y, "セリフ");
wait();
clear();

こちらは柔軟性が高い一方で、人間が記述するには負担が大きくなります。機械にとって扱いやすい形式が、そのまま人間にとって扱いやすいとは限りません

この両者の問題を解決するために設計したのが、「KAG」です。

「KAG」は、「TJS」で記述されたシステムスクリプトとして動作し、人間にとって書きやすいシナリオ記述を解釈し、それをエンジンに伝える役割を担います。

この構造により、エンジン本体の独立性を保ちながら、シナリオの記述性も維持することができます。

*scene_01
[cm]
; 背景画像を指定してフェードイン
[image layer=base page=fore storage="bg_classroom"]
[trans method=crossfade time=800]
[wt]
; キャラクター画像を表示
[image layer=0 page=fore storage="chara_a" visible=true]
登場人物A「ここが新しい学校か」[l][r]
登場人物B「そうだよ。今日からよろしくね」[p]
[cm]

▲「KAG3」の記法例。直感的なタグと台詞のテキストを並べることで、関数や座標を意識せずとも画像表示や文字送りを制御できる。

――シナリオ記述の手軽さと、プログラムとしての柔軟性を両立させていたわけですね。

W.Dee:そしてこの設計は、開発体制にも好影響をもたらし得ます。

具体的には、技術的なレイヤーが分かれることで、人間の役割分担においても、エンジンを開発・保守する「プログラマーの層」と、テキストを執筆する「シナリオライターの層」の間に、両者をつなぐシステムスクリプト(KAG)を担当する、「中間の層」が生まれることになります。

これにより、それぞれの専門性に応じた役割分担が可能となり、より効率的な開発体制を構築することができるのです。

――エンジン開発者とシナリオライターの他に、スクリプトや演出を担当する層も生まれるというお話からは、ノベルゲーム開発において「スクリプター」という専門職が定着していった当時の業界の流れを感じます。そうした分業がトレンドになりつつあったのを踏まえて、アーキテクチャを設計したのでしょうか?

W.Dee:いえ、「吉里吉里」がああなったのは結果的なものです。

私はあくまで趣味としてゲームやゲームエンジンを開発していた立場であり、大規模な商業ゲーム開発の現場を詳しく知っていたわけではありません。

なので、業界の動きを踏まえて「3層開発を実現しよう」と意図していたというよりは、「エンジンに手を入れなくても柔軟にゲームをつくれるようにしたい」という設計を進めたところ、結果として自然にそうした構造になった、という解釈の方が実態に近いと思います。

――ではその後、新たな「TJS2」や「吉里吉里2」や、「KAG3」を開発した理由を教えてください。

W.Dee:あれらは、単純に、「書き直し」です。ソフトウェア開発においては、構築を進めていくうちにさまざまな改善案が溜まっていき、最終的に「これは書き直した方がよいな……」と考える、というのはよくあることだと思います。あれらの開発も、そのパターンです。

「吉里吉里2」の大きな設計方針のひとつは、プラットフォーム依存性の分離です。「吉里吉里1」は比較的Windowsに強く依存した構造を持っていましたが、「吉里吉里2」ではこの点を見直し、クロスプラットフォーム展開を意識した設計へと移行しました。

具体的には、ソースコードの構造として、Windowsに依存する部分を明確に切り離して記述するようにしています。

ただ結局、当時の開発環境や周辺技術の制約もあり、「吉里吉里2」の段階で実際にクロスプラットフォーム対応を実現するには至りませんでした。

時代の流れ。エンジン自作の必要性は薄れて

――W.Deeさんはその後、「吉里吉里3」の開発に着手します。このような言い方で恐縮なのですが、こちらは完成には至らず、プロジェクトとしては実質的にストップとなりました。吉里吉里3では、何を目指していたのでしょうか?

W.Dee:「吉里吉里3」で取り組んでいたのは、動的型付けのスクリプト言語でありながら、実行速度をどこまで引き上げられるかという個人的な挑戦でした。

「吉里吉里3」に内蔵していたスクリプト言語では、変数が取り得る型を静的解析によって推論する仕組みを実装していました。たとえば、for (var i = 0; i < n; ++i) { ... }のようなコードでは、変数 i が整数以外にならないことは解析によって事前に分かります。このような場合、動的型言語で一般的に発生する「実行時の型チェック」を省略でき、オーバーヘッドを削減することが可能になります。

このように、動的な柔軟性を維持しつつ、可能な部分は静的に確定させることで性能を引き上げることを目指していました。

――言語の根本的な処理にまで踏み込んだ挑戦だったのですね。そこから一転して、開発を中止する判断に至ったのはなぜでしょうか。

W.Dee:開発を進める中で、ゲーム開発を取り巻く環境や技術的な状況が大きく変化していったからです。

時代が下るにつれ、Luaをはじめとする組み込み用途に適した言語や、他のゲームエンジンが台頭し、「エンジンから自作する」ことの必要性が相対的に低下していくのを肌で感じていました。

そのため、「吉里吉里3」の開発を途中で止める判断をしました。

――「吉里吉里1」や「2」では、軽量性と柔軟性のバランスをとる工夫に力を注ぎ、「3」では実行速度の極限を追求していました。「技術的な探求そのものが大きな開発の動機だった」と伺いましたが、自身の探求の足跡が詰まったプロジェクトを手放すことに、寂しさはなかったのでしょうか。

W.Dee:もちろん、長年関わってきたプロジェクトから距離を置くことに対する、一抹の寂しさはありました。ただ、それに強く執着しているという感覚ではありません

自分の中では、軽量性と柔軟性のバランスや、動的言語の高速化といった実験的なテーマについて、ある程度の「解」を得られた感覚があったからです。過去には「OSをつくってみたい」という関心を持っていたことすらもありましたが、「吉里吉里」の開発を通じて、言語、ランタイム、リソース管理といった広いレイヤーにまたがる実装を経験し、ある種の到達感は得られたと感じています。

技術的な挑戦としては、十分に満足しているのです。

また、「吉里吉里2」そのものが広く普及し、多くの作品制作に利用されたことについても、大きな達成感がありました。自分の中で、ひと段落はできたかと感じています。

それに「吉里吉里」シリーズの開発自体は、「吉里吉里Z」として有志の方々へと実質的に引き継がれていきました。プロジェクトとしては完全に消滅したわけではないので、強い喪失感のようなものはありません。

「吉里吉里Z」のプロジェクトには、私自身もたまに関わることがありますしね。

感慨深いのは、「プラットフォーム依存性の分離」がその後「吉里吉里Z」にも引き継がれ、完全に実現したことです。有志の手により、Windowsだけでなく、MacやLinuxへのエンジン移植がなされています。

▲macOSやLinuxをサポートする「吉里吉里SDL2」(画像は公式サイトからスクリーンショット

――「エンジンから自作する必要性」が低下した吉里吉里3以降、W.Deeさんご自身は、個人で何か大規模なソフトウェアやツールの開発をしたことはあるのでしょうか。

W.Dee:もともと関心のあった電子工作に没頭することは多々ありますが、ソフトウェア開発でいうと「吉里吉里」ほど注力したものはありません。

ツールやエンジンのようなものを自分でつくりたい、という衝動自体は時々湧き上がります。ただ現実問題、他にもやりたいことや興味のある分野は多く、大規模な開発には至っていません。

それに、現在はコンテンツ制作のためのツールやゲームエンジンそのものが非常に成熟しており、高品質なものを比較的気軽に利用できる時代です。お話したように、インターネットの普及、オープンソースソフトウェアの成熟もあって、「個人がゼロから小規模に独自エンジンを開発する」というスタイルは、以前ほど時代に適合しなくなっているのではないか、と感じています。

なので現在はツールやエンジンそのものをつくることよりも、それらを利用してコンテンツや表現をつくる側への関心の方が強くなっています。

――具体的にはどのようなものを制作したいのでしょうか?

W.Dee:整理すると、「吉里吉里」は、いわゆる「静的」な素材を用いた、2Dの「紙芝居」的な表現に強みを持つゲームエンジンでした。テキスト、画像、演出を組み合わせて体験を構築していく領域において、私はその表現力を磨いてきました。

一方で、現在の私の関心はより「動的」な方向へと移っています

具体的には、3D空間上でキャラクターを動かす表現や、生成AIを用いたコンテンツ生成の可能性に興味があります。固定された素材を組み合わせるのではなく、その場で変化し続ける表現や、それによって制作のプロセス自体がどのように変わっていくのかに関心があります。

かつてのように「エンジンそのものをつくりたい」という、同じ方向での強い欲求が残っているわけではありません。しかし「新しい技術を用いてどのような表現や体験を生み出せるのか、そして制作のプロセスがどう変化していくのかを探求する」という意味では、私の技術的な興味は当時から連続しています。

最後に補足すると、「吉里吉里」のような比較的大規模なプロジェクトを長期間継続できた背景には、個人的な技術的探求心に加えて「利用してくださる方々の存在」がありました。実際に使っていただき、フィードバックや応援をいただけることが、開発を続ける大きな支えになっていました。

この場をお借りして、吉里吉里を使用している方々、吉里吉里を使用した作品を楽しんでいる方々、吉里吉里に関わっているすべての方々に深く感謝の意を表します。

繰り返しとはなりますが、「吉里吉里2」の直接の後継としては「吉里吉里Z」があります。もしも後継プロジェクトを探している方がいたら、そちらを参照していただければと思います。

取材・執筆・編集:田村 今人

ピックアップ関連記事
levtech.jp levtech.jp levtech.jp