godotengine / godot-cpp

C++ bindings for the Godot script API
MIT License
1.68k stars 509 forks source link

C++ Hot Reload Regressions in 4.2.2 and 4.3 #1589

Open kromenak opened 5 days ago

kromenak commented 5 days ago

Tested versions

System information

Godot v4.3.stable - Windows 10.0.19045 - Vulkan (Mobile) - dedicated NVIDIA GeForce GTX 1650 SUPER (NVIDIA; 31.0.15.3623) - Intel(R) Core(TM) i5-3350P CPU @ 3.10GHz (4 Threads)

Issue description

We are working on a project using C++ GDExtension. When we started the project in Godot 4.2.1, we found the hot reload functionality to work quite well on both Windows and Mac dev machines. All developers could iterate quickly by recompiling C++ code, switching back to the editor, and seeing changes immediately.

However, after updating to Godot 4.2.2, Windows devs complained that hot reload could cause the editor to crash, or could result in the new DLL not loading correctly, resulting in extension classes disappearing from the scene, or inspector hookups getting deleted/removed. On Windows, it seemed to sometimes work, sometimes not. On Mac, hot reload continued to work fine.

Now, in Godot 4.3, hot reload seems to be failing on BOTH Mac and Windows in a few ways:

In short, the hot reload behavior for C++ GDExtensions seems to have really deteriorated in the last two big Godot releases.

Steps to reproduce

In Godot 4.2.1

  1. Open the Godot project in Godot_4.2.1/Res.
  2. Open test_scene.tscn. Notice the blue box around the image (the gizmo plugin). Also notice the root Node has an inspector hookup called "Current Attack Data" that is hooked up to custom Resource.
  3. Generate the C++ project in Godot_4.2.1/Cpp using CMake. There is a helper script in Cpp/Build to generate a VS solution quickly and easily.
  4. Build the C++ solution. This should update the DLL at Godot_4.2.1/Res/addons/CppExtensionDebug.dll.
  5. Switch back to the editor. Notice that the blue box gizmo still functions, and that the "Current Attack Data" hookup is still connected.

In Godot 4.3 Note that the ONLY difference about the 4.3 project is that it is meant to be opened in Godot 4.3, and it uses the 4.3 version of godot-cpp. It is otherwise IDENTICAL to the 4.2.1 version.

  1. Open the Godot project in Godot_4.3/Res.
  2. Open test_scene.tscn. Notice the blue box around the image (the gizmo plugin). Also notice the root Node has an inspector hookup called "Current Attack Data" that is hooked up to custom Resource.
  3. Generate the C++ project in Godot_4.3/Cpp using CMake. There is a helper script in Cpp/Build to generate a VS solution quickly and easily.
  4. Build the C++ solution. This should update the DLL at Godot_4.3/Res/addons/CppExtensionDebug.dll.
  5. Switch back to the editor. Notice that the blue box gizmo disappears. Also notice that the "Current Attack Data" hookup has become "". Saving the scene at this point causes the connection to be lost and saved to disk.

Minimal reproduction project (MRP)

HotReloadBug.zip

kromenak commented 5 days ago

I've tried to investigate some of these problems in the source code for godot and godot-cpp. Unfortunately, I'm not very familiar with these systems, but here's some info I was able to find, in case it's helpful.

Inspector Hookup Failing on Hot Reload The exact case here might be when an extension class instance has a property that is also an extension class. In my sample project, the scene has an Actor node (an extension class that inherits Node3D). Actor has an exposed property for AttackData (also an extension class inheriting from Resource). This issue with "losing connections" has not occurred if the inspector hookup is for a built-in class, such as AudioStream.

I stepped through this in the debugger and found this:

akien-mga commented 4 days ago

CC @godotengine/gdextension

dsnopek commented 3 days ago

Thanks!

I'm able to reproduce the issue with your MRP.

It seems like the problem is in godot-cpp (rather than Godot) because switching to the godot-4.2.1-stable tag of godot-cpp but using Godot v4.3-stable seems to work. However, I'll understand it better after I have a chance to git bisect,

dsnopek commented 3 days ago

Git bisect points to godot-cpp PR https://github.com/godotengine/godot-cpp/pull/1446

I think we missed needing to set the instance binding when doing a reload. I'll work on a PR to fix it.

akien-mga commented 3 days ago

Transferred to godot-cpp.

dsnopek commented 3 days ago

I just posted PR https://github.com/godotengine/godot-cpp/pull/1590 which should fix this! I already tested with the MRP, but if anyone has time to test it with their project, I'd appreciate it :-)