Giving Godot a Go

20 Jun 2023


I make video games sometimes, but I’ve never used the Godot engine before.

Most of my experience is in Unity, which I have grown increasingly displeased with over time because of how complex the editor is and because of the decisions made by upper management. I also most recently made a game using the Tic-80 fantasy console, which sits at the opposite end of complexity for game engines.

However, there is a mech themed game jam coming up that I want to participate in, and I figured that this was a good a time as any to start learning how to use the open source kid on the block.

What have I been making?

So, in a previous game jam hosted by my place of work (!), I tried to make an arcade game all about flying a jet that only had a dash attack to fight enemies. The theme of the jam was “Make a nest”, and the way that I was planning to build that into the game was to have the player collect powerups from defeated enemies, then deliver them to a “nest” home base in order to score points. When delivering the powerups to the nest, the player would lose the benefits they gained from them. Thus, the player would need to find a balance between powering themself up and actually scoring points by building the nest.

Unfortunately, I did not get enough done to complete a full gameplay loop working, so I ended up only submitting a prototype. You can play this prototype here: NEST_Prototype.

Screenshot of the original NEST game protoype, showing a spaceship performing a dash attack.

I was always a little disppointed that I didn’t make more progress on that project, so I decided to revive it as my first Godot project!

NEST Remake

You can find the source code here: kyratech/nest-game.

This godot remake of NEST is actually even less feature complete than the prototype that I submitted to the game jam. You can only fly around and crash into the ground. In my defence, all this progress has been achieved in the lazy evenings of my week of holiday last week.

Screenshot of the remade NEST game, showing a spaceship performing a graceful swoop through the air.

Despite its incomplete nature, I am really proud of where this project is going so far. I can directly compare features between the versions of the games and see how far I have come as an artist and a developer.

For example, consider the way that I have achieved 360° animation of the player. In the original game, this was a single sprite that I rotated in Unity by setting the rotation of the game object. However, arbitrary rotations of pixel art tend to look a bit crap due to the low resolution, so I wanted to hand-draw the different angles for this remake.

So I did!

16 frames of animation showing a spaceship with two prongs at the front rotating around the Z axis.

To make the animation more visually interesting, I had the spaceship also rotate such that the top would be facing the player when flying up and the underside would be facing the player when flying down.

My process for this animation was to start with the cardinal directions, then do the inter-cardinals, then finally the frames inbetween those. I took this philosophy from animation practices, where you start with important keyframes, then fill in the transition frames afterwards.

The completed player rotation animation.

Godot as a game engine

It’s very little

The first thing that I noticed when I ran Godot was how fast and small it was. The entire executable was in the download that I got off their website, and upon clicking it I waited a grand total of a second before being given the option to start a new project.

Having used Unity in the past, this was a breath of fresh air!

The philosophy of Godot

I’m still in the early stages of this project, but what I have completed so far has taught me a lot about how Godot is designed.

Specifically, Godot is perhaps the most opinionated game engine that I have used so far. What I mean by this is that the developers of Godot have an idea of how users should be using it to make a game, and the design of the engine is driven by this idea. I am sure that it is possible to make a functional game in Godot by following your own patterns, but it will probably be harder to code and less performant once finished.

This is not a good or a bad thing. Like many things in life, Godot simply expects you to meet it on its level in order to get the most out of it.

The most obvious way that this is expresed is through the “Scene” system. A Scene is a tree of game objets that can be dropped into other Scenes in order to add functionality to them. By compositing Scenes together, you can build up complex behaviour, and eventually, a whole game.

When I first started my project, I wanted to work mostly in code. I never really liked Unity’s UI because I didn’t know where all the settings lived. The simple code-based API of Tic-80 was honestly one of my favourite things about working in it. However, in Godot, there is an important limitation that prevented me from using code as the primary source of behaviour: you can only apply one script to each node in the Scene tree.

So, if I wanted to put all of the behaiour of the player in the player script, I would need to create a single monolithic file that contains all of the functions that I could possibly want. Even for a simple arcade game, this was obviously going to be unsustainable.

Upon reading the docs, I realised that this limitation was intentional. Each node should have a limited set of responsibilities. If you need additional behaviour on an object, you should create a new node or Scene that encapsulates this behaviour separate from other behaviours.

My player Scene is comprised of the player node itself, then child nodes for controlling the sprite animation, collisions, camera controller, and thrust particle trail.

In many ways, this resembles the ECS (Entity Component System) pattern used by game engines such as Bevy. I have researched ECS game engines in the past, and even made a proof of concept ECS engine in Tic-80, so adapting to this way of thinking was surprisingly smooth sailing. The main difference with Godot’s approach is that data and behaviour are not separated into different modules by default.

Conclusions

Now that I know what Godot wants from me, I have been having a blast working with it. I am really excited to use it for my next few projects!