• continued Godot 4 migration
  • got cutscenes playing again
  • fixed game saving/loading
  • fixed shadows
  • discovered that _ready() works subtly differently now
  • lots of fighting with UI
  • various other fixes


You can actually get out of the house and talk to people again! The game crashes moments later when the shop interface attempts to load.

Not a super exciting week to report on; just continued slogging through the update process. If nothing else, this process is helping me reacquaint myself with the code after not looking at it for a few months!

Just a few miscellaneous notes this week…

Godot 4 Changed _ready()

In Godot, _ready() is called when the Node is, well, ready to start its set up (after all its children in the scene tree have completed their _ready() work). It’s where you do all your upfront initialization (usually), so it’s pretty important. In Godot 3, the _ready() defined in every class in your inheritance hierarchy gets called, in order, with your “local” _ready() being called last. This is different from how most function calls work, since they will call the “local” function and you have to explicitly call the super-class’s version by using .whatever().

In Godot 4, _ready() is no longer special (and instead of just using a bare . to call your super-class’s methods, you use super.) so you have to explicitly call super._ready() in your _ready() method. I actually think this is good! Consistency is great! It was just a surprise since that’s not how it worked before, and I only figured it out after some trial and error.

… And Some Other Things

There’s one other weird change that I’ve found, which I’m not as fond of. Classes in GDScript, especially in Godot 3, are a bit weird to work with as a data type themselves. It’s customary to override two particular functions, get_class() and is_class(), so that you can query what something is. They’d look something like

extends Node
class_name FooBar

func get_class():
    return "FooBar"

func is_class(class_name):
    return class_name == get_class() or .is_class(class_name)

which lets you write code like if thing.is_class(TheOneIWant):, allowing for inheritance etc etc.

Well, anyway, in Godot 4 you can’t do that because get_class appears to be special now and you can’t actually override it. I’m not sure if this is intentional or a current bug! Anyway, turns out that the is keyword does what you need now anyway so there’s not really any real reason for doing all of this anymore anyway. You can just write if thing is TheOneIWant and it handles inheritance correctly.

(I actually just popped open Godot 3.5 to see if I could figure out exactly how is works in Godot 3, but for some reason I couldn’t even get my test project to run and print anything at all to the console so if it’s worked this way all along, then I guess this more a note to myself than useful to anyone else.)

UI Continues to Baffle Me

I come from a web development background, primarily in frontend development, so it’s not that UI in general is mysterious to me but it always takes me several tries to get Godot’s UI system to do what I want. I’m glad the UI system is there, it’s quite capable! I just always have to fight it. Some combination of me using it in some bone-headed ways and some interesting decisions on the part of the auto-migration has led me to having to fix a lot of my menus and such to get them looking right again. I’m using the process to try to understand the theme system a bit better and actually, you know, use that instead of having a bunch of manual overrides everywhere. So again, probably for the better! It’s just work.

The Show Goes On

I’m getting impatient to get back to actually pushing the game forward. I don’t know I’ll manage that by next Sunday, but progress is progress.

Have a great week!