Sunday, 23 December 2012

From Corona & Lua to Unity & C# - Part 1

For those of you who have followed my blog for a while you will see that title and think: "Changed his mind again!!", and you'll be right. I was taking my last blog a little further and experimenting with Cocos2D and Kobold2D. Both proved excellent and Steffen Itterheim's book Learning Cocos2D gave me a good grounding in both.

I think the thing that I started to get disheartened by was as soon as I finished the book Steffen announced he would be transitioning from Kobold2D to KoboldTouch. While that is no great shakes in that I hadn't really started I thought to myself given that I was looking to transition did I want to go with something that was closer to my core, .Net. The rationale behind this is that although I have released apps in Lua and Objective-C they took longer than I wanted as I got used to the syntax and idiosyncrasies of each.

Like a lot of people I am a follower of Matt Rix (@mattrix of Trainyard fame) who had spoken of a 2D code centric rendering framework he had been working on called Futile for Unity. I was intrigued by this as I had wanted to dabble with Unity for some time but had been put off by the plethora of buttons and options as well as a third axis I hadn't even contemplated :).

To start off with I watched the videos on Matt's website which gave me a decent insight into what it was capable of. I'll be honest I had to watch them each about three times to break through my mental block of Unity but what was becoming clear is that Unity only forms about 20% of this approach. MonoDevelop would become my friend and that was the point, code centric. So I thought I would take the plunge. First off I followed the steps on Matt's Github page:

How to open the project

  • Grab the project from github and put it somewhere - For the lazy, here's a zip of the whole repo
  • Make sure you have Unity installed
  • Go into BananaDemoProject/Assets/Scenes and open FutileDemoScene.unity
How to make sure you're running it at the right resolution
  • Go to File -> Build Settings -> Click "PC and Mac Standalone" -> Click "Switch Platform" (if it's already greyed out, you're good)
  • On the Build Settings page, choose Player Settings
  • Under Resolution and Presentation, set the size to 960x640 (or 480x320, or 1024x768)
  • Go to the "Game" tab
  • In the top left dropdown, choose your resolution (instead of "Free aspect")
  • In the top right, make sure "Maximize on Play" is enabled.

Having followed these steps and watched the video while playing around with the code I personally started feeling quite comfortable with the concepts. In particular the third video of just over an hour really helped cement my understanding

For the purposes of clarity I am using Unity 3.5 (not 4.0) and took advantage of Unity's April 2012 give away on iOS basic. The latter is obviously required for publication and distribution but the free one to PC and Mac can still be designed to and just change the player settings to 480 x 320 for example.

Like most things when you start with something new I need a focus to adapt to my own requirements. This is the only way I find I can learn is to play around with things and try and try again. What I thought I would do is document my day to day transition from Corona and Lua to Unity and C# which the latter seems a popular option. For me the code for Astavoid was actually very similar to Matt's BananaDemoProject so unless I make paricular reference to code I would strongly recommend having a nose around there.

What should also be noted is I'm a hobbyist Indie (not sure that even exists!!) but means I can only afford at best 4 hours a day in the week and perhaps a little more at weekends. So my definition of a day is actually quite short so your progress could be even quicker.

I thought writing a new game would probably be too challenging so instead I focused on porting Astavoid from Corona SDK and Lua to Futile/Unity and C#.

For those of you who haven't had the pleasure of playing my first game its a very straightforward space evasion game that is available free on the App store. Why not download it for reference, its free after all :).

Day 1
First and foremost I didn't want the same hassle I had when I first wrote Astavoid concerning fonts. On the iOS and Android devices handle paths differently so I followed the lead of Matt's video tutorial and purchased Glyphdesigner. Really not sure why I didn't do this the first time but is an excellent tool to ensure compatibility of fonts across devices. Furthermore, I could include this font image within my textures / atlases. The font mapping file (.txt) also needs to be included within your resource folder in Unity.

