Content Pipeline その2 その流れ

コンテントの流れ 前回は、コンテントマネージメントに関する問題の複雑さについて書きました。今回から、その問題を解決する為に設計されたXNAのコンテント・パイプラインの仕組みを紹介していきます。下図は、XNAのコンテント・パイプラインの概念図です。     パイプラインの名から判るように、コンテントが上から下へ流れるように処理され、アセットとしてできあがったものをゲームで使うようになっています。コンテントを川の水、アセットを水道水として考えると、コンテント・パイプラインは、浄水場と配水管に例えることができます。 コンテント・パイプラインは2つのプロセスに分けることができ、ビルド時にコンテントをアセットに変換するオフライン・プロセス、ゲーム実行時にアセットを読み込むオンライン・プロセスとなります。この2つのプロセスは設計目的も明確に分かれていて、オフライン・プロセスではメモリ使用量や実行速度よりも、簡単にコンテントを加工できるように設計されているのに対して、オフライン・プロセスではアセットに対する処理のし易さよりも、メモリ使用量や実行速度重視で設計されています。   オフライン・プロセス オフライン・プロセスの中心となるのは、データを加工しやすい構造で保持するコンテント(Content)です。XNAフレームワークには標準でMeshContent、AnimationContent、TextureContent等のコンテントがあります。コンテントは、その型に対応するTypeWriterとTypeReaderを記述することによって、どんな型でもコンテントとして扱うことができます。   次にコンテントファイルからコンテントにデータを読み込む役割をするのがインポーター(Importer)です。XNAフレームワークには標準でFbxImporter、XImporter、TextureImporter等のインポーターがあります。3Dモデルファイルなどからのインポートの場合、NodeContentやMeshContentに変換する為の処理が入るので、単なるファイルからの読み込みよりも複雑な処理になりますが、前述のようにNodeContentやMeshContent自体がデータ加工がしやすいように設計されているのに加え、MeshHelperやMeshBuilderといった補助クラスを使うことで、独自インポーター製作の労力を軽減できます。   そして、コンテントに対して様々な処理をしたり、ゲームに最適なデータフォーマット変換するのがプロセッサ(Processor)です。XNAフレームワークには標準でModelProcessor、MaterialProcessor、TextureProcessor等のプロセッサがあります。例えばModelProcessorはNodeContentからModelContentに変換するプロセッサで、実行時のパフォーマンス効率が良いようにマテリアル順に並び替えたり、頂点キャッシャの効率化のための頂点データの並び替えや、Windows/Xbox360のプラットフォームの違いによるデータ変換等が行われます。基本的にプロセッサはコンテントからコンテントへの加工をするのですが、XNAフレームワークでは処理前と処理後のコンテントを区別する為にプロセッサ処理後のコンテントはMicrosoft.Xna.Framework.Content.Pipeline.Processors内で宣言されています。   最後に、コンテント、インポーター、そしてプロセッサの管理をするのが、コンテント・コンパイラ(ContentCompiler)です。主な仕事は、指定されたアセットを生成する為に指定されたインポーターとプロセッサを呼び、最後にTypeWriterを使ってXNBファイルへの書き出しをすることです。その他にも、時間節約の為にビルドや配置(Deploy)を必要なアセットのみだけに対して行うなどの処理もします。   オンライン・プロセス オフライン・プロセスで殆どの処理がすでに終わっているので、オンライン・プロセスではコンテント・マネージャー(ContentManager)を使い、TypeReaderを介してXNBファイルからのアセットを読み込むだけと、非常に単純なものになっています。ContentManagerは読み込んだアセットを保持しているので、既に読み込まれているアセットを読み込もうとした場合は、保持されているアセットを返すキャッシャ機能があります。読み込んだアセットはContentManager.Unloadメソッドで一括して消去することができるので、システム用、ステージ用といった複数のContentManagerのインスタンスを持つことでアセットのライフサイクルの管理をすることができます。   そしてカスタマイズへ 以上がコンテント・パイプラインの大まかな仕組みです。インポーターやプロセッサは独自のものが作れるように設計されているので、FBXやXファイル以外のモデルデータを読み込むインポーター、単純なパラメーターからフラクタルを使ってテクスチャや地形を生成するインポーター、ModelContentから当たり判定データに変換したりするプロセッサを作ったりということができます。 最大の利点はインポーターやプロセッサはモジュール化しやすいので、作ったものを簡単に皆に使ってもらえる、使えるということではないでしょうか? 次からは、実際にインポーターや、プロセッサの作り方の紹介をしていきます。

