image/svg+xml
zubspace
between code and design

Ludum Dare 44

A post-mortem.

What an exciting time! I've actually managed to complete a 'simple' game called Life Cycle within 48 hours in the Ludum Dare game jam! Here's the page on Ludum Dare and you can play it in your browser here. It was the first time I participated and this year's topic was Your life is currency. As I promised in my last post, here's a 2.5 minute timelapse of me creating the game over those 2 days:

I was busy preparing for the event already two weeks earlier within my vacations and learned a lot before and during the event, which I want to share with you.

Here's a roundup:

TL;DR

  • I love Unity tilemaps and level design.
  • Unity physics are a mixed bag of awesome and tears.
  • Never ever use an escape key in a game.
  • I don't enjoy streaming.

Releases

WebGL Release (Runs in your browser)

Windows Release (Download, 20MB)

Linux Release (Download, 21MB)

Source Code on Github

Game idea

A screenshot of the game Life Cycle.
A normal day in the life of box man.

I closely followed the possible themes you could vote upon in the week before the event. I tried to think of a small game for some themes, which I tought were interesting, and "Life is currency" clearly stood out. I was glad to find out that this theme was chosen, because it gave me a headstart in the actual event. Already in the week before I thought about using a dead player corpse to get further in a level and I'm really happy with the result. Initially you could only jump on dead players. Then I thought that carrying them around would be fun, but I won't spoil, why that is useful. There are even more use cases and Ringo also has ideas of his own.

Many possible themes were very similar and you could probably cover most of them with the same type of game. Because of that, there were 2 game types I considered: a space / planet game or a platformer. The problem was, that I have never really made a platformer game before. That's why I carefully studied the approach and made a small prototype. I'm happy that I could build upon that knowledge during the event.

I took a bit of inspiration from 3 related games: Limbo, Hollow Knight, Super Meat Boy.

The are all excellent. I've never played Super Meat Boy though, but I've read enough about it to know that it is both ridiculously hard and awesome.

Things which worked

Unity tilemaps and the tile palette are great. A tool to create levels in a very short time. I've never used them before, but I'm grateful to know how to use them now. You can use multiple tilemaps together. One with and one without collisions for example.

Creating a level from 10 in ten minutes with a tilemap.
A level in 10 minutes from scratch. Not that bad!

Focusing on level design instead of pretty fluff. Yes, the basic tiles and the missing backgrounds are an eye sore. I hear your complaints. But I am actually glad that I focused more on level design instead. Be happy, I spared you of more ugly programmer art..

Many levels. I'm always sad when I find a good game which ends to soon. I actually wanted to go for 16 levels and 4 acts first and had everything layed out in the level selection screen for that content. But time was working against me.

Level unlocking. I love this. It just feels good to unlock stuff.

Unity GUI. I think I finally grok the anchoring system! (Yeah, took me a while...) A bit of practice does wonders. The only thing I need to get into now are scroll views and flow layouts. Oh Unity, why can't you just be easy and straighforward...

PlayerPrefs. From now on I will use PlayerPrefs for everything! No kidding, I love that simple system. Eat my shorts JSON!

Things which did not work that well

Streaming on twitch with OBS. This was a huge distraction and time sink. I created custom splash screens for OBS, for short and long breaks for example. Additionally I built CodeClock with Unity. A cool widget with adjustable text inputs made in Unity

A screenshot of CodeClock. A widget for the OBS streaming application.
CodeClock is the best tool which I'll never need again.

I've never streamed before and thought, that this was a good time to try, but I came to the conclusion, that it ain't worth it. Programming and thinking and at the same time telling your viewers what's going on in your mind is too hard for me. I also alienated many potential viewers because I used my main language (Swiss German) and therefore never reached more than 3 viewers at the same time. Sorry! But talking english would have easily doubled my mental workload.

Keeping unity defaults. The ugly font is Arial which is the only font included in Unity by default. Well, next time I need to look for free fonts beforehand. Some of you maybe even recognize the default blue clear color. Oh dear, I should be punished for that act of lazyness.

Character controller. I'm actually proud that I've implemented a fully working kinematic character in Unity from scratch. But it's a ton of work and it took me quite a while to get right. But I believe that using a dynamic rigidbody would be more limiting. I currently have no idea how to improve this. Please tell me if you do.

Debug view of the character controller casting rays.
Debug view of the character controller casting rays.

Expecting a kinamic rigidbody (player) to interact properly with dynamic ones (dead players). Carrying dead bodies around was essential for some levels I imagined, but Unity gave me a hard time...

Kinematic rigidbody cannot carry a dynamic one properly.
Nope. That is not how it should be...

In my first workaround I tried to use physic springs and stuff. Bad idea! It's just too complex to get right. Finally I had to hack around it, by converting the dead body to a kinematic one when the player was below it. And then I moved it along with the player. Consequently I needed to check both objects, player and carried one, for collisions and detach conditions together as one. Oh dear, what a hack...

Smooth movement. Many of the players complained about the movement. Next time I will probably not use acceleration. Would be easier and result in a more responsive experience. The other thing I had problems with was the Update / FixedUpdate split. I had to re-position the kinematic player inside of FixedUpdate to interact properly with the dead ones having dynamic rigidbodies. But this leads to unsmooth movement, because there will often be multiple Update calls with the same position. To fix that, I simply delayed and lerped the sprite inside of Update to the real position. But that introduces artificial lag... Oh boy Unity, you're giving me headaches... I need to figure out how to do this right...

AreaEffector2D on the conveyors. I needed this to move around the dead players on the conveyors. But there was a confusing bug. Sometimes a dead dynamic rigidbody would suddenly ignore the effector for no reason. Ugly workaround: Each second I set the trigger flag in the collider to false once. You can see the effect when you look closely ingame, because dead players on conveyors bump up a little bit. May god have mercy upon my soul...

I'll never use an escape key again. Don't do it if you plan to release the game for the web or on mobile. I used it to return from inside the level to the level selection and from there to the start screen. But d'oh! The browser closes the fullscreen view, too! And on desktop the key is non-obvious and confusing. And where's the key on mobile phones? In case you use different keys for desktop and other build targets someone will surely be confused by this.

Things I had no time for

These were all things I thought about before Ludum Dare. I will try to focus on these more next time:

  • Online Highscores
  • (Dynamic) Music
  • Ambient sounds
  • Nice graphics
  • Fluids
  • Light and shadow
  • Deeper ingame story

Funny stuff

Spawning a saw on a spawn point fills the room up with dead players.
Never put a saw on a spawn point. I'm glad that this level did not make it.