Game Developer's Magazineの2010年9月号から抜粋した
この記事は、Googleのゲーム開発コンサルタントであるChris Pruettが、
レプリカアイランドと呼ばれるAndroidゲームで便利なゲームプレイレーティングシステムをいかに迅速かつ簡単に実装したかについて語っています。
あなたが作成したゲームを誰かがプレイするのを見るのを経験する気持ちに勝るものはありません。 ゲームの開発プロセスでは、毎日プレイし、おそらく無意識のうちに特定のスタイルのプレイを開発します。 しかし、あなたのゲームを他の人の手に渡せば、毎日のゲーム体験なしで使用されたときにあなたの作品に何が起こるかを見る機会が得られます。
発生する各問題、アニメーションの失敗、マニュアルの不可解なテキスト、および定期的なエラーは、新人がゲームをプレイするときに非常に強い印象を与えます。 ゲームプロセスをどれだけ長く修正し、修正したミスの数に関係なく、手の込んだプレイスタイルとゲームを作成するゲームプレイへの特別な関与により、他のプレーヤーがすぐに遭遇する可能性のある問題を明確に見ることができなくなります。
そのため、ゲームプレイのテストは、優れたゲームを作成するプロセスの重要な部分です。 テストを最大限に活用するには、ゲームに合格するプロセスに関する情報を保存する必要があります。 この記事では、この問題を解決した私の経験について説明します。
小さいから
ゲーム業界で最初の一歩を踏み出し、Game Boy Advance向けのゲームを作成しました。 当時、テスト方法は非常に簡単でした。VCRに接続された特別なGame Boy Advanceデバイスを隣人に渡し、ゲームを記録してから、記録を調べました。 これにより、明らかで重大なエラーをキャッチできました。
ゲームのセクションは、その通過が男たちに強い否定的な感情を引き起こしたが、追加の研究のために受け入れられた。 プレイヤーがゲーム内の特定の場所で何度も失敗した場合、これはゲームプレイのこの部分を作り直す必要があるという明確なシグナルです。 いくつかのゲームは隣人の助けを借りて実行され、私たちはゲームを大幅に改善することができました。
現在、Google Android用のゲームを作成するコンサルタントとして働いています。 このプラットフォームの最初のゲームであるレプリカアイランドアーケードは、10年前に書いたゲームボーイのゲームと大差ありません。 しかし、何かが変わった-私はゲームを作成した会社のためにもう働いていなかった、私は一人のアーティストの助けを借りて、私は主に私の自由な時間に仕事を書いた。

