This article is a post-mortem of the development of Urban Mage, our second released game on Steam which had its origin in Ludum Dare #37 over 5 years ago, and was just released yesterday, on March 8th, 2022.

If you want to skip all the details and just look at the data click here, showing wishlists, sales and analytics for all of our games.

For completeness, we currently have two released games and one game in progress

  • Hell Loop ($2.99) - Released in Q4 2020, built in Unity.
  • Urban Mage ($2.99) - Released in Q1 2022, built in Unreal Engine 4.
  • BITGUN - Planned release in Q2 2022, built in Godot and Rust.

What follows is a little history and a long series of very bad decisions. Author: @darthdeus.

Shadows & Ludum Dare #37

The journey begins over 5 years ago (2016) in Ludum Dare #37 with the theme One Room. I had just recently watched Sebastian Lague's amazing series on how to make a 2D platformer (which I definitely recommend to anyone even if you're not using Unity), and I felt like this was the perfect opportunity to apply it. I didn't particularly care about the theme, but One Room was easy enough to interpret as "one level", which was a perfect way of keeping the scope low.

Back then I thought having tight platformer controls was the most important thing, and was more than happy to stick to a single gray cube jumping on white platforms.

shadows-platformer

I've played a lot of platformers back then and really disliked when the controls were too lose or didn't respond immediately. The fact that my platformer had tight and exact controls was more important than anything else.

Because my university organized a let's do Ludum Dare all together kind of event I got a rare chance to show the game to other people very early and got some feedback. One of it was from someone who didn't really play platformers and said "It would be cool if you could only control it with your mouse, using both keyboard and mouse seems complicated." (The controls were WSAD to move, mouse to aim/shoot.)

shadows-mouse-controls

Of course me being the inexperienced noob that I was (and still am) I had to satisfy my only customer and immediately began re-designing my game. WSAD became "hold RMB" and Space-to-jump became "press LMB". It worked surprisingly well, but because I was terrible at game design I thought "I'll keep this control scheme for noobs and still allow for keyboard controls". While this worked for movement, it used up both keyboard and mouse for movement, which made it very difficult to add any kind of combat.

Lucky for me the mouse has three buttons, and I've always liked Harry Potter, and so the idea of "press mouse wheel to switch to shadow form" was born. When in shadowform the platformer controls would be mostly disabled and the player could fly around the level to the last location where RMB was pressed, and use LMB to shoot.

shadows-shadowform

This worked surprisingly well, although the game was no longer the amazing platformer I had imagined. Obviously the solution was to keep both, and turn this into a mouse based platformer where you also fly in shadowform kind of game. The key mechanic being that if you get hit in shadowform you lose it for a few seconds being locked into platforming, but if you get hit outside of shadowform you die. This seemed almost smart, except that the platforming was now basically useless as there was no reason to actively use it. But I didn't care (or even realize it) - it was in the game, and the game was fun.

Shadows Gameplay LD#37

In the end the game receveied quite positive feedback on Ludum Dare, and even got a little coverage on Youtube, which felt like a huge achievement at the time, and Jupi saying "this is quite cool" as she plays the game was a huge source of motivation for quite a while. It might seem like a small thing, but at the time this was probably the first time I had a random person discover something I made and thought it was cool.

Video below, gameplay starts at around 19 minutes.

Platformer -> Top Down -> 3D

Some time passed and the idea of taking the Ludum Dare version of Shadows and extending it to a full Steam game was born. Unfortunately, getting the 2016 version of Shadows to work in Unity in 2020 was not as easy as just opening the project. At this point my wife decided to join me in making the game, and decided to re-build the project from scratch. Again, starting with Sebastian Lague's platformer tutorial (no affiliation, I just genuinely think this is the best platformer tutorial out there).

shadows-remake-2d.png

At this point I started to realize that graphics were important and got the idea that "lighting makes stuff look good for free". This quickly lead to "top down is easier to make look good than platformers", which quickly became "3D geometric shapes look better than 2D", and suddenly we had a 3D game.

shadows-3d-simple.png

This also quickly became "why restrict ourselves to geometric shapes when there's so many assets and Mixamo".

shadows-realistic-characters.png

But because "lighting makes 3D games look good for free" we also had to double down on that and started using lightmapping, which lead down a big rabbit hole of CPU vs GPU Lightmapper in Unity, as well as using an alternative lightmapper called Bakery.

shadows-lightmapping.png

Now that we have lightmapping we should capitalize on that, so clearly the next step was to add more detailed models as geometric shapes really don't cut it anymore. We also added textures and materials, and spent a lot of time on animations. This included things like "when an NPC opens a door their hand should be placed on the door handle exactly", because obviously that's what makes a game good, right?