The next tool to your arsenal is the excellent Texturepacker this proved to be a lifesaver when I first wrote the game with Corona and is equally as effective for Unity. The only difference being that it outputs a text file rather than a Lua file but the transition is seamless. I couldn't recommend the product enough and, again, if you watch the video's on Matt's page this is what he is using.

So with my font and background graphic within my texture I was now in a position to create my first scene. Nothing too strenuous as really I was dealing with 5 text objects and a background image. Needless to say this was very straightforward. I created my Main.cs (C# script) which I dragged onto my Futile object. Then I open MonoDevelop and put the appropriate logic into the Start method of the Main class. Ensuring of course to add the labels and sprites as children of the scene (AddChild(object) so that they show up. Missed this one a few times :)

The result was a fair reflection of the original title page, other than the fact it didn't do anything at this stage:

Day 2
Buoyed on by my first day's achievements, and when I say day I only mean about 2 hours, I set about bringing the asteroids into my texture and look to provide some movement.

I started to organise my code a little and create an FContainer (or scene) to split up the various screens I was going to need. So I created a TitlePage and a GamePage.

Within my Start method on the Main class I did a call to the title page which in turn did a call to my game page. To conclude the navigation my game page, via the pause button, would return me to the title page. This simple transition meant two classes representing the scene, and my Main class with its singleton instance controlling which one to display. At this point I was calling the scene methods directly and not by button touch.

With this now working well I revisited Texturepacker and dug out my asteroid artwork and added it to my texture. I then re-published and added my new texture to the Unity project.

There is no specific physics engine built into Futile specifically aimed at 2D at the time of writing. Unity of course contains the powerful NVIDIA® PhysX engine but the whole purpose of using Futile was to make my life easier. So on day 2 of my adventure I focused specifically on animation

Thankfully Matt has considered animation / tweening and incorporated Prime31's GoKit library into Futile which makes animating the Futile objects very easy. All I had to do is create a base class for my asteroid object and derive from this for my different asteroid types to give the perception of depth. I then used the GoKit library to tween these asteroid objects relative to their size and depth and then cull when off screen.

Day 3
The aim of day 3 was to hook up the title buttons via touch. Again this is straightforward enough through Futile's touch manager. By reviewing the code of the Banana demo project it is straight forward to see how the touch events via a signal release and then the relevant method to call. From these methods I was then calling my instance to call the scenes on the stack. This makes traversing the scenes easy.

An additional update was to apply the distance counter to the update method of my scene. My game by this point is running at a very smooth 60fps which exceeds the 30fps I was running at with Corona. Not a limitation of Corona I should say but mine in writing efficient objects and caching correctly. I remember probably spending about 2 months on this subject alone optimising my lua code and get it done in a day with Futile / Unity! I use a modulus to only update the counter every other second (or update) to keep the distance score a little more realistic.

Day 4
With the principles of the scene setup I turned my focus to the rocket sprite. Its worth noting at this point that I am using existing assets that may need to be modified dependent on what control mechanism I go for.

With this in mind I created another texture atlas in texturepacker for my rocket and therefore not over bloating my other atlas. This is in part because I made the decision to add in my space background to the original atlas as it would be used on multiple scenes.

I also revisited my asteroid code and inherited more from my base class to streamline my code and adhere to the DRY approach of Don't Repeat Yourself. With this refactoring done I created a fourth size of asteroid to run in the background as a form of parallax asteroid belt.

Day 5
This was a big update day! The first was tackling how to handle storing of data within Unity. I learnt that this was done with key value pairs that could have certain types attributed to them such as strings, floats, etc. I looked at using the PlayerPrefs class to store information for my best score but thought this needed to be extended a little to create my local leaderboard. I found something that I could base my class on here and adapted appropriately. Having returned all scores to my list they are sorted and then limited for my purposes

As well as adding in my best score logic and leaderboard I ensured that all buttons triggered events. This meant converting the FLabel to an FButton and in my case adding a transparent image behind the text for the hit state.

Day 6
To mimic the Astavoid app that is already in existence I applied the GoKit tween logic to my Flabels and FButtons for the transitions between pages / scenes. The transition effect is done within the constructor of the scenes FContainer class while I wrote a specific TransitionOut() method to handle the text and image objects movements back to the start. This works really well with smooth movement and some nice effects such as easing in and bouncing.

Day 7
Android was definitely an area that took a lot of development time up with the original release of Astavoid. The fragmented screen resolutions took some thinking and some adjustment in the code. While iOS isn't there yet its certainly heading in that direction which is why I was relieved to see that Matt had given it some consideration within Futile.

To tackle this I revisited by trusty tools of Texturepacker and Glyphdesigner and increase the size to be scaled appropriately for retina screens. I looked into Matt's Banana project to get a feel for the text sizes he used for this project and played around with my ratios as I had three different text sizes to his one. From this I setup the AutoSD feature of Texturepacker which works to the principle of largest size and then scales down the different ratios as are relevant.

Obviously we would work to the Retina x2 (or even x4) normally but I haven't had a chance to go back to the drawing board on the graphics so just want to work out the logic for the resolution switching.Highly recommend if you are starting out you work to the largest resolution. There are lots of guides out there but this one is pretty useful.

The result being that I have simple parameters set as part of the Futile init that determines the width that is relevant to that resolution, the scale factor and the suffix of the atlas file to pull in. For debugging purposes the scale ratio and the file being used is echoed to the Unity console so you can make sure you are scaling correctly.

A pretty productive first week I think you agree. I have learnt loads in this time and while have lots to learn I feel confident of getting this simple game ported.

Thing to note is that Futile is in its infancy at the moment so documentation is pretty light. However I found Matt Rix (@Mattrix) and Whitaker Trebella (@wtrebella) of Polymer fame, to be incredibly helpful with my annoying question. I can also help with the basics and can be found at MyGamingProject @gameproject10k where I will be happy to help. Part 2 can be found here covering Collision Detection, Multi-touch and sound will be tackled. Another busy week :)


