Back in 2023, my wife and I decided to spend some time developing a fun little game for mobile. We made the game, but never published it. This summer, we refreshed it so it could be published on the web.

The idea came after our car was covered in a truly awful case of guano. We thought it would be funny to reverse the situation... to take reverse-revenge on cars by pooping on them instead. This blog post goes through some of the interesting details from the project.

This post assumes that the reader has already tried the game. Here is a quick GIF that shows the game:

You can play it on Itch.io: Guano vs Cars by HHMagnus, RickitySticks

Google Play vs. Itch.io

Our original plan was to publish the game as an Android app on the Google Play Store. We made it playable on Android and started the publishing process. However, the registration process was slow, and we kept having to add more features or changes to meet mandatory requirements before we could publish.

After a long setup period, we gave up because new requirements kept being added. The following months, I received almost monthly emails from Google Play with more requirements to meet in order to publish the game.

Eventually, we discovered Itch.io, which is far more indie-friendly.

Publishing on Itch.io was much easier. It’s designed for indies, and setting everything up was incredibly fast. The game was even playable on mobile via the web interface, meaning we didn’t have to publish it on any app store at all.

The developer-friendliness of Itch.io is fantastic, and we’ll probably use it again to publish more mini-games. However, it doesn’t seem to generate organic views. We published the game, and five minutes later it was already on the second line of the “New Releases” page. Thirty minutes later, it was off the front page entirely. We doubt that generated any meaningful traffic. Though to be fair, we wouldn’t expect dramatically better results on other stores either.

Tech

The game was made in Unity 2021, which supports exporting to both Android and Web. We later upgraded to Unity 6, which allows you to remove the previously mandatory “Made in Unity” splash screen. Development was done in standard C# with MonoBehaviour.

The game consists of three lanes, with the bird at the bottom able to move between them. Lane changes are handled by a simple script that Lerps between positions after receiving input. Input can be via keyboard keys, mouse movement, or touch gestures. The UI uses Unity’s default system.

Cars spawn randomly from the top, along with the lane markings. The bird’s animation is static and loops continuously. This leads to some interesting aspects:

  • The guano animation and gravity setup.
  • The advantage of Unity’s event system for easily hooking in non-core features.
  • An achievement system: Originally using Google Play, later switched to a custom solution.
  • Text rendering improvements, including shadows for better readability.

Guano Dropping

The guano system needed to simulate poop dropping from the bird high above to hit cars below. This meant the collision detection had to account for the falling motion.

The guano animation transitions from a simple ball into a poop shape. We display this animation while using Unity’s physics system with rigidbodies to simulate the drop. Essentially, it’s a small 3D object that falls, and we use collision detection to determine if it hits a car.

If it hits, we switch the car’s texture to a dirty version. If it misses, we remove the rigidbody and leave the guano on the road with a slow movement effect to simulate the birds movement.

The trade-off is that this approach uses more resources. For a small game, this isn’t a big deal, but it does add some processing overhead.

Game Events

One of the best decisions we made was to hook all major events into serialized Unity events:

[SerializeField]
public UnityEvent<int> onLostGame;

We could configure these in the editor, manually wiring them to achievement systems, music triggers, or transitions. This decoupled the core-game logic from other systems.

In the editor, it looked like this: Hooking up UnityEvent in the editor

This worked great for a small project, though it did require a lot of manual setup in the editor. We’re looking forward to testing how well this approach works in more complex projects.

Achievements

The achievement system was originally meant to integrate with Google Play Games, which was easy to set up in Unity. We manually entered all the achievements into Google Play, which then generated a file containing constant strings for each ID:

public static class GPIDS
{
    public const string achievement1 = "...";
    // ... more const achievements
}

Magic strings are difficult to refactor, so we created an enum to correlate them:

public enum Achievement {
    ACHIEVEMENT_1,
    // ... more achievements
}

public string GooglePlayId(Achievement achievement) {
    return achievement switch {
        Achievement.ACHIEVEMENT_1 => GPIDS.achievement1,
        _ => throw new ArgumentOutOfRangeException()
    };
}

This turned out to be a great choice when we later switched to an internal system. We simply saved a List<Achievement> to a PlayerPrefs string, making the transition trivial. Highly recommended as a pattern.

The achievement system also fires events when a new achievement is earned, which the UI listens for to show both the “Achievement Earned” pop-up and the full achievements list.

Text Rendering and Shadows

One of the weakest parts of the original game was the text. We did the following to improve it:

  • Added shadows to all text for better readability.
  • Added a transparent background behind text so it looked better when road markings passed underneath.
  • Gave the bird a shadow to enhance the sense of height, by adding a scaled-down, textureless duplicate of the bird.
  • Improved outlines on all objects.

Here is a comparison with the initial version on the left and refined on the right: Initial version of the text

Try the Game

We hope you enjoyed these behind-the-scenes details! You can play the game here: Guano vs Cars by HHMagnus, RickitySticks

Next time a bird poops on your car… remember: they might just be practicing for our next game.