2

Content Pipeline その1 その問題点

ゲームにはコンテントが必要 ゲーム製作で欠かせない要素として、プログラミングの他にコンテント作成があります。コンテントとは、3Dモデル、テクスチャ、フォント、サウンド、ゲームのパラメーターといったものの総称です。このコンテントを作るツール、例えばテクスチャならフォトショップ、3DモデルならMayaなどといったツールをDCC(Digital Content Creation)ツールと呼びます。DCCツールというと、高いお金を払って買うものと思われがちですが、自分で撮ったお気に入りの写真をゲームで使えば、その写真を撮るのに使ったデジカメはある意味DCCツールといえる訳です。さらに言えば、ゲームで使われるメッセージなどをWindowsに付いてくるメモ帳を使えば、それも立派なDCCツールとなるわけです。   コンテントは必要だけど管理が面倒 次に、作ったコンテントをゲームで実際に使います。DirectXやMDXではテクスチャやXファイルをファイルから直接読み込むことができ、XNAでもWindows版ではテクスチャをファイルから読み込むことができますが、モデルに関してはXファイルを直接読み込むことはできません。今までDirectX等でゲームを作っていた人の中には「なんでTexture.LoadFromFileメソッドがXbox360上で使えないの?」といった疑問を抱く人もいると思います。XNAでコンテントファイルから直接読み込めないようになっているのには以下の理由があります。   拡張性がない コンテントファイルにはゲームに不必要なデータが含まれている 読み込み時に余分なリソースを必要とする コンテント・マネージメント   1つ目の拡張性については、ファイルからの読み込みの場合、決められたファイルフォーマットから、決められたデータフォーマットへの読み込みしかできません。ですから、サポートされていないファイルフォーマットをゲーム上で使うには、ファイルフォーマット変換するツールを作る必要があります。ゲーム製作ではDCCファイルにゲーム独自のメタデータを追加することが良くあるので、仮にフォーマット変換ツールを作ったとしても、このメタデータが使えない場合もあります。   2つ目については、コンテントファイルフォーマットはコンテントを作りやすいように設計されていて、画像ファイルではEXIF、3Dモデルファイルなどではツールの環境データなどのゲームに不必要なデータが含まれていたりします。   3つ目は、2つ目と同じように、ゲームで使うデータフォーマットはコンテントファイルフォーマットと違って、各プラットフォームで最適に動作するように設計されています。ですから、ファイル読み込み時にゲームに適したデータフォーマットへの変換が発生するので、その処理に時間が掛かるのと、変換用のメモリを必要とします。また、ゲーム用のデータフォーマットはプラットフォームの違いによっても変わってきます(例えばWindowsとXbox360ではエンディアンの違いなど)。これらの変換処理が複雑化するほど、読み込み時間も長くなる、つまり、ロード時間が長くなるのでゲームを快適に遊べなくなってしまいます。   そして4つ目は、たとえファイルからデータを直接読めたとしても、開発環境を含めたコンテント・マネージメントのしくみ無しでは快適なゲーム開発環境が実現できないということです。例えば、Xbox360上でゲームを作っている場合、必要なファイルはネットワークを介してファイル転送する必要がありますが、コンテント・マネージメントがない場合、ファイル転送を手作業でしなければいけません。手作業だとファイルを転送し忘れたり、転送場所を間違ったりと、人為的ミスが発生してしまいます。また、大量のコンテントファイルがある場合、全てのファイルを転送したりすると時間の無駄にもなります。   以上のように、ゲームでコンテントを使用するには様々な問題があり、これらの問題を解決し、XNAの目標であるゲーム開発者がゲーム開発に集中できる環境の提供を実現するために設計されたのがコンテント・パイプラインです。 次回からは、数回に渡ってコンテント・パイプラインの仕組みを紹介していきます。

