A little while ago, I decided to have a go at making this Amiga game from my childhood:
This project actually ended up being much more difficult than I anticipated, which I guess is why it makes a lot of sense to start out with these smaller scope projects. Whilst the majority of it didn’t cause too many issues, there were one or two key problems which I spent a lot of time on.
Sprites and animation
The first thing I did was attempt to make some sprites. I’m actually pretty happy with the little guy in a suit, even if his Microsoft Paint heritage wasn’t particularly subtle.
I also made a bunch of animation frames for him to run around and set about making him animate in Unity. The animation tools allow you to set up a state machine that decides what animation should be playing at any one moment. The transitions can be triggered by setting the parameters from the C# scripts assigned to the player object.
This diagram used to be a lot more complicated, as I had separate sprites/animations for moving left and moving right. It turns out that you can flip the sprite easily by simply negating the scale of the object’s transform. This trick made the state machine much simpler and much less confusing. This lesson alone was probably worth the time I put in so far, since moving a 2D character left and right is probably something I’m going to want to do again at some point.
The next most interesting challenge came at the point when I realised that I wanted my character to have two different collision behaviours with the same object, namely a platform. He needed to be able to stand on top of the platforms, but if he hit a platform with anything other than his feet, he’d need to fall over and “sleep” for a few seconds before the player regained control. I chose to solve this problem by creating separate sub-objects for the player’s feet and for their body, each with their own colliders and own scripts for dictating what should happen in the event of a collision.
After having this working, it was clear there was something else that was wrong. My character, after jumping, could happy jump again and again in mid air without any ground beneath his feet. Similar to the sprite-flipping moment earlier, I felt the sense again that I was stumbling across a problem that had tripped up many a budding platformer developer in the past. The solution was to keep track of when my character was on the ground using a flag – set the flag to True when the character’s feet collide with a platform, and the flag to False if he is commanded to jump. That way, I could ignore jump commands if the flag was set to False.
At this point, I had my character running and jumping around, able to land on platforms and also knocked out by them. The next problem I encountered was easily the toughest to solve, and I again felt like I was treading in the footsteps of many developers before me. I needed holes in my platforms, and I needed the holes to move along the platforms.
It turns out it’s not particularly easy to make a hole in a rectangular collider. You have to use workarounds in one way or another to make it work. If it were the platforms that were moving, it would be easier because the holes would simply be gaps between the platforms themselves, which would have separate colliders. In this case though, the holes move along the platforms – you can see this in the video above.
The solution I used in the end I think really highlights how a lot of what you see in a game is smoke and mirrors. Whether the illusion is down to constraints of the engine or constraints on computing power, there is always a kind of magician’s act going on. When bizarre glitches occur, quite often I bet what is actually happening is that the illusion has broken down momentarily and we are seeing the game world for what it really is.
Anyway, in my case, the holes had to be separate objects that could move independently along platforms. Therefore, Unity objects were instantiated for each hole, and their colour was set to match the background colour so they would appear invisible.
Next, in order for the character to actually pass through them, I would need to detect when the player was in a hole, which meant assigning a trigger collider (a collider that detect collisions but does not apply any forces as a result). A script was set up on these hole objects so that, if the player jumped into one, the collider for the entire parent platform would be switched off. I actually made the colliders for the holes quite tall so that whenever the player was standing above or below a hole the collider for the respective platform would be switched off.
The issue with this approach was that it introduced a whole bunch of bugs into the game due to the number of edge cases, such as jumping through a hole and immediately falling back through it or falling through a hole without jumping first. Because I was switching the collider for the platform on and off manually, certain OnCollisionEnter2D function calls were not executing which I was relying on for checking if the player was on the ground or not. Without that function call, the game still thought the player was on the ground and so could jump in mid air again.
Eventually however I was able to overcome those bugs by essentially keeping an eye out for those edge cases and making sure that the correct code was executed at those times. Perhaps there is a more elegant solution for dealing with moving holes which reduces the number of edge cases, but in the end this solution worked well enough for me.
The final steps of the project were to add enemies and make the game work on my Android phone, neither of which kept me back too long.
Overall, I feel like the project was a good learning experience, especially in terms of learning a bit more about the common problems faced when building a simple platformer. Next time I think I’ll try something outside of Unity.