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

  • 15
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

はじめに

この投稿は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を使って作成します。

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

image0.png

編集後の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を選択します
  2. 表示されたウィンドウで、Build > GeneralでTarget frameworkをMono/.NET 2.0に変更します
  3. 次に同じウィンドウで、Build > Compiler を選択します
  4. Command line parametersに、--standaloneと入力します(下図参照)
  5. System.CoreSystem.Numericsのリファレンスを削除します(下図参照)
  6. Buildします(今回はDebug)
  7. ソリューションのルート/FsharpUnityLibrary/bin/DebugFsharpUnityLibrary.dllが生成されています

image1.png

image2.png

Unityでの利用

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

  1. Unityプロジェクトを作成します。
  2. 先ほど作成したDLLをソリューションのルート/Assets以下にコピーします
  3. 次のようなSample.csを作成します
  4. Sample.csを任意のシーンの任意のGameObjectに付与し、シーンを再生します
  5. Consoleウィンドウに後述のログに出力されることを確認します
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);
    }
}
Hello F# World!
18446744073709551616
(Hello, 7)

ちょっと考えてみた!

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

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

編集後のComponent1.fs
namespace FsharpUnityLibrary

type FsharpSampleClass() = 
    member this.Message = "Hello F# World!"
    member this.MyBigInterger = 18446744073709551616I
    member this.MyTuple = ("Hello", 7)
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)型を使うことを考えると思います。さて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さん、ありがとうございました。