godot: _Init() is not being called for C# scripts.

Godot version: dacc3f3 and 3.1 alpha

OS/device including version: Window 7 x64

Issue description: _Init() is not being called on my c# scripts

Steps to reproduce: Create a node with this script:

using Godot;
using System;

public class InitTest : Node
{
    public override void _Init()
    {
        GD.Print("Hello World!");
    }
}

But when it runs no message is printed.

Minimal reproduction project: init-test.zip

About this issue

  • Original URL
  • State: open
  • Created 6 years ago
  • Comments: 18 (11 by maintainers)

Most upvoted comments

That pretty much sums it up.

The problem is that if you want to use Godot in a way where your work flow is code-centric you will get into all sorts of trouble with initialization order when you try to pass dependencies around. Anything that is passed to you from the editor via the export attribute is pretty much guaranteed to work. No problem there. But this is not always the case if you want to primarily be responsible for instantiating your own objects from code, passing them to child nodes that require them and adding nodes to the tree manually.

The work flow becomes reversed from what is customary in Godot.

_Ready of course doesn’t accept parameters so you can’t use it to pass dependencies around. C# has constructors and while constructor injection is normally a very powerful pattern in C#, this doesn’t always work that well with Godot because by the time constructor runs - nothing is ready in Godot, so you can’t depend on anything. You can only rely on your own code. If you need some piece of information from Godot, it is not available at this time.

It was my hope that _Init might have been an additional step in initialization which would have allowed clean separation between:

  • Object creation
  • Passing dependencies around via property injection or constructor injection
  • Initialization of the objects

While _Ready would have quaranteed that all child objects are, well, ready, the order would have been reverse with init - allowing us to do away with constructing and using our own Initialize() methods.

I spent a full year studying all the various approaches which could be used to pass data around and get dependencies in Godot in code-first approaches, essentially treating Godot as a library. For me reflection probably worked the best, but also felt like an overkill for something which should be simple.

Godot 4.x largely fixed all the problems which drove me into this in the first place by allowing export of nodes.

But in the end after a year of experimenting I simply finally gave up. The problem at the core wasn’t really ever resolved. Godot is difficult to work with if you want to go code-first and ignore the editor. There is room for improvement. And my hope was (a long time ago) that _Init might have been a simple work flow improvement. There was some talk, a long time ago, of adding _Init support to Godot’s C# version and bringing feature parity between GDScript and C# versions.

To sum it up.

My thinking was that you would do what ever injection you want with parameter/CTOR injection. Then you would go down the tree hierarchy with _Init and initialize the objects with data from a parent class. Then on _Ready you would come up the hierarchy child-to-parent and do final steps with your fully initialized objects and reliably present objects.

Now, maybe this is not how _Init works in GDScript. I don’t know.

But what I do know is _EnterTree would have worked excellently for this exact purpose if it weren’t for the annoying fact that it runs each time the node enters the tree vs. once on creation. I also tried using _EnterTree in my experiments and it required adding bool IsInitialized as class member to every object + logic for checking for this. Which became really old really soon. But other than that it did work exactly as described.

This was a long time ago and I’ve probably forgotten a lot of what the real and practical problems were, but I do believe the out of the ordinary way Godot required networking to be initialized in 3.x was a big part of the issue. And similar practices were also present in other places. But I’ve forgotten the details of the issues.

And I’m not sure what the situation in Godot 4.x is as I’ve mostly transitioned to using node exports after giving up on code-first approach.

I’m sure you can figure out the bottle necks for yourself with some experimentation.

I will hard-code the bindings generator to ignore _init then.

@willnationsdev Yes. However, you will have to add a default constructor as well, since the implicit one is removed if you add a constructor overload. (There was an issue about this but I can’t find it).