shadows-textures.png

Next up, it seemed that designing levels by hand is complicated and takes a lot of work. Lucky for me, I did my bachelor thesis on using PCG for automated difficulty balancing, so the arrogance didn't stop there, and I was sure I could also implement PCG for big complicated levels fast enough compared to designing them by hand.

Many iterations later, we had a pretty decent game with animated characters, non-trivial AI, PCG for bigger levels, and lots of other stuff. We did use a lot of assets, including both models and code. Ultimately I think we ended up getting most of the popular assets, including things like Odin for building custom UI for our level generator

Because a lot of my time in university was also spent on performance it became my mission to make everything work for big levels. It took a lot of effort, but we got to a point where the levels were pretty big with hundreds of NPCs walking around doing stuff. Somehow I thought thousands of NPCs all doing pathfinding and complicated AI would be possible, but it was not.

shadows-big-level.png

Throughout all this we still didn't really have a game. We had a sandbox simulation where each NPC was supposed to have their own personality, their own team designation, team members, a set of personal goals and a schedule they'd adhere to. They would also go on meetings with their team members, and the idea was that if one team member didn't show up at a meeting they could check their workspace, and if they couldn't find them they would slowly start becoming more suspicious. They would also use phones to call other places on the map to relay information to other NPcs. The player would have to be strategic in how they eliminate everyone to not arise too much suspicion.

If this sounds like a huge pile of over-complicated junk with no clear game design, it definitely was. My arrogance and megalomania knew no bounds. Having studied computer science I thought I could solve every technical problem myself, and didn't even think twice about things like "keep the scope small". I would actually think that those limitations of "doing AAA stuff takes too long" would only apply to other people but not me, I could get it done fast ... right?

Among other things, decals are also clearly important, and one can't have blood that disappears after a while, which lead down a big rabbit hole of "painting blood on textures" (trying the Paint in 3D asset).

Maybe the most surprising part to us was how much these things affect Unity's Editor performance. At first it might seem obvious, more code means slower compile times right? Without going into too much depth, even with our somewhat small game - built by two people part time for a few months - we got to a point where it would easily take a minute for the editor to reload when changing a single line of code. We took all the steps including moving all the assets into Plugins, and even reported some performance issues to Unity, which actually got fixed after pushing it on the forums really hard for a few weeks, but even with all that the iteration time was just unbearably slow.

This became problematic even with things like developing our own tools with Odin, where we would abandon sometimes even partly-implemented ideas just because the workflow with them was infuriatingly slow (due to the editor domain reloads).

As you can probably guess our game was quickly becoming a gigantic pile of crap and development speed crawled to a halt. At this point we've been at it for around 5 months while I was working a full time job and my wife was taking care of our first toddler. This was also the time where I had a brilliant idea of "Unreal Engine 4 looks cool, let's just take a look", which quickly turned into "I'll just try rewriting it in UE4 real quick to see if that'd work better". This was a desperate attempt to fix the workflow problems due to slow editor reloads, while also getting "better graphics for free".

At this point shadows was already beyond 1000 commits, but that didn't stop me from thinking I could rewrite it in a different engine because "I know better now".

1000-commits.png

After about a week we got some gameplay going, and found one big surprise. Compared to Unity's editor, UE4 is incredibly fast. At least when sticking only to blueprints, we had basically zero iteration time when changing something to pressing play, as compared to sometimes waiting 20 seconds after changing a prefab for Unity to "recover" when exiting the prefab scene. Just to clarify, this is on a 12 core 64GB RAM high end desktop.

It could be argued that this was because we just had much less code in UE4, but when we later started working on Urban Mage], which grew quite large in terms of code, we didn't run into any performance issues in the editor.

Ludum Dare #47 and First Steam Release

Lucky for us another Ludum Dare was just about to begin, and wanting to take a break I participated. The theme was Stuck in a Loop, and me being me I didn't care about the theme one bit. I just wanted to make a game. Again, I started making a platformer, again with Sebastian Lague's platformer tutorial. I actually took a tiny detour and tried doing this in Godot, but quickly realized that if I want to make a game in a few hours it's probably not a good idea to switch engines. Luckily I managed to stick to Unity, and one day later after changing the game idea from a platformer to tower defense I had a "fully functional" and fun game. To make it fit the theme I made it about sinners trying to escape from hell, and called it "Hell Loop".

Being amazed by the new found productivity we decided to cut our losses and switch to Hell Loop and make it into a proper game that could be released on Steam. We tried very hard to keep the game as small as possible, but as the codebase grew we started running into editor performance issues again. They weren't as bad as in the case of Shadows, but still, waiting for 10-20 seconds for a tiny 2D platformer to load felt like unnecessary pain.

In the end, we did manage to finish and release Hell Loop on Steam just in time for Christmas (released around 2am on December 24th). We didn't do almost any marketing other than a few posts on twitter and creating a Discord server, but over all we had no press coverage, no YouTube coverage, and no strong fanbase other than a few friends. This is what our release traffic looked like (more data at the end of the blog post):

hell-loop-traffic

Having finished the game felt amazing, but at least for me the most amazing part was that I could finally close Unity and move on. The long compile times really made me hate developing the game.

Bevy and Rust?

It took only a few days of recovery after releasing Hell Loop, but since I've been anxiously waiting to try something else, I quickly jumped onto building the next game using Bevy and Rust. Having been programming for quite a while, and having tried Rust before, I was quite happy to try a lower level approach similar to MonoGame, and just having more control over everything.

We went back to simple pixel art and simple 2D platformer - again following the same tutorial I've already mentioned quite a few times.

bevy-graphics

But since Bevy is pretty low level, a lot of stuff needed to be written from scratch, including a custom auto-tile for destructible terrain, and our own level generator:

A lot of problems were fixed and figured out, but some core problems remained unanswered, such as how to load different levels and scenes and how to handle loading assets in a particular order. These problems were ultimately all solvable in some way, but we wanted to build something that could be finished and released in just a few months, and spending a few more months working around technical problems which utliamtely didn't make the game any better felt like a distraction not worth the time investment for us.

bevy-shadows bevy-shadows2

In the end, we decided it was just way too difficult to do everything we wanted, and ended up abandoning Bevy in favor of going back to Unity to re-build the same game, since we already forgot the pains from developing Hell Loop. (As a side note, we actually ended up using Rust again in our third game BITGUN, more on which later.)

Luckily it didn't take long and memories of terror from the loading cursor came back quickly, and ultimately we decided to give Unreal Engine 4 a proper try, since during our previous testing it was quite pleasant to work with. This is how Urban Mage was born.

Unreal Engine 4 and Urban Mage

I've always enjoyed playing Hitman and Assassin's Creed, and in general any form of third-person open world action game. UE4 seemed to have all the right answers to this, and since we're not afraid to use existing assets to prototype quickly it felt only appropriate to give it a go.

We quickly started going down the rabit hole of very complicated things like particle systems

This very quickly lead down the previous path of Shadows and we started introducing things like Behavior Trees and "complicated AI" where people would notice other people dying and go to a phone booth to call for help, which would call in police who would search for the player.

But in the words of a typical Apple presentation, "we didn't just stop there". We started introducing additional features like Photo Mode. We didn't implement all of this ourselves and used a lot of assets, so the development wasn't slowed by adding features on their own, but rather by increasing scope and no clear vision.

Probably the most ridiculous part of this whole thing was spending a huge amount of effort on walk/run animations and trying to have blending for animations in different directions, and looking into root motion. Just to clarify we had basically zero experience with animation or 3D other than what we've previously done on Shadows, and most of this has been just using animations and assets we bought and modifying them. All of this ended up being wasted effort since it didn't add anything to the game, and we didn't even realize that tight controls and "perfectly realistic animations" don't really go well together. A lot of time was spent watching tutorials on how to achieve AAA-level polish on these things instead of gameplay.

There's a lot of great assets that make it seem like all of this would be easy, but it just didn't occur to us how much work would be to tie all of this crap together.

Continuting with the "we didn't just stop there" we also started looking at mesh destruction which is natively supported in UE4. This again looked like "easy way to get a lot of game for free", but proved extremely difficult to work with when combined with physics. We didn't just want to disable collisions for the debris since that made things look very ugly, but having them enabled made everything extremely difficult to work with. This again became a big feature where we went from "everything is destructible" to "let's just scrap the feature completely".

Since until now we were using the demo scene from Synty Town Pack we again fell into the trap of "building levels is difficult". This lead to yet another insane detour of "what if we just used Houdini to combine all the assets we have into a procedurally generated city". We had no experience with Houdini but it seemed cool, and PCG was my thing, so naturally I thought "it can't be that hard".

urban-mage-houdini.jpg

