連載
.NET&Windows Vistaへ広がるDirectXの世界

第5回 ゲーム開発者にとってのビルド作業とは? ― Content Pipelineを使ってみる

NyaRuRu
Microsoft MVP Windows - DirectX(Jan 2004 - Dec 2006)
2006/12/06
Page1 Page2

2.インポータによるコンテンツの読み込み

 Content Pipeline全体像はXNA Team Blogの「The XNA Framework Content Pipeline」というエントリで詳しく解説されている。また、付属するヘルプ*2にも詳しく書かれているので、一度目を通しておくとよいだろう。

*2 [スタート]メニューから[すべてのプログラム]−[Microsoft XNA Game Studio Express]−[XNA Game Studio Express Documentation]をクリックしてドキュメント・エクスプローラを開き、その目次から[XNA Game Studio Express]−[Extending the XNA Framework Content Pipeline]−[Overviews]を開き、その配下のページを参照してほしい。

 ここでは、個別の解説は省略し、こんなことができるという例をいくつか示そう。この部分については、XNAゲーム開発者のみならず、Visual Studioを常用する開発者の方々にも良い刺激になるのではないかと思う。

XMLインポータの利用

 まず次のようなXMLファイルを作成し、プロジェクトに追加してみていただきたい。

<?xml version="1.0" encoding="utf-8"?>
<XnaContent xmlns:Generic="System.Collections.Generic">
  <Asset Type="Generic:Dictionary[string,int]">
    <Item>
      <Key>Orange</Key>
      <Value>10</Value>
    </Item>
    <Item>
      <Key>Apple</Key>
      <Value>7</Value>
    </Item>
  </Asset>
</XnaContent>
プロジェクトに追加するXMLファイルの内容(XnaSample.xml)

 さらに、追加したXMLファイルをソリューション・エクスプローラで選択した状態のまま、プロパティ・ウィンドウで以下のようにプロパティを設定する。

  • [ビルド アクション]:「コンテンツ」
  • [XNA Framework Content]:「True」
  • [Asset Name]:好きな名前、ここでは「Parameters」とする
  • [Content Importer]:「XML Content - XNA Framework」
  • [Content Processor]:「No Processing Required」

 最後にソース・コード(の任意のメソッド)へ次のような記述を追加する。

ContentManager content = new ContentManager(Services);
Dictionary<string, int> param =
  content.Load<Dictionary<string, int>>("Parameters");
プログラム中からテクスチャ・コンテンツにアクセスするコード例
Dictionary型と、先ほど設定したアセット名(Asset Name)を指定するだけで、XMLコンテンツにアクセスできる。なお、ContentManagerクラスのコンストラクタのパラメータに渡しているServicesはMicrosoft.Xna.Framework.GameオブジェクトのServicesプロパティである。

 このように、煩雑なロード処理を記述することなく、デシリアライズされた後の.NET型を直接得ることができる。また、XMLファイルの記述で数値に変換できないテキストが入っていた場合は、XMLインポータの段階でビルド・エラーになる。この仕組みにより、データ・ロード時の型に想定されるエラー処理の多くを、ゲーム本体から分離することが可能になるだろう。

 さて、このXMLファイルの記述形式はどのように得たのだろうか? ここで紹介したXMLファイルだが、実はIntermediateSerializerクラスのSerializeメソッドに、値設定済みのDictionaryを渡して得たものである。もし別のデータ形式を使用したければ、同様にIntermediateSerializerクラスを使用して変換できるか確かめてみてほしい。

 ユーザー定義型をシリアライズすることも可能だが、必ずしも全てのフィールドがシリアライズできるわけではなく、IntermediateSerializerが想定していない型であればそのフィールドだけ無視される。筆者が確認した範囲では、以下の型のフィールドはシリアライズ可能なようだ。また、フィールドにContentSerializer属性を指定することで、シリアライズ処理の制御が可能なようである。

CLRの標準的な型はサポートされている。
  • System.Boolean
  • System.Byte
  • System.Char
  • System.DateTime
  • System.Decimal
  • System.Double
  • System.Enum
  • System.Int16
  • System.Int32
  • System.Int64
  • System.SByte
  • System.Single
  • System.String
  • System.Type
  • System.TimeSpan
  • System.UInt16
  • System.UInt32
  • System.UInt64