今、私は当時の若いベータテスターの聴衆にアクセスできません。 そして、このアクセスであっても、ゲームの現在のターゲットオーディエンスはやや古いです。
結局のところ、電話でゲームの進行状況情報を収集する簡単な方法はありません。 唯一の方法はゲーム中に「魂の向こうに」立つことですが、これは不便であり、プレイヤーのプレイ方法に影響を与え、実験の純度を低下させます。
独立した開発者は何をすべきですか? レプリカ島の開発を完了した後、このゲームをプレイするのが面白いと保証するものではないことに気付きました。 このゲームは「真空で」開発されたため、ゲームをリリースする時が来ると確信する前に、サードパーティのゲームプレイを見る必要がありました。
私が最初に試したのは投票でした。 私は仕事をしている会社の内部サーバーにゲームを置き、同僚にプレイを依頼して印象を送ってもらうように手紙を送りました。 ゲームについての質問がある小さなフォーラムも立ち上げました。 このアプローチはうまくいきませんでした。
多くの人がゲームをダウンロードしたという事実にもかかわらず、ダウンロードした人の1パーセント未満が非常に少なく、私の質問に答えようとはしませんでした。 さらに、質問に答えた人は十分な情報を提供しませんでした。 「ゲームをプレイするのは難しい」という評価の正確な理由を理解することは困難です。 理由がゲーム内での不便な制御、レベルの不十分な設計、ゲーム内の障害物の位置、合格レベルのガイドなどです。
スコアカードに反映する
その事件の後、
クラッシュバンディクーゲーム用に
ノーティードッグが開発したゲーム収集および処理システムについて考えました。
システムは、メモリカードにゲームプロセスに関する統計を記録しました。 このデータは、ナビゲーションが困難なエリア、またはゲームキャラクターが最も頻繁に死亡したエリアを検出するために(オフラインで)収集されました。
これらの問題領域は作り直され、この情報はゲームの複雑さを動的に調整するシステムにも使用されました。
私のシステムを作成する上で私を導いた興味深い原則の1つは、Naughty Dogのアイデアでした。 彼らの究極の目標は、プレイヤーが何らかの段階で立ち往生し、ゲームを続行できなかった瞬間を排除することでした。
私はこのアイデアが好きでしたが、電話で遊ぶことがどれほど実現可能か理解できませんでした。 予算の大きいゲームの統計を記録することで、現在の状況を少し理解してもらいました。 そして、多くの企業がプレイヤーの活動に関する情報を収集するメカニズムを使用していることを学びました。
何人かの人々は、大量の情報を収集しているにもかかわらず、研究中のゲームで何を変更する必要があるかを認識して理解するのに便利な形式でこのデータを処理および提示するのが難しいと言います。
一方、一部のスタジオには、プレイヤーのレベルの動きを再現し、プレイヤーが好む武器、敗北するのがより困難な対戦相手、特定の場合にはっきりと見えるマップの部分に関する統計を生成できるツールがあります。
プレーヤーの一連のインジケーターの形成は幅広い種類のゲームに適用できるようですが、これは、収集されたデータを処理するためのツールを構築するために多大なリソースを投資する大企業にのみ正当化されます。
このタイプのシステムを最も効果的に使用する方法の例は、Georg ZoellerがBioWareで使用する
素晴らしいテレメトリシステムについての講演で見ることができます。
ゲームプレイに関するデータの収集はタスクの簡単な部分であることが判明しましたが、ゲームの作成者に明確で有用な画像を提供するようにこのデータを解釈することははるかに複雑です。
ツールボックスをできる限りシンプルにしようとしたので、がっかりさせられました。 しかし、それでもいくつかの重要な指標を試すことにしました。
私のAndroidフォンにはメモリカードがありませんでしたが、インターネットに常時接続されていました。 おそらく、ゲーム内のいくつかの重要なイベントをキャプチャし、それらをサーバーに送信して、結果を取得できると考えました。 私の目標は、システムを可能な限りシンプルに保ちながら、彼らが私のゲームをどのようにプレイするかについて可能な限り理解することでした。
基本システム
私が書いたシステムは、ゲームプロセス中にプレーヤーのアクションに関するデータを収集してサーバーに送信する実行スレッド、サーバー自体、収集したデータを処理するツールの3つの部分で構成されていました。
サーバー-これはもちろん大声で言われます。 私のサーバーは、HTTPを介してGETリクエストをチェックし、結果をMySQLデータベースに書き込む30行のPHPスクリプトで表されました。 GETリクエストの構造も非常にシンプルでした。 これは、イベントの名前、座標、コードバージョン、セッションID、およびタイムスタンプです。
これらのデータは、受信した形式で直接データベースに入力されました。 サーバーで特別なページが開かれたときに、現在のデータ処理もPHPで実行されました。 長期的にはあまり良い選択ではありません。これについては以下で説明します。
ゲームキャラクターの死亡とレベルの完了という2つのイベントを登録することから始めました。 ゲームキャラクターが死亡するか、プレイヤーがレベルを完了するたびに、ゲームは対応するイベントをサーバーに送信しました。 このデータから、ゲームプレイのかなり詳細なアイデアを形成することができました。
どのレベルを通過するのに最も時間がかかるか、どのレベルでプレイヤーが最も頻繁に死ぬか、どのレベルが速すぎるかを確認することができました。 これらのデータをプレーヤー別にグループ化して、すべてのプレーヤーの何パーセントがどのレベルで死亡するか、各プレーヤーの平均故障率を見ました。
このイベントまたはそのイベントの座標を分析すると、どの場合にゲームキャラクターが敵の行動で死亡し、どのケースでピットに落ちたのかがわかります。 手始めに、私の簡単なスコアカードはかなり詳細でした。
地図上の失敗を明るい赤でマークする
ベースシステムが機能し始めたらすぐに、ベータテスター向けの更新プログラムをリリースし、受信データの監視を開始しました。 非常に迅速に、繰り返し発生する状況が特定されました。
いくつかのレベルでは、プレイヤーのほぼ100%が少なくとも1回は失敗しましたが、他のレベルでは、プレイヤーは数時間動けなくなりました。 このデータを分析することで、どのレベルを改善する必要があるかが明確にわかりました。
しかし、問題レベルを定義するだけでは十分ではありません。 特定のレベルで問題が発生した理由がわからない場合がありました。
そして、私は一歩前進しました。 同じデータを使用して、ゲームキャラクターの死の場所をレベルマップに示すツールを作成しました。 そして、ゲームキャラクターがどこで死んだのか、どこで死ななかったのかを正確に見ることができました。
システムの最初の実行では、ゲームキャラクターが死亡したレベルの小さなポイントのみが示されました。 しかし、プレイヤーの数が増えると、ヒートマップ(ヒートマップ)のようなものが得られるようになりました。これは、レベルマップ上のプレイヤーの死の場所を示し、それははるかにわかりやすいものでした。 ヒートマップの作成に関する章を以下に示します。

