3

JPEG / PNGを受け入れ、Texture2Dコンテンツを含むXNBファイルを出力するXNAゲーム用のゲームエディターを作成しています。

私は自分のカスタムなどのカスタムシリアライザーを持っており、Reflectionなどを使用してContentCompilerを呼び出すことにすべてを掘り下げて、実際の汚い部分に取り掛かり、実際にその部分を自分のフォーマットで機能させることができます。ただし、XNAがコンパイル(プロジェクトのビルド時にVisual Studioで)およびロード(最もよく使用されるContent.Loadメソッドを使用するゲームで)する方法を知っている通常のTexture2D形式にシリアル化する必要があります。自分のイメージを作成したくありません。このためのファイル形式は明らかです。Texture2Dをコンパイルしようとすると、エラーは発生せず、XNBファイルが作成されますが、ファイルの内容は画像データではなく、わずか3〜4 KBのオーバーヘッドです(これは私がTexture2Dオブジェクトの他の非イメージプロパティだと思います)。

コンパイルに使用するコードは次のとおりです。

    protected void InitializeWriter()
    {
        Type compilerType = typeof(ContentCompiler);
        cc = compilerType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0].Invoke(null) as ContentCompiler;
        compileMethod = compilerType.GetMethod("Compile", BindingFlags.NonPublic | BindingFlags.Instance);
    }

    internal void Write(string objectName, string path, object objectToWrite) 
    {
        if (basePath == null)
        {
            throw new InvalidOperationException("The base path to write has not been set.");
        }
        if (cc == null) { InitializeWriter(); }
        string fullPath = Path.Combine(basePath, path, objectName + ".xnb");
        using (FileStream fs = File.Create(fullPath))
        {
            compileMethod.Invoke(cc, new object[]{
            fs, objectToWrite, TargetPlatform.Windows, GraphicsProfile.Reach, false/*true*/, fullPath, fullPath
        });
        }
    }

私は自分のコンテンツプロセッサを持っており、このコードはそれらと完璧に連携します。これは、ContentCompilerのCompileメソッドを呼び出すだけですが、Reflectionを使用します(内部クラスであるため)。

Texture2Dがシリアル化される理由はわかりませんが、実際のビットマップデータはありません。

編集 申し訳ありませんが、Texture2Dをコンパイルしません(GraphicsDeviceの循環参照について文句を言います)。Bitmapオブジェクトをコンパイルしようとすると、エラーなしでコンパイルされますが、実際のビットマップデータはシリアル化されません)

4

1 に答える 1

1

さて、いくつかの掘り下げと何時間もの調査の後、私は自分の問題を解決しました。

これが何をすべきかです:

Texture2Dをシリアル化してロードし直すことはできません。ロードは明らかに問題なく実行されますが(2D XNAゲームではコンテンツマネージャーを使用してTexture2Dをロードするため)、ゲームからロードするために保存することはできません。この問題をさらに調査した結果、Texture2Dにシリアル化すると思われるTexture2DContentクラス(グラフィックスパイプライン内)が見つかりました(これは完全に正しいことがわかりました)。

そのため、Texture2DContentクラスの新しいインスタンスを接続しましたが、そのデータをビットマップに設定する方法が見つかりませんでした。すべてのDLLと基本/派生クラスを検索しましたが、方法はありません。次に、importメソッドを持つTextureImporterクラスを実現しました。ファイル名とContentImporterContextが必要です。これは、他の深層労働者階級のコンストラクターも含む複雑なクラスであり、正しく初期化できないことを知っていました。そこで、インポートメソッドにパラメータとしてnullを渡そうとし、コードにステップインしてNullPointerExceptionを確認しましたが、奇妙なことに、それは機能し、ファイルを出力しました。XNBを確認したところ、有効なテクスチャでした。これが私のコードです:

    TextureImporter importer = new TextureImporter();
    Texture2DContent tc = importer.Import(item, null) as Texture2DContent;
    AssetWriter.Write(item.Substring(item.Replace('\\', '/').LastIndexOf('/') + 1), tc);

ここで、itemは単なるファイル名であり、AssetWriterはこれを実際に実行します(いくつかのメソッドがありますが、以下にそれらを一緒に貼り付けました)。

   Type compilerType = typeof(ContentCompiler);
   cc = compilerType.GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0].Invoke(null) as ContentCompiler;
   compileMethod = compilerType.GetMethod("Compile", BindingFlags.NonPublic | BindingFlags.Instance);
   string fullPath = Path.Combine(basePath, path, objectName + ".xnb");
   using (FileStream fs = File.Create(fullPath))
   {
      compileMethod.Invoke(cc, new object[]{
      fs, objectToWrite, TargetPlatform.Windows, GraphicsProfile.Reach, false/*true*/, fullPath, fullPath
      });
   }

このように機能します。プログラムは必要なものすべてをコンテンツコンパイラに渡し、コンパイルがその役割を果たします。Texture2DContentを正しく処理し、それをTexture2DのXNB出力にマップします。この出力は、contentManagerのloadメソッドを使用してロードできます。

于 2012-01-15T02:12:00.407 に答える