初心者がF#をUnityで使ってみた！

# はじめに
この投稿は[F#アドベントカレンダー2014](http://connpass.com/event/9758/)の22日分の投稿です。

別にF#アドベントカレンダーは、`Hello World!`でもいいとのことでしたので、初心者が`Hello World!`してみました。Unityゲームエンジンで。

[@pocketberserker](https://twitter.com/pocketberserker)さんさんが、[こちら](http://pocketberserker.hatenablog.com/entry/20120118/1326874406)の記事でUnityでF#を使われている記事を見て、まねして私もやってみました！F#の勉強会もだいぶ前ですがに行ったし、何もしないのはもったいないかなと、`Hello World!`ですがやってみました！

繰り返しになりますが、F#ド初心者です。

間違いの指摘、良くないところのアドバイスなどお願いします！

# UnityでF#を使ってみた！

Xamarinを使ってF#のライブラリを作り.NET 2.0向けのDLLを作成して、それをUnityで利用してみます。
(Xamarin Studioのバージョンは5.5.4で、Macでやっています。)

(間違いの指摘、良くないところのアドバイスなどお願いします！またこうした方がいいなどありましたら、教えていただけると嬉しいです。)

## ソリューション・プロジェクトの作成
まずF#のライブラリプロジェクトをXamarinStudioを使って作成します。

1. Xamarinを起動し、メニューからFile > New > Solution を選択します
1. 表示されたウィンドウで、F# > Library を選択します(下図参照)
1. Locationを適切に設定し、NameをFsharpUnityLibraryとし、OKボタンを押します
1. プロジェクト内の`Component1.fs`を次のように編集します

![image0.png](https://qiita-image-store.s3.amazonaws.com/0/4125/5dab05f8-607c-518b-e0aa-667ee738d555.png "image0.png")

```fsharp:編集後のComponent1.fs
namespace FsharpUnityLibrary

type FsharpSampleClass() = 
    member this.Message = "Hello F# World!"
    member this.MyBigInterger = 18446744073709551616I
    member this.MyTuple = ("Hello", 7)
```

## DLLの作成

次にUnityで使えるように、DLLを作成します。

1. プロジェクトを右クリックし、ポップアップからOptionsを選択します
1. 表示されたウィンドウで、Build > GeneralでTarget frameworkを`Mono/.NET 2.0`に変更します
1. 次に同じウィンドウで、Build > Compiler を選択します
1. Command line parametersに、`--standalone`と入力します(下図参照)
1. `System.Core`と`System.Numerics`のリファレンスを削除します(下図参照)
1. Buildします(今回はDebug)
1. `ソリューションのルート/FsharpUnityLibrary/bin/Debug`に`FsharpUnityLibrary.dll`が生成されています

![image1.png](https://qiita-image-store.s3.amazonaws.com/0/4125/a68cec42-113e-c4e8-daaf-faed1ccc110d.png "image1.png")

![image2.png](https://qiita-image-store.s3.amazonaws.com/0/4125/ac83b371-a0f0-5b12-68be-b27c96580b13.png "image2.png")

## Unityでの利用

さきほど作ったF#のDLLをインポートして、UnityでF#を使ってみます


1. Unityプロジェクトを作成します。
1. 先ほど作成したDLLを`ソリューションのルート/Assets`以下にコピーします
1. 次のような`Sample.cs`を作成します
1. `Sample.cs`を任意のシーンの任意のGameObjectに付与し、シーンを再生します
1. Consoleウィンドウに後述のログに出力されることを確認します

```csharp:Sample.cs
using UnityEngine;
using FsharpUnityLibrary;

public class Sample : MonoBehaviour
{
	void Start ()
	{
		FsharpSampleClass fshapSample = new FsharpSampleClass();

		string message = fshapSample.Message;
		Debug.Log (message);

		System.Numerics.BigInteger myBingInteger = fshapSample.MyBigInterger;
		Debug.Log (myBingInteger);

		System.Tuple<string,int> myTuple = fshapSample.MyTuple;
		Debug.Log (myTuple);
	}
}
```

```Consoleウィンドウに出力されるログ
Hello F# World!
18446744073709551616
(Hello, 7)
```

# ちょっと考えてみた！

さらっとF#のコードについてさらっと流しましたが、意図があってのコードです。

F#側のコードとUnityのC#側のコードを再掲します。

```fsharp:編集後のComponent1.fs
namespace FsharpUnityLibrary

type FsharpSampleClass() = 
    member this.Message = "Hello F# World!"
    member this.MyBigInterger = 18446744073709551616I
    member this.MyTuple = ("Hello", 7)
```

```csharp:Sample.cs
using UnityEngine;
using System.Collections;
using FsharpUnityLibrary;

public class Sample : MonoBehaviour
{
	void Start ()
	{
		FsharpSampleClass fshapSample = new FsharpSampleClass();

		string message = fshapSample.Message;
		Debug.Log (message);

		System.Numerics.BigInteger myBingInteger = fshapSample.MyBigInterger;
		Debug.Log (myBingInteger);

		System.Tuple<string,int> myTuple = fshapSample.MyTuple;
		Debug.Log (myTuple);
	}
}
```

`18446744073709551616I`に注目してください。(最後は英字のI(アイ)ですよ) このように大きい正の整数では[ulong(UInt64)型](http://msdn.microsoft.com/ja-jp/library/t98873t4.aspx)を使うことを考えると思います。さて[ulong(UInt64)型](http://msdn.microsoft.com/ja-jp/library/t98873t4.aspx)の表現範囲は、0から18446744073709551615です。F#側の18446744073709551616は、ulong(UInt64)型の表現範囲より1大きいですね。ここでは、[System.Numerics.BigInteger型](http://msdn.microsoft.com/ja-jp/library/system.numerics.biginteger(v=vs.100).aspx)を使ってulong(UInt64)が表せない正の整数を表しています。I(アイ)はBigIntegerの接尾詞です。


また、MyTupleではタプル([System.Tuple\<T1, T2\>](http://msdn.microsoft.com/ja-jp/library/dd268536(v=vs.100).aspx))型を使っています。

何か気づきませんか？

Unityでは、[System.Numerics.BigInteger](http://msdn.microsoft.com/ja-jp/library/system.numerics.biginteger(v=vs.100).aspx)型やタプル([System.Tuple\<T1, T2\>](http://msdn.microsoft.com/ja-jp/library/dd268536(v=vs.100).aspx)や[System.Tuple\<T1, T2, T3\>](http://msdn.microsoft.com/ja-jp/library/dd387150(v=vs.100).aspx)など)を普通は使うことは出来ません。それらは.NET Framework4.0で加わったものだからです。

Unityはmonoを使っています。.NET Framework 4.0相当のmonoバージョンは2.10らしいです(クラスライブラリの一部はそれより前でも使えるんですかね？勉強しておきます)。Unityはだいぶ古いmonoをベースにしています。(2.6.5?でもコミット的には、2.6.4の子孫でないっぽいし、そもそも2.6.5ってリリースされていないし) そのため、Unityでは.NET Framework 4.0で追加された、BigIntegerやタプルを通常は使うことはできません。

ところで、F#は.NET Framework 2.0でも動くようになっています。F#で.NET Framework 2.0で動作させるようターゲットなどを設定した場合、コアライブラリ (FSharp.Core.dll)の中に、F#開発に必要なSystem名前空間(BigIntegerやタプル、その他いくつかのクラス)の、.NET 4.0 APIと同じAPIがいくつか含まれるそうです。(くわしくは[こちら](http://msdn.microsoft.com/ja-jp/library/vstudio/ee829875%28v=vs.100%29.aspx))。そのため、Assets以下においたF#ライブラリのDLL内に含まれているF#コアライブラリのおかげで、UnityでもBigIntegerやタプルが使えるようです。

# まとめ

実際に今後F#をUnityで使うかは未定ですが、Hello WorldですがF#をUnityで動かしてみました。

今までなぜF#がUnityで動くか疑問でした。理解するため、monoや.NETについてちょと勉強しましたが、その感想は

「F#、.NET 2.0から動くん？」「.NET Frameworkすげえ！」「CLIすげぇ」「ILの互換性ぱねぇ、.NET 2.0からの互換性ぱねぇ、変性が2.0の時点で入ってる！」「mono、Xamarinありがてぇ！」

という感じです。まだまだしっかりと理解できていませんので、もうしこし理解がすすんだらまとめたいと思います。

F#成分少なくてすいません。初歩的すぎてすいません。

また、私のアドカレ本来の担当日をカバーしてくださった[@bleis](https://twitter.com/bleis)さん、お手をわずらわせてしまった[@pocketberserker](https://twitter.com/pocketberserker)さん、ありがとうございました。