以下の型は専用のシリアライズ書式を持つ。
  • Microsoft.Xna.Framework.BoundingBox
  • Microsoft.Xna.Framework.BoundingFrustum
  • Microsoft.Xna.Framework.BoundingSphere
  • Microsoft.Xna.Framework.Curve
  • Microsoft.Xna.Framework.Matrix
  • Microsoft.Xna.Framework.Plane
  • Microsoft.Xna.Framework.Point
  • Microsoft.Xna.Framework.Quaternion
  • Microsoft.Xna.Framework.Ray
  • Microsoft.Xna.Framework.Rectangle
  • Microsoft.Xna.Framework.Vector2
  • Microsoft.Xna.Framework.Vector3
  • Microsoft.Xna.Framework.Vector4
  • Microsoft.Xna.Framework.Graphics.Color
  • Microsoft.Xna.Framework.Graphics.CompiledEffect
  • Microsoft.Xna.Framework.Graphics.PackedVector 以下のベクトル型
また、上に挙げた型に対する配列と一部のGenerics型がサポートされている。
  • T[]
  • System.Nullable
  • System.Collections.Generic.ICollection<T>
  • System.Collections.Generic.Dictionary<Key, Value>
  • System.Collections.Generic.List<T>
シリアライズ可能な型のフィールド

 フィールドに使用可能な型に制限があるとはいえ、使用頻度の高い型は網羅されており、ゲームの設定ファイルなどで使用するには十分だろう。IntermediateSerializerを使用した簡単なコンソール・プロジェクトでXMLファイルのひな形を作り、後はテキスト・エディタで編集してもよいし、データ入力が増えてくれば、専用のデータ・エディタを作るのもよいだろう。後は読者の皆さんの工夫次第だ。

カスタム・インポータの作成と利用

 さて、XML形式はちょっとしたデータ入力には便利だが、そのほかのテキスト・ファイルや、標準でサポートされないバイナリ・ファイルのインポートに対応するにはどうしたらよいだろうか? 実は、XNAではベンダや開発者が独自のインポータ(カスタム・インポータ)を作成することを許している。そこで、次のような単純なコンマ区切りテキストをDictionary<string, int>型に変換するインポータを作成してみよう。

Orange, 10
Apple, 7
単純なコンマ区切りで記述されたCSVファイル(test.param)
「文字, 数字」という並びのコンマ区切りのファイルである。

 インポータの作成は、Visual C# 2005 Express Editionに限らず、好きな言語・環境で行うことができるが、ここはC#を使用して書いてみよう。

 カスタム・インポータの作成手順については、前述のヘルプにある「Developing a Custom Importer」の項を参照するとよい。基本的にはMicrosoft.Xna.Framework.Content.Pipeline名前空間で定義されているContentImporter<T>の派生クラスを作成し、Importメソッドのオーバーライドによって実装を行うという方式だ。サポートする拡張子やVisual C# Expressでの表示名はカスタム属性によって記述する。

 以下にCSVファイルの読み込みルーチン全体を示す。CSV読み込みが本記事のテーマというわけではないので、エラー・チェックやRFC 4180(=CSV仕様)への準拠は考慮していない。あくまでサンプルという形でお願いしたい。

// 「クラス ライブラリ」プロジェクトをテンプレートから選択し、
// Microsoft.Xna.Framework.Content.Pipeline.dllを参照に加える。
using System;
using System.Collections.Generic;
using System.Text;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Content.Pipeline;
using System.IO;

namespace XNASample
{
  // 拡張子.paramを対象とする
  [ContentImporter(".param", DisplayName="Parameter File Importer")]
  public class ParameterImporter : ContentImporter<Dictionary<string,int>>
  {
    private static IEnumerable<string> GetLines(string filename)
    {
      using (StreamReader sr = new StreamReader(filename))
      {
        while (true)
        {
          string line = sr.ReadLine();
          if (line != null)
            yield return line;
          else
            yield break;
        }
      }
    }

    // Importメソッドのオーバーライド
    public override Dictionary<string, int> Import(string filename, ContentImporterContext context)
    {
      Dictionary<string, int> dict = new Dictionary<string, int>();
      foreach (string line in GetLines(filename))
      {
        string[] tokens = line.Split(',');
        if (tokens.Length >= 2)
        {
          dict.Add(tokens[0], int.Parse(tokens[1]));
        }
      }
      return dict;
    }
  }
}
CSVファイルの読み込みを行うインポータのコード例

 次に、作成したインポータを使用可能にする。ヘルプ*3の「How to: Add a New Processor or Importer to XNA Game Studio Express」の項で解説されているように、設定はプロジェクトのプロパティから行う。