DirtyHarry said...

Hello there, this is MagnetiCat ;)

This is an extremely useful post for all indies having to deal with similar time constraints.

I am using both Cocos2D and Corona, currently, for my project. I have been playing a bit with Unity, but the performance I get is quite horrible compared to both other platforms.

How does Astavoid made with Unity behave on device? What kind of loading times are you experiencing?


mygamingproject said...

Hi MagnetiCat

Performance hasn't been a problem to me at all so far but i only ever have about 40 gameobjects at one time. In fact I am running at 60fps rather than 30 because my code is more efficient.

Lack of physics into Futile is killing me at the moment

DirtyHarry said...

Yeah, it is difficult for a system like Futile to reach the same maturity of something like Corona. But to be honest I used it only in a small test for a platform, and the performance was not very good - especially loading times on devices. I will need to take another peek at it ;)

Darkstar said...

Thank you very much for sharing your experience and for pointing out the resources which helped you progress in your project. Great post !

Unknown said...

I have corona, my sub runs out next year (May 2014). I'm making the ramp up on unity, but will keep corona maybe perhaps for other things. Only the last 4 weeks did I start hitting up C# tutorials and in fact this ramped me quick on C# (it's geared for .net development but the C# core is in there)

C Sharp for absolute beginners

Anyway, that got me up on C#, now I'm playing with Unity.

Futile + Physics : Anything good yet? I have a game where I need physics, collisions etc. Have you found anything that works yet? I haven't built to my device or anything, and I still have a subscription to Corona so I have time :)

I too have about 3 to 4 hours a day max (most of the time it's like 2.5 maybe) as I'm married, have a son (he's year and half old) and expecting a girl in August - my time is almost exclusively at night. I know the feeling of time crunch :)


mygamingproject said...

Hi Nick

I'll be finishing the third part of this with my findings as have gone through about 3 iterations of collision detection alone. Depressingly it now turns out to only be a line of code but that wasnt the case 6 months ago.

Futile's physics branch is soon to be merged to master ( and have not experimented with that at the moment but know others have.

However, the main physics and particle systems within Unity are incredibly powerful but in the end and for the sake of this article steered away from them.

Post a comment