はじめに
この投稿はF#アドベントカレンダー2014の22日分の投稿です。
別にF#アドベントカレンダーは、Hello World!
でもいいとのことでしたので、初心者がHello World!
してみました。Unityゲームエンジンで。
@pocketberserkerさんさんが、こちらの記事でUnityでF#を使われている記事を見て、まねして私もやってみました!F#の勉強会もだいぶ前ですがに行ったし、何もしないのはもったいないかなと、Hello World!
ですがやってみました!
繰り返しになりますが、F#ド初心者です。
間違いの指摘、良くないところのアドバイスなどお願いします!
UnityでF#を使ってみた!
Xamarinを使ってF#のライブラリを作り.NET 2.0向けのDLLを作成して、それをUnityで利用してみます。
(Xamarin Studioのバージョンは5.5.4で、Macでやっています。)
(間違いの指摘、良くないところのアドバイスなどお願いします!またこうした方がいいなどありましたら、教えていただけると嬉しいです。)
ソリューション・プロジェクトの作成
まずF#のライブラリプロジェクトをXamarinStudioを使って作成します。
- Xamarinを起動し、メニューからFile > New > Solution を選択します
- 表示されたウィンドウで、F# > Library を選択します(下図参照)
- Locationを適切に設定し、NameをFsharpUnityLibraryとし、OKボタンを押します
- プロジェクト内の
Component1.fs
を次のように編集します
namespace FsharpUnityLibrary
type FsharpSampleClass() =
member this.Message = "Hello F# World!"
member this.MyBigInterger = 18446744073709551616I
member this.MyTuple = ("Hello", 7)
DLLの作成
次にUnityで使えるように、DLLを作成します。
- プロジェクトを右クリックし、ポップアップからOptionsを選択します
- 表示されたウィンドウで、Build > GeneralでTarget frameworkを
Mono/.NET 2.0
に変更します - 次に同じウィンドウで、Build > Compiler を選択します
- Command line parametersに、
--standalone
と入力します(下図参照) -
System.Core
とSystem.Numerics
のリファレンスを削除します(下図参照) - Buildします(今回はDebug)
-
ソリューションのルート/FsharpUnityLibrary/bin/Debug
にFsharpUnityLibrary.dll
が生成されています
Unityでの利用
さきほど作ったF#のDLLをインポートして、UnityでF#を使ってみます
- Unityプロジェクトを作成します。
- 先ほど作成したDLLを
ソリューションのルート/Assets
以下にコピーします - 次のような
Sample.cs
を作成します -
Sample.cs
を任意のシーンの任意のGameObjectに付与し、シーンを再生します - Consoleウィンドウに後述のログに出力されることを確認します
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);
}
}
Hello F# World!
18446744073709551616
(Hello, 7)
ちょっと考えてみた!
さらっとF#のコードについてさらっと流しましたが、意図があってのコードです。
F#側のコードとUnityのC#側のコードを再掲します。
namespace FsharpUnityLibrary
type FsharpSampleClass() =
member this.Message = "Hello F# World!"
member this.MyBigInterger = 18446744073709551616I
member this.MyTuple = ("Hello", 7)
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)型を使うことを考えると思います。さてulong(UInt64)型の表現範囲は、0から18446744073709551615です。F#側の18446744073709551616は、ulong(UInt64)型の表現範囲より1大きいですね。ここでは、System.Numerics.BigInteger型を使ってulong(UInt64)が表せない正の整数を表しています。I(アイ)はBigIntegerの接尾詞です。
また、MyTupleではタプル(System.Tuple<T1, T2>)型を使っています。
何か気づきませんか?
Unityでは、System.Numerics.BigInteger型やタプル(System.Tuple<T1, T2>やSystem.Tuple<T1, T2, T3>など)を普通は使うことは出来ません。それらは.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がいくつか含まれるそうです。(くわしくはこちら)。そのため、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さん、お手をわずらわせてしまった@pocketberserkerさん、ありがとうございました。