godotengine / godot

Godot Engine – Multi-platform 2D and 3D game engine
https://godotengine.org
MIT License
90.13k stars 21.17k forks source link

System.TypeInitializationException Causes Editor To Crash #45723

Open Anemony22 opened 3 years ago

Anemony22 commented 3 years ago

Godot version: Godot Engine v3.2.3.stable.mono.official -- Open GL 3.0 Renderer: GeForce RTX 3070/PCIe/SSE2 Microsoft Visual Studio Community 2019 Version 16.8.4

OS/device including version: Windows 10 (19042.746)

Issue description: Building project, either through 'Build' at top right of Godot, or building the solution in Visual Studio causes Godot to crash. The application and visual studio (if either are running) don't crash, just the editor.

From some more testing, it seems like it only crashes if Visual Studio is open, or has been opened since the editor was started.

I've attached the console log. The last System.TypeInitializationException shows up just before the editor crashes, and the one before that shows up when I open the editor. image

Steps to reproduce: My project didn't used to do this and other projects don't cause this issue, so I'm not sure how to reproduce this.

Minimal reproduction project: Couldn't reproduce

Anemony22 commented 3 years ago

I think I've cracked it. Static variable declarations at the top of a class cause the editor to crash because the node hasn't entered the tree yet. In retrospect this seems obvious, but especially for newer programmers such as myself, a hard crash with no visible logs or messages caused a lot of headache 😅 I take it this isn't intended behaviour.

For anyone else who has this issue, go through your static variables and move anything that interacts with the tree or (pre)loading of resources into the _Ready() override and attach the script to a Node, rather than loading it in as a c# script separately.

For reference, it was this code at the top of my class that caused the editor crash:

private static PackedScene packedDay = GD.Load<PackedScene>("res://scenes/day.tscn");
private static PackedScene packedCinema = GD.Load<PackedScene>("res://scenes/cinema.tscn");
private static PackedScene packedSession = GD.Load<PackedScene>("res://scenes/session.tscn");

private static Node mainScene = (Node)Engine.GetMainLoop().Call("get_current_scene");
private static Node Global = Global = mainScene.GetNode("/root/Global"); // Global Singleton;
colececil commented 2 years ago

I ran into this same issue during a game jam, when my editor started crashing quite frequently. I didn't know what was going on, but I just kept going (dealing with the editor crashing and having to reopen it often), as I didn't have time to look into it. Today I went through my repo and found the commit where the issue started happening. Once I found what was causing the problem, I was able to create this small sample project to reproduce it: test.zip.

I was about to create a new issue for this, but then I found this one here. I thought I'd go ahead and add the information I've gathered, in case it's helpful.

Environment:

Behavior:

Cause of Issue:

The issue occurs when there is a script that accesses information about a Node from a static context, such as this line from /scripts/TestNode.cs in my attached sample project:

private static int test = Global.OtherNode.ZIndex;

Here, Global is an autoloaded script, and OtherNode is a static property of type Node2D that holds a reference to another Node.

If Global.OtherNode is not initialized before the TestNode script tries to access it, then the issue will be easy to find, because the game will crash with a NullReferenceException and a stack trace. However, if the property is always initialized before the other script tries to access it (as in my case), the game will work fine, but the editor will frequently crash, which is very confusing behavior.

Expected Behavior: