Flixel ported to Unity

This weekend at GDC I was lucky enough to show my port of Flixel into Unity to Adam “Atomic” Saltsman (creator of Flixel and Canabalt). He was excited about it and encouraged me to post it online - so here it is. I did the port as a way of learning both Flixel and Unity and as potential platforms for a 2D platformer that runs on the iPhone. Yes, that’s right, this is a way to get your Flixel game on the iPhone, Wii or soon iPad, Android, Xbox 360, and PS3 :)




Before you get your hopes up though, lets talk about how I did the port and what works and what doesn’t work.

Flixel is written in ActionScript, which is a variant of Javascript. Unity uses a slightly different variant of Javascript for its game logic (you can also use C# or Boo). Porting Flixel’s source code to run in Unity was a matter of changing some syntax, adding type declarations in a bunch of places, and swapping out Flash API for Unity API calls. Since Unity doesn’t really have native 2D sprites I used Brady Wright’s SpriteManager with a few modifications to stand in for Flash sprites. The end result is that the whole thing runs with a single texture, 1 draw call and about 500 polygons.

What Works

The Flixel demo game, Mode, is playable. I implemented some slightly odd iPhone controls: tilt to move, tap the left side of the screen to jump and the right side to fire. You can try it with normal keyboard controls right now in your web browser by clicking here. The scoring/death logic is disabled for testing purposes. You can compare to the original Flash version here.

What Doesn’t Work

In order to get it up and running quickly I chopped out big chunks of code for audio, text, menus, intro logo, shaking the screen, etc. In order to get the polygon count low I pre-composite the whole level into the texture atlas (it all fits into a 1024x1024 texture). This means that the start up time is quite slow and dynamic levels would be awkward. The most glaring issue is speed, so lets talk about that next.

Performance

When I initially got the port working (over a weekend in October 2009) it ran pretty slowly. I did a bunch of work to put everything into a single texture atlas which helped, but it still felt sluggish, so I set it aside and waited for computers to get faster. Now in the latest version of Unity iPhone 1.6 it runs much faster. It currently runs at about 25-30 fps on an iPhone 3GS. This is certainly playable, but way slower than it should be given the low level of complexity. I don’t have the Pro version of Unity which includes a real profiler, so I’m stuck with this internal profiler report:

iPod Touch Profile

iPhone Unity internal profiler stats:
cpu-player> min: 42.1 max: 63.0 avg: 48.2
cpu-ogles-drv> min: 0.4 max: 2.0 avg: 0.5
cpu-present> min: 0.9 max: 3.0 avg: 1.1
frametime> min: 44.0 max: 69.3 avg: 51.4
draw-call #> min: 1 max: 1 avg: 1 | batched: 0
tris #> min: 400 max: 400 avg: 400 | batched: 0
verts #> min: 800 max: 800 avg: 800 | batched: 0
player-detail> physx: 0.8 animation: 0.0 culling 0.2 skinning: 0.0 batching: 0.0 render: 0.8 fixed-update-count: 2 .. 4
mono-scripts> update: 46.2 fixedUpdate: 0.0 coroutines: 0.0
mono-memory> used heap: 1130496 allocated heap: 7524352 max number of collections: 0 collection total duration: 0.0


iPhone 3GS Profile

iPhone Unity internal profiler stats:
cpu-player> min: 18.0 max: 21.3 avg: 20.5
cpu-ogles-drv> min: 0.4 max: 1.0 avg: 0.5
cpu-present> min: 1.4 max: 4.6 avg: 1.9
frametime> min: 30.3 max: 36.2 avg: 33.3
draw-call #> min: 1 max: 1 avg: 1 | batched: 0
tris #> min: 440 max: 440 avg: 440 | batched: 0
verts #> min: 880 max: 880 avg: 880 | batched: 0
player-detail> physx: 0.3 animation: 0.0 culling 0.1 skinning: 0.0 batching: 0.0 render: 0.7 fixed-update-count: 1 .. 2
mono-scripts> update: 19.1 fixedUpdate: 0.0 coroutines: 0.0
mono-memory> used heap: 684032 allocated heap: 7524352 max number of collections: 0 collection total duration: 0.0


As you can see graphics are not the problem. The vast majority of time is spent in the mono-scripts update phase. This makes sense because I have just one Unity GameObject with a single Update function that deals with all of the Flixel sprites. (I hacked SpriteManager so it doesn’t create a separate GameObject for each sprite.)

Without a real source-level profiler I’m stuck doing divide-and-conquer or manual profiling. I have not spent the time to hunker down and do this and I’m not sure I have the Unity-specific expertise to do it well. What I’d rather do, is post the source for this online and get some help from the community - especially from someone with more experience with Unity performance optimization. That’s where you, Dear Reader, come into this story as a hero :)

You can download the source to Flixel ported to Unity iPhone from Github.

If you manage to make any improvements let me know. I’m sure there are plenty of folks who would love to port their Flixel games to the iPhone this way.

Cheers,
-josh