0

ゲームプログラミング開始

前回は、XNA Game Studio Expressでゲームプロジェクトを新規作成したときに生成されるテンプレートコードの中身の説明をしました。今回は、ゲームプログラムの基本となる以下のものを実装、つまりコーディングをします。 コンテントの読み込み SpriteBatchを使ったスプライト表示 コントローラーによる移動 今回は、簡単な説明に留めますが、次回からはそれぞれについて詳しく説明していきます。   コンテントの読み込み XNAにはビットマップ、3Dモデル、オーディオといったゲームを作る上で必要なコンテントを簡単に、効率よく使うためのコンテント・パイプラインというものがあります。全てのコンテントは、プロジェクトをビルドした時に、コンテント・パイプラインによって処理され、Windows/Xbox360上で効率良く使えるデータ形式に変換されるようになっています。また、それぞれのゲームで独自形式のフォーマットを取り扱えるようにカスタマイズできる機能を持っています。 今回使うコンテントは、左の飛行機の絵が一枚だけです。XNAでは全ての画像データはテクスチャとして変換されます。コンテントのプロジェクトへの追加はソートコードの追加と同じで、ソリューション エクスプローラからコンテントを追加するプロジェクトを右クリックしてメニューを開き、その中の追加/既存の項目を選びます。 ダイアログボックスが開いたら、ファイルの種類をContent Pipeline Filesにしてから追加したいコンテントを選びます。 GSE 1.0では以下のファイルフォーマット形式がサポートされています。 3Dモデル 2D画像 マテリアル オーディオ .FBX.X .DDS .BMP.JPG .PNG.TGA .FX .XAP(XACT) プロジェクトディレクトリ直下に直接コンテントを追加してもいいのですが、コンテントとコードの区別がつくようにプロジェクトディレクトリの下にContentというディレクトリを作っておくと便利です。また、この場合、ContentManagerの初期化の時(Initializeメソッド内)にコンテントのルートディレクトリを指定しておくと、コンテントの読み込みの時に”Content/アセット名”と書かずに済みます。 // コンテントのルートディレクトリを”Content”に設定する content = new ContentManager(Services, “Content”); 実際のコンテントの読み込みをする為には以下のようなコードをLoadGraphicsContentメソッド内に書きます。 // 飛行機用のテクスチャを読み込む airPlaneTexture = content.Load<Texture2D>(“air-plane”); ContentManagerクラスにはLoad<T>という、ジェネリクスメソッドがあり、どのような型のコンテントでも同じようにして読み込むことができます。.Net 2.0ならではの機能であるジェネリクスを使うことによって、今までのようにLoadTexture2D、LoadMeshFromFileといった、長い関数名を覚える必要もなく簡単にコンテントを読み込むことができます。   スプライトの描画 XNAでは簡単にテクスチャイメージを描画する為のSpriteBatchというクラスがあります。なぜ単にSpriteではなく、SpriteBatchという名前になっているかというと、このクラスは複数のスプライトをまとめて処理(バッチ処理)する機能をもっているからです。詳細については別の投稿で説明しますが、簡単に言うとWindows/Xbox360の違いを気にせずに、高パフォーマンスを実現しながらも、簡単に使える便利なものといった感じです。 // SpriteBatchに描画開始を伝える spriteBatch.Begin(); // 飛行機のテクスチャを指定した座標に表示する spriteBatch.Draw(airPlaneTexture, airPlanePos, Color.White); //…

2