F# で作成したライブラリをUnityのスクリプト上で利用する
ゲームのほうのUnityの話です。
UnityはMonoを基盤としており、スクリプト内で.NETなライブラリはもちろん、自作ライブラリをUnity側で読み込んで使うことだってできます。
そのライブラリ、F#で作ろうず!
こうなると、ロジック部分はF#で作りたいですよね?
特に非同期プログラミングとか、副作用のすくないコードとか。
では、作ってしまいましょう!
とりあえずサンプルを作る
サンプルなので、簡単なCounterみたいな?
namespace FsCounter open System module Counter = let Zero = 0 let Increment counter = counter + 1 let Decrement counter = counter - 1 let Reset max = let rand = new Random() match rand.Next(max) , rand.Next(max) with | _ , 0 | 0 , _ -> Zero | x , y when x > y -> x % y | x , y -> - ( y % x )
Reset関数以外はテストコードも書いてみました。
module FsCounterScenario open NaturalSpec open FsCounter [<Scenario>] let ``初期値0のカウンターを生成できる ``() = Given Counter.Zero |> It should equal 0 |> Verify [<Scenario>] let ``初期状態のカウンターをインクリメントするとカウントが1増える`` () = Given Counter.Zero |> When Counter.Increment |> It should equal 1 |> Verify [<Scenario>] let ``カウントが1のカウンターをインクリメントするとカウントが2になる`` () = Given Counter.Zero |> Counter.Increment |> When Counter.Increment |> It should equal 2 |> Verify [<Scenario>] let ``初期状態のカウンターをデクリメントするとカウントが1減る`` () = Given Counter.Zero |> When Counter.Decrement |> It should equal -1 |> Verify [<Scenario>] let ``カウントが-1のカウンターをデクリメントするとカウントが-2になる`` () = Given Counter.Zero |> Counter.Decrement |> When Counter.Decrement |> It should equal -2 |> Verify
Unity側で使う
上記コードをビルドして出来上がったdllを、Unityプロジェクト下にあるAssetsフォルダのどこかに放り込みましょう。Assets下ならどこでもよさそうなので、外部ライブラリだとわかりやすいようにフォルダでまとめておくのがお勧めです。
ただ、F#ライブラリの場合はこれだけだと"FSharp.Core.dllがないよ"とかで怒られるので、F#関連のdllも放り込みます。
追記:コンパイラオプションで--standaloneを指定してコンパイルすれば自作ライブラリのdllだけで動くようになります(@zeclさん、情報ありがとうございます!)
using UnityEngine; using System.Collections; using FsCounter; public class CountViewer : MonoBehaviour { int max = 100; int min = -100; int data = Counter.Zero; void OnGUI() { if (data >= max || data <= min) data = Counter.Reset(max); if (data > 0) data = Counter.Increment(data); else data = Counter.Decrement(data); GUI.Label(new Rect(Screen.width / 2 - 50, Screen.height / 2, 100, 60), new GUIContent("Counter : " + data)); } }
カウンタをラベルに表示するだけの簡単なものです。
あとはこのスクリプトをEmpty Objectにリンクさせれば動くようになります。