Building incredible multiplayer games since 2012.

Free HUGS!

Free HUGS!

In my last post, I discussed why Proletariat chose to use Haxe and Unity together to build World Zombination. Now, I’d like to introduce you to the Haxe library we built that allows you to write Unity code: HUGS. We’re making it freely available on GitHub so you can use Haxe in your own Unity projects.

image
Sloth math!

HUGS stands for Haxe Unity Glue…Stuff. (We really just wanted a cute acronym [ed: Whatever, sloth-hater.]). The library includes Haxe extern definitions for almost every class exposed in Unity and .NET 2.0. A Haxe extern definition is basically just a class definition written in Haxe that mirrors the C# class definition. (Some more info on extern class definitions here.)

To install HUGS (assuming you already have Haxe installed), just enter this on the command line:

haxelib install HUGS

(You may need to sudo if running on OSX/Linux.)

Haxelib is a library manager that is distributed with Haxe: it allows you to search, install, and upgrade libraries that have been made publicly available. You can browse all the available libraries on lib.haxe.org.

Now that you’ve installed HUGS, let’s see how to use it! (I’m going to assume you have some familiarity with the Unity API.) Here is a simple MonoBehavior written in Haxe:

package;

import unityengine.*;
using hugs.HUGSWrapper;

class HugsBehavior extends MonoBehaviour
{
  public function Awake() {
    Debug.Log("woke up!");
  }

  public function FixedUpdate() {
    var rb = getTypedComponent(Rigidbody);
    rb.AddForce(new Vector3(0,10,0));
  }

  public static function main() {
  }
}

You’ll first notice that this looks pretty similar to C# syntax, but there are definitely some differences. I’ll leave it to you to look at the Haxe documentation for the basic syntax, but there are a couple non-obvious things I’d like to point out.

The first line indicates the Haxe package for the class. Haxe packages are analogous to C# namespaces. This simply indicates that the class will be in the top-level namespace.

Next, the Haxe import statement is used to specify classes or packages that you wish to reference. In this case, we’re importing the entire unityengine package, which is analogous to the using UnityEngine statement in C#. (Note that in Haxe, package names are always lowercase.)

After that, we see the using hugs.HUGSWrapper statement. This may be confusing, because it does not mean the same thing as using in C#! (That’s what import is for.)

The using statement in Haxe is a way to extend class definitions with custom functions. It’s a handy way of adding your own functions to existing classes, without having to modify the class itself. The HUGSWrapper class (included in HUGS) adds helper functions to various Unity API classes that make it easier to work with in Haxe. Refer here for more information on the Haxe using statement.

One of the functions that HUGSWrapper adds is getTypedComponent, which is called inside the FixedUpdate function in this example. This is analogous to a GetComponent call in Unity C#, but with a friendlier Haxe syntax. (The Haxe and C# type systems are different, so this helper function maps between the two for you.)

Finally, we see an empty static main function defined. This is necessary for the Haxe compiler- there needs to be a main function in one of your classes. This function isn’t actually going to be called by Unity. In a “real” project with lots of files, you would typically put this main function in some empty class, but since we only have one class in this example we’ve included it here.

Now let’s see how we can use this MonoBehavior in Unity! First, we need to set up our project structure. We’ve found that one easy way to do this is to have two top-level folders. In our case, we’re going to call these haxe_project and unity_project. Save the example class as HugsBehavior.hx inside the haxe_project folder, and then create a new unity project inside the unity_project folder.

Now, let’s generate the C#! Go to the haxe_project folder and run the following:

haxe -main HugsBehavior -lib HUGS -D no-compilation -cs ../unity_project/Assets

I’ll explain the various command line arguments:

  • -main HugsBehavior specifies the class that has the static main function. Like I mentioned earlier, we put this inside the HugsBehavior class in our example.
  • -lib HUGS indicates that Haxe should use the HUGS haxelib. If you haven’t yet installed HUGS, the Haxe compiler will tell you to do so.
  • -D no-compilation tells the Haxe->C# compiler that it should not try to actually build an executable. By default, Haxe will actually build an exe file for you that you can run directly. In our case, we just want to generate the C# source files and put them in the Unity project.
  • -cs ../unity_project/Assets indicates to Haxe that we are building C#, and specifies the directory where the C# code should go.

Assuming you’ve successfully compiled, you can now go into the Unity project and add the HugsBehavior behavior to a GameObject! You can try this by creating a Sphere GameObject, and adding the HugsBehavior script. You’ll also want to make sure to add a RigidBody component to the sphere, because our example needs it. When you hit Play, you’ll see the sphere kind of slowly float up as it fights gravity. (Awesome demo, I know.)

If you look at the generated C# code inside the unity project, you’ll see it is not exactly pretty. The Haxe compiler also generates a lot of functions behind the scenes in order to support its type system and language features. Finally, as I mentioned in the previous post, Haxe will inline functions inside the generated C# code, which can make the generated functions long and unwieldy. (You can disable this with the --no-inline command line argument for testing.)

Thankfully, you should not have to look at the generated C# code often, if ever. For example, try removing the RigidBody component from your GameObject, which will cause the FixedUpdate function to crash. When you hit Play, you’ll see the following error in Unity:

NullReferenceException: Object reference 
not set to an instance of an object MyBehavior.FixedUpdate () 
(at [...]/hugs_project/HugsBehavior.hx:14)

Notice that the error message indicates the Haxe source file that caused the exception, rather than the generated C# source. This is accomplished via #line directives inside the generated C# code that map each line to its corresponding line in the Haxe source file. This makes debugging far simpler and allows you to usually treat the generated C# source as a black box.

Finally, I’d also like to introduce the cslibgen project. This is a simple C# program that will take a .NET DLL and generate Haxe extern definitions for all classes in the DLL. (Hat tip to Ben Cooley, who wrote the original version that we’ve since forked to add various features.) All of the extern definitions in HUGS were generated via cslibgen. You can also use cslibgen to generate externs for other classes- such as utilities purchased from the Unity Asset Store. Typically these are distributed as C# source files, but you can use generate Haxe externs by first compiling these C# files in MonoDevelop, and then feeding the resulting DLL into cslibgen. I should note that the Haxe code generated by cslibgen is not always perfect, and can get tripped up by libraries that use lots of function overloading, operator overloading, or complicated use of C# generics. We are continually trying to improve this tool and fix bugs, so let us know if you find problems.

The HUGS library source code is available here, and cslibgen source and executable is available here. Have fun!

In our future tech posts, we’ll be moving to the server to discuss how we’re using Haxe and node.js, and showcasing some libraries we’re using that help make this much easier. See you then!

If you’ve got any questions on HUGS, feel free to shoot us an email hi-eng@proletariat.com or send us a message on Twitter @proletariat_inc.

Dan Ogles, CTO

image

On Twitter