Galaxy Generated and Rendered in Unity 3D
Galaxy Generated and Rendered in Unity 3D

In the end, it took me four evenings to replicate the functionality in my Javascript prototype. I’d have to point out that I was able to do some really nice UI stuff (e.g. drag to rotate, mousewheel to zoom) in Unity that I hesitated to mess with in Javascript (the galaxy was rendered to a canvas in Javascript).

On the whole, I have some impressions.

First, C# is very strict about types, and while I can see some benefits, I think a lot of it is utterly wasted. E.g. having to constantly cast from one numeric type to another is simply a pain in the butt (I routinely expect to have to tease apart a bunch of cryptic type-related errors every time I compile a few lines of new code).

// given an array of weights, pick an index with corresponding weighted probability,
// e.g. [1,2,3] -> 1/6 chance of 0, 2/6 chance of 2, 3/6 chance of 3
public uint Pick( uint[] weights ){
    int s = 0;
    uint idx;
    foreach( uint w in weights ){
        s += (int)w;
    }
    s = Range (1, s); // returns a random int from 1 to s, inclusive
    for( idx = 0; idx < weights.Length; idx++ ){
        s -= (int)weights[idx];
        if(s <= 0){
            break;
        }
    }
    return idx;
}

And all of this rigor didn’t actually prevent or even help debug an error I ran into with overflowing a uint (I have a utility that picks weighted random numbers, but I overflowed the weights leading to an out-of-bounds error. (A simple fix is to change idx < weights.Length to idx < weights.Length – 1.) On the whole it would be nice if you could simply live in a world of “numbers” (as in Javascript) and only convert explicitly to a specific representation when doing something low level.

Second, there’s this weird restriction on naming classes within a namespace such that the namespace and class sometimes may not match and the class you want is often not in the namespace you expect. (E.g. I wanted to create the namespace LNM.PRNG and define the class PRNG in it, but this confuses the compiler, so I ended up calling the namespace LNM.Random — so code referring to this is “using LNM.Random” which mysteriously causes a class called PRNG to become available.) I don’t see why namespaces and class names can’t be the same.

Oddly enough in some cases I am allowed to name the class the same as the namespace, and I don’t know why. So LNM.Astrophysics implements the Astrophysics class, but I had to rename Badwords to BadwordFilter at some point because the compiler started complaining.

I’ve been using Monodevelop, which is an editor produced by the Mono folk and lightly customized to work with Unity. It’s a bit of a slug (if it’s developed using Mono, then it’s not a terrific advertisement for Mono). In particular, its autocomplete is great when it works, but utterly frustrating far more often. It fails to match obvious words (e.g. local variable names) and often makes it impossible to type something short (which matches something longer) on the first attempt. The autocomplete is darn useful, or I’d simply switch back to Sublime.

Flying my untextured spaceship around an undecorated, partially implemented solar system
Flying my untextured spaceship around an undecorated, partially implemented solar system

So the current reckoning is that I ended up producing the following:

  • Astrophysics.cs — defines the LNM.Astrophysics namespace and implements the Astrophysics utility class, some useful enumerations, and the Galaxy, Star, and Planet classes.
  • PRNG.cs — defines the LNM.Random namespace and implements the PRNG class which provides convenience functions for the Meisui.Random Mersenne Twister implementation I’m using.
  • Badwords.cs — defines the LNM.Badwords namespace and implements the BadwordFilter class which checks to see if any of a pretty comprehensive list of nasty words is present in a given string. (Used to prevent obscene star names from being generated.)
  • Billboard.cs — a Monobehavior that keeps a sprite facing the camera. It’s a little cute in that it tries to save CPU time by only updating a given star every 10 physics updates. There’s probably a better way.
  • FixedCamera.cs — a Monobehavior that implements a mouse/touch controlled camera that keeps a fixed view of a specified target unless explicitly moved. I’m planning on using this as my main view control throughout the game.
  • NewtonianScoutship.cs — a Monobehavior implementing an Asteroids-style player ship. I’ve also experimented with a “Delta Vee” style abstracted Newtonian ship controller but good old rotate and accelerate just feels better, and makes movement a pleasant challenge in and of itself. (It also makes becoming “stationary” in space almost impossible, which I think is a Good Thing.)
  • GalaxyGenerator.cs — a Monobehavior that instantiates a galaxy and renders it with sprites. (Right now every single star is a Draw Call, so I’m going to need to do some optimization at some point.)
  • Starsystem.cs — a Monobehavior that instantiates a Star (and its planets) and renders them, a navigation grid (to provide a sense of movement when passing through empty space) and orbits using a bunch of Prefabs.

So, while I continue to find C# quite tedious to develop with, I am making significant progress for the first time in over a year, and while C# feels much less productive than real Javascript, I do think it’s very competitive with Unityscript, and it’s been quite easy to get over the hump.