レプリカ島のゲームキャラクターの死亡データに基づいて生成されたヒートマップ
ゲームデザインの視覚的なデザインの誤算
高レベルのゲーム統計とゲームキャラクターの死の場所のレベルでの指定の組み合わせは、ゲームデザインの欠点に光を当てます。 たとえば、最初のモンスターと出会ったときに多くのプレイヤーが死亡したことに気付きました。 これは、モンスターが非常に強かったからではありません。 状況を詳細に調査した結果、天井が低いため、攻撃の主な方法-上からジャンプ-を実装するのが難しい場所にモンスターが出現したという結論に達しました。
また、ゲーム自体の複雑さを動的に調整するための私のシンプルなシステムには修正が必要であることに気付きました。 このシステムは、この事実を公表することなく、ゲームキャラクターの寿命を延ばし、一定回数連続して死亡した後の飛行のエネルギーを増やしました。 統計を調べて、私は彼女がこれよりずっと早くやるべきだったことに気付きました。
また、私のレベルの構造は大きく変化しました。 私は彼らの通過に費やされた長い時間で十分な数のレベルを持っていましたが、少数の死でした。 そして、そのレベルでプレイヤーが単に迷子になったことに気付きました。 通過の順序をより理解しやすくするために、これらのレベルを再編集しました。 いくつかのケースでは、レベルをゼロから完全に再編集しました。
しかし、私が遭遇した最大の問題はピットでした。 レプリカ島はプラットフォーマーであり、ご想像のとおり、プレイヤーはピットを大量にジャンプする必要があります。
パイプに
住んでいる 有袋類や
配管工とは異なり、私のゲームキャラクターは主な移動方法として飛行がありました。
ゲームパッドを必要としないゲームキャラクターの制御システムが必要でした。 ゲームの主人公以来、緑色のAndroidロボットは、足でロケットエンジンを使用して飛行していました。 動きの基本的なモデルは、ジャンプの前にまだ表面にインパルスを取得し、このインパルスを使用して、エンジンの助けを借りて正しい方向に飛行することでした。 エンジンはかなり早くエネルギーを消費しましたが、着陸時にエネルギーが更新されました。 そして、アイデアは、プレーヤーがジャンプをしてから、慎重にエネルギーを消費し、適切な場所に到達するか、敵を正確にジャンプして攻撃するというものでした。
これはすべて良いことでしたが、ベータテスターから来たゲームキャラクターの死の統計を見ると、ほとんどの場合、彼らは底なしの穴で死んだことがわかりました。 最小のピットでも多くのプレイヤーが失敗しました。 そして、ゲームの過程でピットの死者数が減らなかったという事実をもっと心配していました。 プレイヤーは、ゲーム中に障害を克服するスキルを向上しませんでした。
その後、ゲームのデザインとレベルのデザインを慎重に研究し、いくつかの理論を形成しました。 私の理解では、主な問題は、ジャンプ中にプレーヤーに穴が見えないことでした。 最終的に、ジャンプ中に、着陸地点に単純な穴またはトラップ穴が存在することは目立ちませんでした。 私のレベルは非常に高いことが多いため、どのピットが地下レベルに至り、どれがひどい死に至ったのかを判断することは困難です。
2番目の重要な問題は、ゲームの主人公を示すカメラの動作がうまく機能していないことでした。 主人公が高いジャンプをしたとき、地球の表面は見えなくなりました。 その結果、適切な着陸場所を決定することは困難でした。
スーパーマリオブラザーズのような有名なプラットフォーマーはほとんど垂直スクロールを実行しません。 マリオには、カメラが上下に移動できるタイミングを決定する一連の複雑なルールがあります。 ただし、私のゲームでは、飛行機構の存在により、すべての場合で垂直スクロールが許可されました。 多数の修正を行った後、プレーヤー自身が表示領域の境界に近づかない限り、カメラの動作がよりスマートになり、上に移動しなくなりました。
これらすべての変更の後、ベータテスター用に別の更新プログラムをリリースし、その結果を以前のバージョンのゲームから取得した結果と比較しました。 変更は非常に有望でした。 死者の総数は減少し、レベルを通過する時間は基本的に通常に戻りました。 そして、ピットに落ちることによる死亡率は著しく減少しました。
ゲームの最終バージョンをリリースする準備ができるまで、テストプロセスを数回繰り返しました。 スコアカードを使用すると、特定の変更がベータテスターによるゲームの進行にどのように影響するかを簡単に判断できました。
ゲームリリース
そのため、いくつかのテストを実行した後、グラフに
標準の正規分布が表示され始めました。 ゲームをリリースする時が来たので、スコアカードをゲームに組み込んだままにすることにしました。 新しいユーザーから受け取る情報が、ベータテスターグループから受け取る情報と異なるのではないかと考えていました。 見つける方法は1つしかありませんでした。
もちろん、ゲームがサーバーにデータを送信するたびに、最善の解決策はユーザーに通知することです。
最新の変更に関する情報とともに表示されるウェルカムメッセージでのゲームのリリース後の最初の時間は、ゲームがその後ゲームを改善するために、ゲームプロセスに関する匿名の個人化されていない情報をサーバーに送信するという情報でした。 そして、これを望まないプレイヤーは、メニューからこのシステムをオフにすることができます。
このアプローチは最善の解決策のように思えました。 ゲームコードが開いていて、送信されたデータパケットの構造を誰でも調査できるという事実にもかかわらず(送信されたデータが特定の人やデバイスと比較できないことを事前に確認しました)、プレイヤーに「いいえ、ありがとう」と言う機会を与えました。
Androidマーケットからのインストール数とスコアカード内のユニークプレイヤーの数を比較すると、ゲームプロセスに関するデータをサーバーに転送することを拒否したゲームユーザーは20%未満であるという結論に達しました。
当然の結果として、分析のために膨大な量のデータを受け取りました-私のゲームのユーザーによって生成されたイベントに関する1ギガバイトの情報について、1400万以上の情報ポイントがありました。 執筆時点では、その数は120万人でした。
実際、この量の情報が私のシステムをかなり急速に破壊しました。 レプリカ島のウェブサイト
に投稿した最初の13,000人のプレイヤーから収集した統計情報があります。 しかし、ゲームのリリース後、ほとんどの分析ツールが機能しなくなりました。
幸いなことに、最初の13,000人のプレイヤーは、ベータテスターの小さなグループと非常によく似た統計情報を提供しました。これは、おそらくテストグループで得られた結果が大きなグループに適用できることを示唆していますプレーヤー。
なんとかして、この計画はうまくいった
レプリカ島のイベントアカウンティングシステムに非常に満足しました。 ほとんど費用がかからず(イベントをキャプチャするサーバー側はXbox Liveアカウントよりも費用がかかりません)、2種類のイベントのみを使用して、プレイヤーがゲーム内の場所を迅速かつ効率的に判断できました問題に遭遇しました。
さらに、この情報の収集を開始するとすぐに、ゲームのさまざまなバージョンから受け取ったシステムの概要データを比較する機会を得ました。これにより、ゲームに加えた変更がプラスの効果をもたらすことを確認する機会が与えられました。
PHPとMySQLを使用してサーバー側を実装することは、優れたソリューションでした。 イベントのキャプチャは非常に簡単なため、どの言語でも実装できると確信しています。 PHPでは、サーバー側全体の実装に30分もかかりませんでした。
実行の別のスレッドを使用してイベントをサーバーに送信することも良い方法でした。 HTTP要求の送信中にユーザーインターフェイスがブロックされることは望ましくありません。また、サーバーとの通信プロセスを別の実行スレッドに入れます。
最初は、このためにデバイスでのゲームの速度が低下することを恐れていましたが、結局のところ、心配する理由はありませんでした。 余分な負荷は非常に小さいため、ゲームのプロファイリング中に気付くことすらできませんでした。
結局のところ、システム全体を可能な限りシンプルに保つことは良い解決策でした。 ゲームで記録できるさまざまなイベントオプションを検討しました。 しかし、ゲームの主人公の死の瞬間を追跡し、レベルを完了すると、分析に十分な情報が提供されました。
情報量が多いと、データ処理メカニズムが複雑になり、結果として明確な画像を取得するのが難しくなります。 インジケーターを収集および処理するための自動システムを作成した経験がありますので、将来サーバーに送信するデータ量を増やすことにします。 しかし、私の意見では、シンプルなシステムから始めることは間違いなく良い動きでした。

