最初のゲームでやりがちなテキスト管理の失敗と、その直し方
いまのところ、ゲーム内のテキストはちゃんと動いています。セリフは出るし、メニューの表記も正しいし、アイテム説明も意図どおりです。開発の内側にいるかぎり、テキストの持ち方に問題があるという信号はまったく出ません。それを読んでいるのはゲームだけで、ゲームは持ち方を気にしないからです。
信号は後から、しかも必ず外から来ます。言語を足すと決めたとき、誰かにテキスト全文を渡すことになったとき、誤字の報告が来て同じ文字列を四十か所から探すことになったとき。その瞬間に、テキストの持ち方は内部の細部であることをやめ、あらゆる作業の値段を決める要素になります。
この記事は、特に高くつく失敗のカタログです。「どこに置いているか」「どうやって指し示しているか」「文字列の中に何を埋め込んでいるか」の三つに分けて並べ、最後に開発を止めずに直す手順を書きます。
いま困っていないのが問題
これらの失敗がなぜ長いあいだ見えないのかを、正確に押さえておく価値があります。それこそが、わざわざ書き出す理由だからです。個人開発者はゲーム全体を頭の中に持っています。ショップの確認メッセージと鍛冶屋の確認メッセージが同じ文の二度打ちであることも、その両方がどこにあるかも知っています。だから重複はコストになりません。コストが現れるのは、その知識が頭の外に出なければならなくなったときです。翻訳者、編集者、二人目のプログラマー、あるいは八か月後の自分が、どこに何があるか知らないままテキストを扱う場面です。
何が引き金になるかもはっきりさせておきます。最大のものは言語追加です。すべてのテキストが同時に「探せる・取り出せる・差し替えられる」状態であることを要求されるからです。ただし同じ失敗は、もっと小さな出来事でも牙をむきます。通貨の名前を変える、キャラクターの口調を変える、混乱を招くと分かったチュートリアルを直す、パブリッシャーに文字量を聞かれる。どれも、テキストが整理されていれば簡単で、されていなければ憂鬱な作業になります。
救いは、どの失敗も単体では直すのが難しくないことです。高くつくのは量がまとまったときだけで、これは「あとで英雄的に書き直す」のではなく「早めに出血を止める」ほうを選ぶ理由になります。
どこに置いているか
最初のまとまりは置き場所の問題です。どのツールからも手が届かない場所にあるテキストのことです。
- コードに直接書かれたテキスト。定番です。動作には問題ありませんが、書き出せず、数えられず、ソースごと渡さないかぎり誰にも渡せません。プレイヤーに見える行とデバッグ用のラベルを自動で見分ける確実な方法もありません
- エディタのシーンやプレハブのデータに打ち込んだテキスト。直書きより見つけにくく、たいてい厄介です。バイナリや半バイナリのプロジェクトファイルの中に隠れていて、リポジトリ全体を文字列検索しても引っかからないことがあります
- 同じ文をあちこちにコピー&ペーストしたもの。修正はすべての箇所に適用する必要があり、翻訳費用も重複して払うことになり、やがてコピー同士がずれて、同じ内容を二つの画面が別の言い回しで説明するようになります
- 画像に焼き込まれた文字。看板、ロゴ、チュートリアルの図解、ラベルが絵の一部として描かれたボタン。ツールから見ればそれはテキストではなく、どの集計にもどの書き出しにも現れません。誰かが遊んで目にするまで見えないままです
- 正本になっていないスプレッドシート。いつか誰かが作り、個人のクラウドに置かれ、手作業でプロジェクトに書き出され、以後は両側で編集されているファイル。どちらが最新か誰にも言えなくなり、最終的な答えは「どちらでもない」になります
どうやって指し示しているか
二つ目のまとまりは同一性の問題です。コードが特定の文字列をどう指名しているか。ここを間違えると、あとからテキストを安全に更新することが不可能になります。
最悪なのは識別子がまったくない状態です。原文そのものをキーにしてテキストを引くコードは、原文が一文字変わるまでは動きます。変わった瞬間に、そこに紐づいていた訳文がすべて静かに外れます。ほぼ同じくらい悪いのが、内容を名前にしたキーです。文言を編集した瞬間、その名前は嘘になります。キーは「どこに出るか」「何の役割か」を表すべきで、そうしておけば文章を書き直してもキーは無傷で残ります。
関連する二つの癖は、もっと静かに効いてきます。無関係な場所で同じ項目を使い回すのは効率的に見えます。「開く」がドアの操作表示とメニューの両方に出る、というような場合です。しかしそれが同じ語なのは自分の言語だけで、他の言語では別の語だったり、別の活用が必要だったりします。共有された項目は、そのどちらか一方にしかなれません。もう一つが自動採番のキーで、text_001 から text_400 のような並びは、途中に一行挿入したり削除したりした瞬間に、それ以降がすべて一つずれます。
# 壊れやすい: 文言や並び順に同一性が依存している
lookup("ゴールドが足りません。")
lookup("text_137")
# 壊れにくい: 文ではなく「置き場所」を表す識別子
shop.error.insufficientFunds = "ゴールドが足りません。"
door.prompt.open = "開く"
menu.file.open = "開く"文字列の中に何を埋め込んでいるか
三つ目のまとまりは文字列そのものの中身です。セリフの中に打ち込まれている、実体はレイアウトや書式やプログラムの都合であるものたちです。
最も多いのが手動の改行です。いまのテキストボックスできれいに折り返るように文の途中で改行を入れると、その改行はデータの一部になります。ボックスのサイズ、フォント、言語のどれかが変われば、改行は違う位置に落ちます。たいていは語句の途中で、どの言語でも壊れて見えますし、文節の区切りで折り返すべき日本語では実際に間違いです。折り返しは描画側に任せ、手動の改行は詩や見出しのように意図的に改行したい場所だけに使ってください。
最も被害が大きいのが、断片をつなぎ合わせて作る文です。前半の断片と数値と後半の断片を連結するコードは、どこにも一文として存在しない文を作ります。だからその文は、一文として読むことも、レビューすることも、訳すこともできません。語順も、前後の語形変化も、単数複数の扱いも言語ごとに違い、連結ではそのどれも生き残りません。プレースホルダーを一つ含んだ一本の文字列にすれば解決しますし、書く手間は連結より少ないくらいです。
残りは一つひとつは小さいものの、積み上がると効いてきます。余白代わりの行頭・行末スペースは、どこかのツールが最初にトリムした瞬間に見えないゴミになります。区切り線のつもりで並べた記号はレイアウトの偽装です。手打ちで、しかも不統一に入れられたタグや制御文字は、ファイルの半分が一方の書き方、残り半分がもう一方という状態を生みます。数値や日付を文の中に直接書式化して埋め込むと、その一行が特定の地域の表記慣習に固定されます。
開発を止めずに直す
ここから抜け出すのにゲーム制作を止める必要はありませんし、テキスト全体の整理を一気にやろうとするのは、この手の作業が途中で放棄される典型的な原因です。代わりに、次の順番で進めてください。
第一に、新しい事例を増やすのをやめます。今日以降の新規テキストについて、自分と(チームがあるなら)チームで一つだけルールを決めます。プレイヤーに見える新しい文字列は、必ずキー付きでテキストファイルに入れる。例外なし。一文字列あたりの手間はほぼゼロで、問題の総量に即座に上限がかかります。今週できることの中で、費用対効果が最も高いのはこれです。
第二に、移行を始める前に棚卸しをします。プロジェクトを検索して引用符付きの文字列を洗い出し、画面やシステム単位で一覧にします。この段階では直しません。一覧はたいてい恐れていたより短く、汚れがどこに集中しているかを教えてくれます。多くの場合、まだ何の規約もなかった初期に書いた一つか二つのシステムです。
第三に、ファイル単位ではなく画面単位で移行します。ショップのテキストを全部、次にポーズメニューのテキストを全部、という進め方なら、各ステップの後でゲームは遊べてテストもできますし、どこで中断しても動く状態で止まれます。ファイル単位だと、検証しづらい中途半端な状態がゲーム全体に残ります。
第四に、重複の統合は移行の前ではなく移行のついでにやります。文字列を移すときに双子を見つけたら、その場でまとめる。事前にすべての重複を探し出そうとするのは、退屈なわりに見返りの小さい大仕事です。
すでに開発が進んでいて、この中の一つしかやる時間がないなら、第一のものをやってください。新しいテキストがきれいで古いテキストが汚いゲームは、放っておいてもきれいな方へ近づきます。両方汚いゲームはそうなりません。
元に戻らないための習慣
ここまでの失敗は、注意が切れた瞬間にすべて戻ってきます。だから、正しいやり方のほうを楽な道にしておくのが有効です。テキストファイルはコードと同じバージョン管理に置いてください。テキストの変更が他の変更と同じ履歴に現れ、そのパッチが実際に何を変えたのかを見られるようになります。キーの命名規約はプロジェクト内のどこかに書き残してください。README の三行でも構いません。頭の中にしかない規約は、他の人がプロジェクトに触れた瞬間や、自分がしばらく離れて戻ってきた瞬間に、適用されなくなる規約です。
仮のテキストや未完成の行のために、状態を表す列か目印を用意してください。どのプロジェクトも「TODO: あとで書く」を目に見える場所に一つは残したまま出荷します。状態列があれば、それは事故ではなく、リリース前に実行できる検索条件になります。
最後に、はぐれた直書き文字列の掃除を、たまにでいいので定期的にやってください。プロジェクトを検索して引用符付きの文字列に目を通し、プレイヤーに見えそうなものを拾うのに数分しかかかりません。節目ごとにやれば、新しいはぐれ者をまだ安いうちに捕まえられます。整理されたテキストは放っておいて整理されたままにはなりませんが、維持する労力は、壊れたものを修理する労力よりはるかに小さいものです。