RobotLegs Posts

Taming Unity

logo

For the last couple of months I have been working on a few different things including many new releases of Post To Tumblr. Most of my time however has been spent working on an unnamed (as of yet) game in Unity.

Its my first time using Unity, having come from a predominantly Flash games background I was excited to have the power of C# with a WYSIWYG editor for rapid iterations, and indeed I did make rapid progress. I soon had a working gameplay prototype up and running and everything and everything was hunky dory. It worked but the code was far from pretty with dependencies between my components all over the place not to mention the headaches when I tried to introduce Unit Testing into the mix.

The game I am developing is a turn based strategy with some complex gameplay rules, perfectly suited to unit testing I thought. Unfortunately however the power of Unity’s rapid development is also its downfall. It allows you to do some pretty nasty things. It also uses a vast number of statics and singletons making testing rather tricky. I managed to muddle my way through things using Unity’s recently released Unit Testing Tools however things were far from ideal.

The main issues were dependency hell and Managers. Unity seems to recommend “Managers” as a way to look after various parts of game logic. You create an empty game object then attach a manager component to it then reference that manager from anywhere. Seems okay (though there are numerous problems with this particularly when it comes to changing scenes) however the big problem is how to reference that manager from your components?

The method I was using was in the Awake() I would use GameObject.FindObjectOfType(); then cache the result and use it. Fair enough but this still means I have a dependency in this component on the Manager. It also makes Unit Testing very hard because there is no way to pass in a mock Manager. A stopgap solution was to use constructors to pass in the manager:

private MyManager _manager;
public MyClass(MyManager <span class="hiddenGrammarError" pre="">manager)
{
_manager</span> = manager;
}

void Awake()
{
if(_manager==null) _manager = GameObject.FindObjectOfType();
}

Still we have the dependency there however and my code was starting to get more and more complex. Plus Unity doesn’t really like you instantiating MonoBehaviours using constructors so I would continually get warnings in my tests. Far from ideal, so I decided to go looking for an alternative.

In the past I have worked a great deal with the Robotlegs framework and knew it was designed specifically to help with clear separation of use and help with managing dependencies for easy unit testing. So I wondered if anyone had ported Robotlegs to Unity. Well I was very happy to discover someone had and had done a good job of it in the form of Strange IoC.

Strange is an MVCS framework very similar to Robotlegs so if you know Robotlegs you should be swimming. I wont go into the details of MVCS, checkout the documentation or the Robotlegs documentation if you want to know more.

Using Strange I was able to replace the dependencies in my components by converting most my components into “Views” which respond by displaying data and then dispatching signals which the rest of the application picks up in Commands and and updates the Models or uses Services to communicate with the database. It immediately made my code much more testable by removing many of the dependencies between my components. At the same time I was able to convert many of my Models and other “Manager” like classes to implement Interfaces which made my code much more portable should I choose to change parts or reuse bits in future projects.

A disclaimer is that I have only used it for my menu systems and multiplayer services so far as thats what MVCS is ideally suited for and haven’t converted my spaghetti game logic over to it yet so cant comment on it just yet. My main worry is that it may slow down the enjoyment of rapid iteration and development. I will have to think carefully about that as I go forward.

Try Harder 2012

The above is what it looks like from a speakers position at the try { harder } conference. (click to embiggen).

I had indented to write this post a couple of weeks ago, immediately after the conference but STRATO denied that. But oh well, here it is anyways.

This year was the second annual try { harder } conference / coder retreat / brain explosion. I have spoken about try harder in the past but it really is a uniquely awesome event. Its a rather intimate affair  where 10-15 people getting together and sharing ideas and knowledge in the tranquil forests of Center Parks Nottingham.

The format was largely the same as last year. Everyone gave a talk on a topic of their choosing, some were technical talks such as David Arno‘s on C# (NCrunch, MVC & Mono) or Mattes Groeger‘s on developing iOS social games. Quite a few talks were on non-technical things such as David Wagner‘s talk on ‘the value of tinkering’ or Stray‘s talk on ‘Heuristics, collaboration special sauce’. Each talk was fascinating and the wide range of topics covered adds to the special feel of this event.

When deciding what to give my talk on I couldn’t make my mind up. I have been through a lot this year from launching my first business then having it fail to exploring a great many new tools and technologies to creating and launching my first mobile game. Not to mention all the cool things I have had the pleasure to work on at Playdemic. In the end it was a tweet from David Wagner who suggested that I talk about an exciting tool I had been experimenting around with lately; Adobe Monocle.

Adobe Monocle is the new profiler for flash and mobile content from Adobe and really is very nice. It currently still in pre-release and hence under NDA so I had to ask for permission before giving the talk on it. I haven’t had permission to blog about it get so if you want to find out more about it then check out this video that Thibault Imbert made a few months back:

I personally think it is a game changer for flash game makers. It makes development so much easier by giving better insights as to what is going on inside your game.

Try Harder is more about simply giving talks however. Each afternoon was set aside for pair programming sessions. Like last year we were given a deceptively simply problem then split off in pairs to try to solve that problem in a test-driven way. The kicker was that at the end of your hour with your parter you then must delete all your work and start again with the next person.

The problem we were given this year was “to find and score the palindromes with a length greater than 3 chars in a given string”. Seems simple, but when you get into it, it is deceptively complex. Because of the varied programming backgrounds of the attendees there were many different tools and technologies used.

Of the 6 different partners I had I solved the problem using: Javascript, Actionscript3, Haxe, C#, Java and Ruby using TextMate, Flash Builder, FlashDevelop, Visual Studio and IntelliJ. It was fascinating to see the multitude of ways to solving the same problem

