Godot 4 was recently unleashed upon the world, which was something I was originally going to ignore for a while as I had gotten comfortable with 3.5. I wasn’t too interested in learning a bunch of new syntax for the updated GDScript, even though it’s purported to run faster, jump higher, etc, etc…that was, at least, until I learned that the type system had become a lot more robust. Meaning you can export typed arrays, and type function arguments as enums. In the end, it wasn’t the game-changing performance updates, but the pedantic semantics that drove me to make the switch. It’s in the name of coherency! Nobody likes inconsistently styled code!
So first off, they’ve got a nifty little conversion process, which immediately sets off my paranoia. What exactly are they converting? What are they gonna mess up? Something’s gonna get messed up, right? Thankfully, they’ve got a neat little option that only touches the config file, and leaves you to the backbreaking work of refactoring all your code…okay I’m not THAT paranoid, I’ll just make a backup, and a backup to the backup, and let’s see what breaks! It’s not like the project is that big yet anyways.
After acclimating to some glaring layout changes and new fonts, I immediately ran my program on the slim chance that it might work out of the box. No dice, as it appears there is now a native member variable of CharacterBody2D (the new KinematicBody2D) named velocity. Easy fix, and potentially a lot cleaner to use now that the new move_and_slide() method natively utilizes the character velocity. It also returns a bool instead of the new velocity, as it updates velocity automatically…hm. This definitely breaks some of my implementation, as I had separated my axis physics. Well, for now we’ll call move_and_slide in our physics loop, get rid of some other conflicts of nomenclature aaaaand oh dear.
So this is where I was at.
And this is what I’m dealing with now.
Man, I am so glad that I’m not converting a bigger game! Right off the bat I can see that there have been some changes with tilemaps, specifically autotile. You can see in the second video the top half of my old testing area is still there, which didn’t use the 3.5 autotile system. Also, seeing as I fall at the rate of molasses, there’s obviously some issues with my physics setup. On the bright side however, it seems as if my player state machine has made it out unscathed! Absolute win.
Let’s start with the TileMap. The TileMap node is still in the hierarchy, but the TileSet settings have all pretty much been reset. However, I’m digging this new interface! Much easier to understand than the old setup, plus the TileMap itself doesn’t close out of the inspector when I’m messing with the TileSet settings, which is a huge quality of life change. Hopefully this UI design carries over to the pain of dealing with Control elements as well. I also spotted native support for hexagonal TileSets, but I shouldn’t get distracted now. I set up a simple little TileSet that utilizes the physics layer I set up, and I’m off to the races. The rat can stand! I was worried I might have redo all my physics layers. I’m a big fan of the new tile layout, except for setting up an autotile, which I haven’t gotten to yet. At first glance it doesn’t seem super intuitive, but I’ll address that later.
Next up is tackling player physics. I started by remapping my inputs, which Godot had cleaned out in the conversion process. Interestingly, the default input events (like “ui_confirm” and such) are hideable with a toggle! Makes things feel a bit neater. Next I cleaned up all my physics functions by removing physics calculations in reference to delta, as this is technically overkill as each of these calculations is already being processed on the consistent physics loop. I had set up individual calls to move_and_slide() that referenced the velocity for each movement based function, so all of these references had to be removed, and move_and_slide was placed in my main physics loop. If you’re upgrading from 3.5, Godot tries its best to convert your code to work with its new systems, but it’s unlikely it’s going to work. It ended up basically resetting my velocity with each call due to how move_and_slide directly updates the velocity now, rather than leaving it to the user to handle themselves. While I see the merit in making these systems easy and accessible (if you make a CharacterBody2D it will literally make a player controller for you by default), I feel like the loss in adaptability will outweigh this is in the long run. While you can always make your own custom physics system if you want some esoteric behavior, functions like move_and_slide made it very easy to interact with collisions in a very customizable way. On the third hand though, Godot natively supports moving with platforms now, which is rad (Though if you’re constraining your player’s max velocity, do you have to set up edge cases when the player is traveling at a higher velocity on a platform? Do I have to keep track of an internal velocity anyways? So much to test!).
Anyways, other than some collision inconsistencies (corners and capsule colliders cause some issues with is_on_ground), I’m pretty much back where I was, as far as I can tell. I’m excited to use all the new shiny toys introduced in 4.0, and ESPECIALLY excited to explicitly define the types of each and every variable in my code.
You may have noticed I’ve changed a few other things since my first post. Mainly I decided to switch out of low res, so I don’t have to translate through a viewport anymore, thank goodness! I dealt with a few issues in regards to scale, added a gun, dealt with a bunch of issues in adding a gun, added a Hurt state to my machine, and added some bullets that can send simple signals. As I flesh these systems out I’ll detail them in a future post. Thanks so much for reading, and give me a job, I’ll kiss the ground you walk on, okay goodbye.
You’re doing it, Peter.