Fortunately for us this is one place where we actually ran into technical difficulties way beyond what we could handle, as Houdini Engine for Unreal was extremely buggy for us and caused both parts (Houdini and Unreal) to both crash, and get out of sync when things in UE4 wouldn't sometimes update. It wasn't really something we could fix, so the whole idea of using Houdini was scrapped.

It didn't take long for us to realize that we've again created a huge monster that was impossible to finish, and we abandoned the project.

Steam Next Fest and Urban Mage Release Day

At this point our second daughter was born, I quit my fulltime job to "help with the kids", but quickly transitioned into "fulltime indie gamedev" and started working on our next game BITGUN, which is a story for a future blog post.

Fast forward a few months with Steam Next Fest around the corner and we were able to get both BITGUN and Urban Mage registered for the event. We didn't have much time to prepare the demos, and decided to heavily cut down on features to get something done.

Until now the story has been mostly really bad decisions and scope creep, but now comes the point where I think I've actually made a good decision. After getting BITGUN ready for Steam Next Fest we only had a few weeks for Urban Mage, and it was nowhere near ready, and so the decision to start over "from scratch" was made.

New Urban Mage wouldn't be a 3rd person stealth action, but rather simple hidden object "click to kill" style God game where the only mechanic is to click on interactible objects to get points. The only thing we re-used were the NPCs that walk around and sometimes do things, and our assets.

At this point I've already implemented the raycast-based platformer controller at least 5 times in different engines, so if there was one thing I knew how to do it was how to make the mouse click on things very quickly.

click kill

Other than clicking on things we ended up implementing Steam Leaderboards for tracking player's score, and three simple game modes, while keeping the game to a single level. Creating a demo was easy, we simply added boundaries to the map that prevented the camera from moving outside.

urban-mage-demo-level.jpg

The full game just expands on the playable area and introduces more interactions.

urban-mage-interactions

While this meant we had to abandon our initial idea of a $19.99 game (and instead priced at $2.99) it also meant we could get the core gameplay done in a matter of days, and spend the rest of the time polishing, adding content, and actually making a game, as opposed to the previous attempts at creating huge complicated sandboxes with no gameplay.

Summary and Data

Since we're not working with publishers we'll share our sales/analytics data here. We'll update this section in a few days post release or if anything interesting happens.

Lifetime traffic of Urban Mage (spike is release day):

urban-mage-lifetime-traffic.png

Lifetime daily wishlists of Urban Mage (spike is first day of Steam Next Fest):

urban-mage-lifetime-daily-wishlists

Lifetime cumulative wishlists of Urban Mage (first spike Steam Next Fest, second spike Release):

urban-mage-lifetime-cumuluative-wishlists.png

Urban Mage Sales Summary (note that this is ~12 hours after release):

urban-mage-sales-summary.png

We ran two streams during Steam Next fest in February each having around 200 viewers. In total our wishlists grew from around 300 to 400 during Steam Next Fest for Urban Mage, which isn't great.

In comparison, here's BITGUN's (our second game) wishlists which grew from around 400 to 1100 during Steam Next Fest:

bitgun-lifetime-daily-wishlists.png

And cumulative wishlists

bitgun-lifetime-cumulative-wishlists.png

Note that we've done significantly more marketing for BITGUN, and it's Steam Next Fest stream had over 6000 people watching concurrently.

Lastly, here's lifetime traffic of BITGUN (spike is Steam Next Fest):

bitgun-lifetime-visits.png


At the time of writing twe have 669 followers on Twitter, which has been growing at around ~60 per month, and 215 members on Discord. What is interesting is that while we did link both in our Steam Next Fest demos there was basically zero change in either (less than 3 extra people joining), even though BITGUN Demo has 3601 licenses and 521 unique players, while Urban Mage Demo has 3099 licenses and 78 unique players. (Licenses are likely people who clicked "add" but never played the game).

For comparison, Hell Loop has sold 394 copies and made $699 net during the ~14 months since its release and is now sitting at 658 wishlists. At this point it averages less than one copy sold per day unless it is on sale. Note that this is with almost zero marketing for the game and a terrible release right at the beginning of a Christmas sale which it wasn't a part of. We only ran 2 visibility rounds so far.

For completeness, here's Hell Loop's sales data throughout its lifetime

hell-loop-lifetime-sales.png

hell-loop-sales-page.png


We'll be writing a second postmortem for BITGUN once it gets released and show more updated data.

If you liked this article consider supporting us by buying Urban Mage and posting a review on Steam (doesn't have to be positive, we want honest reviews). Games get a rating and increased visibility once they reach 10 reviews.

You could also support us by wishlisting BITGUN which is planned to be released in Q2 2022.


Discussion thread on Reddit