Wednesday, December 23, 2015

Unit Testing FSharp for Unity3D

I'm going to try using FSharp in Unity, and I want to unit test my code before I drop my compiled dll into Unity's Asset folder. Testing is one thing that MonoDevelop is pretty good at. After installing mono-develop, I installed NUnit:

sudo apt-get install monodevelop-nunit.

You can also install it from MonoDevelop via the menu: Tools->Add-in Manager.

So in the project view, I right click on my Solution Items, and select Add->New Project...
I don't see any templates for FSharp Unit Testing, so I'll do this from scratch. I create a FSharp Library Project, and name it Test. For Unity compatability, we need to change the taget, so select Project -> Test Options -> Build -> General and change the target framework to Mono/.NET 3.5.

Next, I install NUnit. Right click on the new project, Test, and select Add Nuget Packages. I'll look for and install NUnit. And here I have a problem. NuGet won't install the correct version for my target (3.5), but it will tell me that it installed the wrong one... and that's why I don't use NuGet.

So instead, I visit http://nunit.org/?p=download, and grab the Previous Release: NUnit 2.6.4. I unzip it to my ~/Applications folder, and then reference the dll in my project: In the project view, right click on References and select Edit References... From here I select the .Net Assemblies tab, and browse for ~/Applications/NUnit-2.6.4/bin/nunit.framework.dll \

Now I'm ready to write tests, so I create a simple class:

open System    
open NUnit.Framework
open Entitas

[<TestFixture>]
type Tests() =

    let world = new World(64)

    [<Test>]//1st entity - no components
    member this.Test001() =

        let e1 = world.CreateEntity("Playerz")
        Assert.AreEqual(1, e1.Id)

Save my work, right click on my Test project, and select Run Item to run my tests. I can also reference Unity data types by referencing the UnityEngine.dll:

Right click on References and select Edit References... From here I select the .Net Asseblies tab, and browse (on my system) for /opt/Unity/Editor/Data/Managed/UnityEngine.dll

Now, I add 

open UnityEngine
...

    [<Test>]//2nd test - one conponent
    member this.Test002() =

        let e2 = world.CreateEntity("Playery")
        e2.AddComponent(1, new Vector3(1,0f, 1.0f, 1.0f))
        ...
When I'm satisfied that my basic functionality is working, I move the dll into my Unity projects Asset folder. I do this by selecting my game project (not the testing project) in the project view, go to Project -> Project Options. Select the Build->Output and browse to my Unity project Asset folder. I create a new folder - Assets/Libraries, and select it. Now when I build my game project, the dll is generated directly into my Unity project. I can switch to the Unity Editor, and click on Play to see my code at work.

Sunday, December 13, 2015

Using FSharp with Unity

Getting the FSharp binaries to work with Unity is pretty well covered here: Tutorial: Using F# with Unity3D. I was able to get up and running with Unity 5.2.2f1 on Linux Mint 17 and MonoDevelop 5.10.

I started working through the Unity Angry Birds tutorial, and ran into some problems with the mouse. Really, though, it turned out to be an error between chair and keyboard while trying to re-implement the csharp tutorial code in fsharp.

At first attempt, this line looked like it should be changed from this

    Vector2 catapultToMouse = mouseWorldPoint - catapult.position;

to this:

    let catapultToMouse = mouseWorldPoint - catapult.position

The problem with is that now, 'catapultToMouse' becomes a Vector3. The caused problems latter on when 'catapultToMouse.sqrMagnitude' had an unexpected value. I fixed this with a helper function that converts a Vector3 to a Vector2:

    let catapultToMouse = Vec32(mouseWorldPoint - catapult.position)


The other issue I ran into was my code was not deetecting a null value for a unity component. It turns out to be a known issue F# null test fails to detect null values

After these two issues were resolved, I was able to get the demo working. And finally, to enable touch support on Android, I added this code to the end of the Update method:

        if Input.touchCount > 0 then
            match Input.GetTouch(0).phase with
            | TouchPhase.Began -> this.OnMouseDown()
            | TouchPhase.Ended -> this.OnMouseUp()
            | TouchPhase.Canceled -> this.OnMouseUp()
            | _ -> ()


The entire project is located here

Friday, December 11, 2015

Nemerle or FSharp?

Both are comparable functional DotNet languages. I want to use one of them in Unity. So I worked through this tutorial -MAKING AN "ANGRY BIRDS" STYLE GAME - PART 1 with each language, plus C#. Here are my conclusions.

C#

  • Baseline. Everything works and can target android.

F#

  • I couldn't the get mouse to work correctly
  • It takes more boilerplate to interop with components (1)
  • I can't use latest binaries in Unity, due to Unity's funky 3.5ish framework level
  • But - code completion and compilation works in MonoDevelop 

Nemerle

  • Interop is transparent (2) and mouse works + touch works on android
  • The binaries are current - a new drop yesterday included the 3.5 framework
  • I can edit in Code and compile using Nant. No *.sln files to deal with.

I never finished the FSharp version, because I couldn't get past the mouse issue.
NOTE: This is fixed. See my next post
 If I were to use FSharp, it would be as a library that does not interface directly with Unity. I'd need a CSharp layer. Maybe if I actually wanted to use MonoDevelop. But I prefer Code, and debugging for Unity is working now.

I think I prefer Nemerle syntax, it doesn't seem as dense. I can even use white space with #pragma indent. But more importantly, Nemerle seems to work better with Unity, and I can use the latest binaries when targeting android.

It's a no brainer. For my purposes, Nemerle wins.


1 - Defining a Unity component property in F#

[<defaultvalue>][<serializefield>]
val mutable catapultLineBack:LineRenderer

2 - Defining a Unity component property in Nemerle

public mutable catapultLineBack: LineRenderer




Thursday, December 3, 2015

Stop The Madness: Using json in csharp

I want to read some json in csharp. It shouldn't bee too hard, there are some great libraries out there - Json.NET comes to mind. The problem with most of the existing libraries is that they do too much - I don't really need xml support, or linq or json path. In fact, all I want is the JSON.parse and JSON.stringify that I love so much in javascript. And so here it is - JSON2.cs.

The first thing you're going to say is 'Why are you boxing values? Where is dynamic?'. Actually, the 1st version used dynamic, and it's very cool to use, because you can access json values as dot properties. But dynamic is not allowed in the Unity version of csharp. Too bad, but I can see that dynamic could become a performance issue. So we will use bracketed notation. There are 2 helper classes - JSONObject and JSONArray. And 2 helper functions that really just wrap a cast - JSON.Object and JSON.Array.

The reason for all of this madness? So I can store a small database in my game with preferences and local leaderboard values:

 /**
 * Get Leaderboard
 * 
 * @param {int} count
 * @returns {JSONArray} the top count scores.
 */
 public static JSONArray GetLeaderboard(int count) {
  var jsonQueryAll = string.Format(@"{{""limit"":{0}, ""sort"": [[""score"", ""DESC""]]}}", count);
  return db.QueryAll("leaderboard", jsonQueryAll);
 }

To facilitate this, I've also ported localStorageDB.js to PlayerPrefDB.cs. You can see it in action, I'm using it in my first Unity game, Shmup Warz. Yes, I'm porting Shmup Warz also from typescript to csharp. Where does the madness stop?!