埋めたバンプ
イベント登録システムのすべてがうまく機能したわけではありません。 期待した結果が得られなかった、または単に時間の無駄だったいくつかの決定をしました。
バックエンドにPHPを使用するという決定は、良い動きでした。 ただし、PHPを使用して受信データを処理するのは誤りでした。 私のアイデアは、Webインターフェースを介してすべてを実行することでした。 PHPとJavaScriptでレベルエディターを作成しました。
ただし、処理するデータ量が大幅に増加すると、PHPの速度が低下し始めました。 PHPは、メモリとコンピューティングリソースの点で非常に限られた環境で動作しました。 そして、私はすぐにこれらの制限にぶつかりました。 20,000人のプレイヤーから情報を受信し始めるとすぐに、私のPHPツールのほとんどは機能しなくなりました。
特に、PHPでの画像処理には問題があることが判明しました。 ヒートマップ生成メカニズム全体をPHPで実装しましたが、サーバーで実行する代わりにローカルで実行するものを作成する必要がありました。
PHP GDインターフェースで多くのエラーに遭遇し(アルファチャネルを使用した画像の形成は単に機能しませんでした)、さらに処理するためにレベル画像のサイズを単純に縮小することにしました。
この記事では、Pythonと
ImageMagickを使用してこのツールを書き直しました。
そして結果は印象的でした。 この実装のコードは、
Game Developerマガジンの公式Webサイトからダウンロードできます。
その結果、これらのデータはゲームキャラクターがいつ死亡し、レベルを完了するのにどれだけの時間が必要かを教えてくれましたが、プレイヤーがプレイをやめたときに、ゲームのメインキャラクターの死に関係のない瞬間を判断するための情報を提供しませんでしたゲーム(ゲームシェルフの瞬間)。
私は、スコアカードでは発見できなかったレベル設計の重要な誤算を含むゲームをリリースしたという結論に達しました。 最も極端な状況では、プレイヤーは解決方法を理解していないタスクに直面し、レベルの通過を完了することなく、単にプレイを終了しました。
これは、レベルの完了イベントを修正する条件が発生しなかったため、私のシステムに表示されたことはありません。 このことを知ったのは、プレイヤーがゲームを渡すときに同じ場所で立ち往生しているという苦情を私に送り始めたときだけでした。
私の自動システムは非常に便利でしたが、ゲームプレイの全体像を見せませんでした。 私の場合、インジケーターはレベルで問題のある領域を識別するのに適していますが、ゲームの要素が相互作用する順序に関連する計算ミスを判断するのには効果がありません。
未来
次のゲームでは、同様の自動システムを再び使用します。 ゲームキャラクターの死の座標を修正することに加えて、私は彼を追い抜いた死の形に基づいてイベントを追加するかもしれません。 正確にどこで発生したかだけでなく、ゲームキャラクターがどのように死亡したかを正確に知ることが役立つ場合があります。
また、ゲームによっては、ゲームキャラクターの動きの履歴を、あるレベルまたは別のレベルで死ぬ前にサーバーに送信すると便利な場合があります。
ただし、このようなシステムの重要なポイントはそのシンプルさです。 信頼できるツールが処理のために作成されるまで、データ収集は意味がありません。
次のゲームでは、データをサーバーに送信してデータベースに保存する基本的なシステムをそのままにしておきます。 そして、受信したデータを処理するための最適なツールの作成に焦点を当てます。
また、プレイヤーが取得したサマリーデータを使用して、動的なゲームの複雑さ制御システムを構成する方法にも興味があります。
ゲームがサーバーからサマリーデータを受信できる場合、1人のプレイヤーのゲームの結果だけでなく、他の何百万人のプレイヤーの平均データにも基づいて、ゲームプレイが変更されます。 私の意見では、これにより新しい興味深い機会が開かれます。
プレーヤーのパフォーマンスを収集して分析することは、カスタムテストの理想的な代替手段ではありません。 しかし、それらは非常に有用な平均化された画像を提供します。 また、スコアカードを使用すると、個々のベータテスターで可能なよりも多くのプレーヤーグループでゲームをテストできるため、システムは長期的にゲームの詳細を示します。
スコアカードから得られた利点は、レプリカアイランドでのスコアカードのコストを上回りました。 クライアントとサーバーの部分のシンプルさを保ちながら、ゲームレベルの設計とプレイヤーの習慣に関する多くの有用な情報を受け取りました。その結果、ゲームは良くなっただけです。
残念なことは、以前のゲームではそのようなシステムを実装していなかったことです。 どのプラットフォームのどのジャンルのほぼすべてのゲームにも適用できるようです。
ヒートマップを生成する方法
ヒートマップの生成はそれほど複雑ではありませんが、正確な指示を見つけるのに手間がかかりました。
ここで
説明した方法と同様の方法を使用しました。

