C#によるゲーム開発 2014

[去年の Advent Calendar の時][ac] は、C#で使える主なゲーム用フレームワークをいくつか紹介しました。
2014年も Unity の勢いは強く、これらのフレームワークはいまいち注目されていない感がありますが、
開発は盛んに行われています。(ANXだけは更新されてませんね……)
今回は今年一部で話題になった Mono for Unreal Engine と Paradox Engine を紹介したいと思います。

Unity を使って C# でゲームを作っている方も少なくないとは思いますが、
Unity は古い Mono コンパイラを使っているために C# 3.0 までしか対応していません。
しかし、今回紹介する二つはどちらも .NET 4.5 に対応しており C# 5.0 で開発が可能です。
今時の C# でゲームを作りたい方の参考になれば幸いです。

## Mono for Unreal Engine
公式サイト:http://mono-ue.github.io/

Mono for Unreal Engine は Unreal Engine 4(UE4)でロジックをC#で記述できるようにするプラグインです。
UE4は、最新技術を使ったハイクオリティなグラフィックスを表現することが可能なゲームエンジンです。
利用するのに必要なのはたったの 19$/month で、学生なら GitHub の Student Developer Pack でなんと無料です。
UE4 においてロジックを記述する方法としてはブループリントという独自のシステムと C++ がありますが、
このプラグインによって C# でもロジックを記述できるようになります。
Mono for Unreal Engine 自体は UE4 のサブスクリプションを持っていれば無料ですが、
今のところなぜか電話番号と住所の入力を求められます。
個人情報を入力するのはちょっと気になりますが、UE4でもC#が使えるというのは嬉しいです。

## Paradox Engine ##
公式サイト：http://paradox3d.net/

Paradox Engine は、 OROCHI や Yebis などミドルウェアで有名なシリコンスタジオ製のゲームエンジンです。
こちらは完全に無料となっています。
公式サイトにアクセスすると、でかでかと Create cross-platform games in C# と書かれています。素敵。
Paradox Engine は、ゲームエンジンと聞いてよくイメージされる Unity のようなゲーム画面を見ながら要素の配置などを行えるわけではありません。
あくまで開発はコーディングがメインです。(一応ロードマップには A full scene editor があります)
Paradox Engine を起動すると、Paradox Studio というツールが立ち上がります。
Paradox Studio はアセット(画像や音声など)を管理する機能がメインとなっています。
プロジェクトを作成すると、 Visual Studio と同じ形式の sln ファイルができるので、
コードを Visual Studio で管理、アセットを Paradox Studio で管理というような形で開発ができます。
その他、特徴としては
<dl>
  <dt>async/await 対応</dt>
    <dd>一部の非同期処理のメソッドはawaitをつけて呼び出せるようになっています。<dd>
  <dt>低レベルAPIアクセス</dt>
    <dd>DirectX や OpenGL の低レベルAPIにもアクセスできるようになっています。</dd>
  <dt>拡張HLSL</dt>
    <dd>HLSLを拡張した言語でシェーダを便利に扱いやすくなっています。</dd>
</dl>
といった感じです。

ちなみに、今年オープンソース版がリリースされ、バイナリ版とオープンソース版で別のライセンスになっています。
バイナリ版で作ったゲームはロイヤリティフリーで特に縛りは無いようです。
オープンソース版はGPLv3なので、ソースからビルドした Paradox Engine で作ったゲームはGPLv3としてソースを公開する必要があります。

せっかくなので Paradox Engine でモデルを表示するまでをやってみたいと思います。
今回使ったバージョンは 1.0.0-beta06 です。
まだベータ版なので今後ライブラリの破壊的変更や Paradox Studio の UI 変更の可能性があることにご注意ください。