*3 [XNA Game Studio Express Documentation]の目次から[XNA Game Studio Express]−[Programming Guide]−[How to: Add a New Processor or Importer to XNA Game Studio Express]を開く。

 XNA Game Studio Express beta 2をインストールすると、C#プロジェクトのプロパティ左側のタブに、「Content Pipeline」という項目が追加されているはずだ。先ほど作成したDLLをここに追加する。

Content Pipelineのインポータとして利用する独自アセンブリの登録
XNA Game Studio Express beta 2がインストールされた状態でのプロジェクトのプロパティ。「Content Pipeline」の項目が追加されている。
  [Content Pipeline]タブを選択する。
  [Add]ボタンをクリックして、Content Pipelineのインポータに使用するアセンブリを追加する。

 次に、先ほどのCSVファイルをプロジェクトに追加する。名前は適当に「test.param」とでもしておこう。ソリューション・エクスプローラから、このファイルのプロパティを以下のように設定する。

  • [ビルド アクション]:「コンテンツ」
  • [XNA Framework Content]:「True」
  • [Asset Name]:好きな名前、ここでは「MyParam」とする
  • [Content Importer]:「Parameter File Importer」
  • [Content Processor]:「No Processing Required」

 ビルドを行うと自動的にエクスポータが起動され、MyParam.xnbが生成される。後は

content.Load<Dictionary<string, int>>("MyParam");

と記述すればCSVファイルの内容をDictionaryで取得できる。

 このほか、インポートされた複数のデータに対する「プロセッサ」というものも規定されており、データの結合や事前最適化といった処理が可能になっている。もちろんカスタム・プロセッサを作ることも可能だ。

 XNAは、独自のビルド・エンジンを作成する代わりに、MSBuildを拡張するという方式を選んだ。そのため、XNA Game Studio Expressのプロジェクトは、msbuildコマンドによってコマンドラインからのビルドが可能だ。このことはバッチ・ビルドなどで役に立つだろう。

 さらに、Content Pipelineを利用してデータ(テクスチャやXMLファイルなど)の前処理やロード処理の多くの部分をゲーム本体から切り離すことで、多人数のチーム開発で各チーム・メンバーに明確なロールを分け与えられるようになった。プログラミング担当者が、必ずしもコンテンツ担当者が作成したコンテンツ・データ(例えばXMLファイルの内容)を目にする必要がないという点は興味深い。

 また、カスタム・インポータ、カスタム・プロセッサとして作成した.NETアセンブリをコミュニティ間で共有すれば、それらが対応する各フォーマットのコンテンツは、その活躍の場を広げられるだろう。

 機械にとってXMLは扱いやすいファイル・フォーマットかもしれないが、人間が記述するのに適しているとはいいがたい。まさにこの点で、XMLではなく使い慣れたiniファイルを選択するという人がいるのも、個人的にはうなずける話だ。その点Content Pipelineは、ゲーム開発という分野に特化した軽量なスクリプトの存在を許し、ドメイン特化言語(DSL)を活用した従来のゲーム開発のスタイルを、自然に発展させる可能性を秘めているといえる。

 XNAのキーワードである「コミュニティ」の発展に、Content Pipelineが寄与していくことを期待したい。End of Article


 INDEX
  .NET&Windows Vistaへ広がるDirectXの世界
  第5回 ゲーム開発者にとってのビルド作業とは?― Content Pipelineを使ってみる
    1.XNA Game Studio Express beta 2とContent Pipeline
  2.インポータによるコンテンツの読み込み
 
インデックス・ページヘ  「.NET&Windows Vistaへ広がるDirectXの世界」


Insider.NET フォーラム 新着記事
  • 第2回 簡潔なコーディングのために (2017/7/26)
     ラムダ式で記述できるメンバの増加、throw式、out変数、タプルなど、C# 7には以前よりもコードを簡潔に記述できるような機能が導入されている
  • 第1回 Visual Studio Codeデバッグの基礎知識 (2017/7/21)
     Node.jsプログラムをデバッグしながら、Visual Studio Codeに統合されているデバッグ機能の基本の「キ」をマスターしよう
  • 第1回 明瞭なコーディングのために (2017/7/19)
     C# 7で追加された新機能の中から、「数値リテラル構文の改善」と「ローカル関数」を紹介する。これらは分かりやすいコードを記述するのに使える
  • Presentation Translator (2017/7/18)
     Presentation TranslatorはPowerPoint用のアドイン。プレゼンテーション時の字幕の付加や、多言語での質疑応答、スライドの翻訳を行える
@ITメールマガジン 新着情報やスタッフのコラムがメールで届きます(無料)

注目のテーマ

Insider.NET 記事ランキング

本日 月間