Try Harder is held in the heart of the forests of Center Parks Nottingham. This adds to a sense of “getting away from it all” and I found it to be a really helped with concentrating on what we were doing. In many of the evenings I enjoyed walking around the forests or swimming in the pool or sampling David Wagner’s rather excellent scotch whisky that he brought with his all the way from Scotland (cheers Dave!)

   

So if you cant tell I had a great time at try { harder } this year. I think because I knew what to expect this time I could relax and enjoy the whole thing a little more. I also approached the event with a much more open mind which meant I could relax more and enjoy the format.

Bring on try { harder } 2013!

On Porting RobotLegs2 & SwiftSupenders2 to Haxe

I originally hoped that this post would be about my successful completion of a RobotLegs2 port to Haxe however something else has come up (more on that in a later post) so instead im just going to talk about the process and progress of the port thus far.

So although there is already an excellent RobotLegs 1 Haxe port out there by David Peek, I decided I would like to try to port the brand new Robot Legs 2 Framework  which offers a great many improvements over the original.

Rather than beginning the port from scratch I decided to use as3hx to take the legwork out of converting the AS3 code to Haxe code. To get the tool you must first checkout the library from its google code repo at: http://caffeine-hx.googlecode.com/svn/trunk/projects/as3hx/

Once downloaded its just a simple matter of compiling the source into a neko executable:

[codesyntax lang=”powershell” lines=”normal”]

haxe as3hx.hx

[/codesyntax]

Then you can run it with:

[codesyntax lang=”powershell” lines=”normal”]

neko as3hx.n

[/codesyntax]

To convert a AS3 project give it an input and output folder:

[codesyntax lang=”powershell” lines=”normal”]

neko as3hx.n -vector2array -uint2int robotlegs2 robotlegs2out

[/codesyntax]

In this case the input folder is the source download from the RobotLegs2 GitHub page.

It will start to convert but will get stuck:

[codesyntax lang=”powershell” lines=”normal”]

C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/api/IEventCommandMap.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/api/IEventCommandMap.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandExecutor.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/impl/EventCommandExecutor.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandFactory.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/impl/EventCommandFactory.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandMap.as
C:/Users/MikeC/Desktop/as3hx/robotlegs2out/robotlegs/bender/extensions/eventcommandmap/impl/EventCommandMap.hx
C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/EventCommandTrigger.as
Called from ? line 1
Called from Run.hx line 66
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 55
Called from Run.hx line 38
Called from C:Motion-TwinHaxe/std/neko/Lib.hx line 63
Called from Run.hx line 29
Called from as3hx/Parser.hx line 117
Called from as3hx/Parser.hx line 131
Called from as3hx/Parser.hx line 488
Called from as3hx/Parser.hx line 415
Called from as3hx/Parser.hx line 589
Called from as3hx/Parser.hx line 794
Called from as3hx/Parser.hx line 744
Called from as3hx/Parser.hx line 919
Called from as3hx/Parser.hx line 964
Called from as3hx/Parser.hx line 1106
Called from as3hx/Parser.hx line 1016
Called from as3hx/Parser.hx line 1075
Called from as3hx/Parser.hx line 1179
Called from as3hx/Parser.hx line 330
Called from as3hx/Parser.hx line 1003
Uncaught exception - In C:/Users/MikeC/Desktop/as3hx/robotlegs2/src/robotlegs/bender/extensions/eventCommandMap/impl/Eve
ntCommandTrigger.as(75) : Unexpected .

[/codesyntax]

It seems like as3hx is getting confused around this line in the AS3 source:

[codesyntax lang=”actionscript” lines=”normal”]

if (describeType(mapping.commandClass).factory.method.(@name == "execute").length() == 0)
				throw new Error("Command Class must expose an execute method");

[/codesyntax]

It looks like a bit of E4X is confusing the script. To solve this sort of problem I made a note of the location and file and just commented the offending line out. This allows as3hx to get past that particular snag. After going through this process a few times the project should be fully converted.

From there I setup a project in FlashDevelop and tried to compile. After fixing a few things that as3hx couldnt solve I came accross a rather major stumbling block.

RobotLegs2 unlike RL1 has a strong dependency on the dependency injection container SwiftSuspenders. So to get RL to compile I first need to port SwiftSupenders2.

So I repeated the process above but for SwiftSuspenders. Eventually this left me with a whole load of broken unit tests. Till Schneidereit the (rather splendid) author of SwiftSuspenders wrote a great number of unit tests for the library, which is one of the reasons why its so excellent. So I knew that to achieve a proper port all I need do is pass all those tests and I can then be confident that the code is solid.

After a few evenings of toil I managed to get 50 tests to pass in the Flash target. This is quite abit shy of the 160+ tests in the original AS3 version of the library, however a great many of those tests are not relevant to Haxe such as ArrayCollection tests, XML tests and DescribeType tests. I also decided for now to remove all of the event dispatching (and thus their tests) code from the library for now due to their dependency on the Flash platform. Despite this I think the 50 tests that do pass are probably representative of the core functionality of the library.

With the Flash target passing I indented to then move onto passing the tests in the other targets (JS, C++, php etc). I was hoping that with the flash part passing that they would all pass considering that im using the inbuilt haxe reflection methods not any platform specific reflection, but alas this was not to be the case. Starting with the JS target I started to get alot of errors on some of the basic Injector tests. After some digging in the compiled JS source I traced it back to an issue in the Meta Data generation for the @Inject tag on the JS target.

Unfortunately, I have run out of time on this little side project for now so am going to have to park it. I have uploaded the progress thus far to GitHub should anyone else wish to take up the mantle on the port:

https://github.com/mikecann/SwiftSuspendersHx
https://github.com/mikecann/RobotLegs2Hx

I had indented, once everything was passing, was to do a branch of the project and incorporate some features that only the Haxe language can support. Features such as proper generics and macros would bring some added awesome.