主なアクションは次のとおりです。
- 円の画像をグレースケールで生成します。その色は、放射状のグラデーションに沿って、中心の黒から端で透明に変わります。これは、イベントが発生したポイントを表示する画像です。
- 色のグラデーションを持つ長方形の画像を生成します。画像の下部を白または赤、またはヒートマップ上の「最もホットな」スポットの指定として選択した色にします。画像の上部は黒で、間にいくつかの色があります。この画像は、後で統計データに関するグラフィカルなレポートを生成するための「辞書」として使用されます。
- 過去のイベントの座標のリストを生成します。
- , . «» .
- イベントのリスト内の一意の場所ごとに、イベントの座標に従って円の画像を描画します。 次の式で計算された不透明度係数で画像を描画します。
( )/( "") * 100%
乗算転送モード(src * dst)を使用して、描画された円の点を互いに混合します。
結果の画像を透明なキャンバスにオーバーレイします。
プロセスが完了すると、さまざまな強度の黒の暗い斑点の多い画像が得られます。 これは、次のステップで処理される中間イメージです。
- 前の手順で取得した画像を取得し、それに色を追加します。 各ポイントの透明度レベル(アルファ)を取得し、それに基づいて、処理されたポイントの色を計算するために、手順2で作成した「色辞書」のY座標を計算します。
- 結果の画像を取得し、ゲームレベルの画像の上に重ねます。 イベントの場所は色付きの領域として表示されます。色の強度が増加すると、イベントがより多く発生した領域が示されます。
これらのすべての手順を実行するときは、チャネルごとに8ビットの範囲で色空間を維持するようにしてください(特に、手順5で不透明度を計算する場合)。 または、イメージング用に浮動小数点データをサポートする形式の使用を検討してください。
正確なエラー(正確なバグ)は簡単に特定できます。これは、多数のイベントで顕著になり、全体像に対する1つのイベントの寄与が1%未満になります。
ImageMagickなどのツールは、この問題の解決に役立ちます。