![newproj](https://qiita-image-store.s3.amazonaws.com/0/59959/551f5ef7-07e2-af58-87be-0f2ebe5cb7ff.png)

これが新しくプロジェクトを作った画面です。
まずはモデルのFBXファイルをインポートします。

![import](https://qiita-image-store.s3.amazonaws.com/0/59959/57d10204-5ff8-da81-b5e9-c91e01246171.png)

サンプルに含まれている knight.fbx を読み込みます。

![fbx](https://qiita-image-store.s3.amazonaws.com/0/59959/6e2d6d2b-a63a-4124-7699-321414e78b30.png)

FBX ファイルで指定されているテクスチャやマテリアルなどが表示され、一部だけインポートすることもできます。

![knight](https://qiita-image-store.s3.amazonaws.com/0/59959/dd8d944d-f0d4-13e2-c27a-ee90c8a2bbef.png)

アセットビューにインポートしたアセットが表示されます。

![axis](https://qiita-image-store.s3.amazonaws.com/0/59959/60052f15-d2ef-56bc-1cc5-dac6095834f8.png)

モデルが変な方向を向いているので、knight_model を選択して
Up Axis を 0,0,1
Front Axis を 0,-1,0　にします。

これを保存してアセットの準備は完了です。
次に sln ファイルを VisualStudio で開いてコードを書きます。
(プロジェクト名)Game.cs というようなファイルがあるので開きます。
このファイルがゲームの中心になります。
最初は以下のようなコードが書かれています。

```csharp:ModelViewGame.cs
using System.Threading.Tasks;
using SiliconStudio.Core.Mathematics;
using SiliconStudio.Paradox;
using SiliconStudio.Paradox.Effects;
using SiliconStudio.Paradox.Graphics;

namespace ModelView
{
    public class ModelViewGame : Game
    {
        public ModelViewGame()
        {
            // Target 9.1 profile by default
            GraphicsDeviceManager.PreferredGraphicsProfile = new[] { GraphicsProfile.Level_9_1 };
        }

        protected override async Task LoadContent()
        {
            await base.LoadContent();

            CreatePipeline();

            // Add custom game init at load time here
            // ...

            // Add a custom script
            Script.Add(GameScript1);
        }

        private void CreatePipeline()
        {
            // Setup the default rendering pipeline
            RenderSystem.Pipeline.Renderers.Add(new CameraSetter(Services));
            RenderSystem.Pipeline.Renderers.Add(new RenderTargetSetter(Services) { ClearColor = Color.CornflowerBlue });
            RenderSystem.Pipeline.Renderers.Add(new ModelRenderer(Services, "ModelViewEffectMain"));
            RenderSystem.Pipeline.Renderers.Add(new UIRenderer(Services));
        }

        private async Task GameScript1()
        {
            while (IsRunning)
            {
                // Wait next rendering frame
                await Script.NextFrame();

                // Add custom code to run every frame here (move entity...etc.)
                // ...
            }
        }
    }
}
```

Game クラスの構成は、XNAなどと違うあまり見慣れない構成になっています。
Paradox Engine はエンティティコンポーネントベースと呼ばれるシステムになっているので、
エンティティというカメラやモデルなどの部品やスクリプトを組み合わせてゲームを構成します。

この状態で実行するとコーンフラワーブルーで塗りつぶされたウィンドウが表示されます。
実行は Visual Studio からでも Paradox Studio からでも同じように F5 で実行できます。

モデルを表示するためのコードを追加します。
`LoadContent` メソッドの、`CreatePipeline();`の後に以下のコードを書きます。

```csharp
// 騎士のモデルを非同期に読み込む
var knightEntity = await Asset.LoadAsync<Entity>("knight");
// カメラのエンティティの作成と設定
var cameraEntity = new Entity("Camera")
{
    new TransformationComponent() {Translation = new Vector3(0, -300, 230)},
    new CameraComponent
    {
        NearPlane = 1,
        FarPlane = 10000,
        TargetUp = Vector3.UnitZ,
        Target = knightEntity,
    }
};
// カメラコンポーネントを描画パイプラインにセット
RenderSystem.Pipeline.SetCamera(cameraEntity.Get<CameraComponent>());
// カメラとモデルをシーンに追加
Entities.Add(cameraEntity);
Entities.Add(knightEntity);
```

必要なコードはたったのこれだけ。
やってることは Unity で カメラの GameObject を作って、
fbxをD&Dしてモデルを追加するのと似たようなものですね。

実行してみます。

![view](https://qiita-image-store.s3.amazonaws.com/0/59959/791895a3-11fb-a885-74e3-d71eeb4fc7e3.png)

ちゃんと騎士が表示されました。

Paradox Engine は拡張HLSLなどでグラフィックスにこだわったゲームも作ることができそうです。
今後のアップデートにも期待ですね。

## XNA追悼
最後に、C#によるゲーム開発について語るうえで重要な存在 XNA について。
[XNA開発終了の記事][xna]で、2014年4月1日に fully retire とありました。
今年ついにその日を迎えました。
XNA は現存の様々なゲームエンジンなどにも影響を与えています。
ありがとうXNA。貴方のことは忘れません。

[ac]: http://jag5.dreamlog.jp/archives/8162454.html
[xna]: http://www.gamasutra.com/view/news/185894/Its_official_XNA_is_dead.php