godotengine / godot

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

Script changes made with an external editor are not live reloading #73808

Open fhd opened 1 year ago

fhd commented 1 year ago

Godot version

3.51.stable.mono.official

System information

Ubuntu 22.04.2 LTS, GLES3, GeForce RTX 3090

Issue description

Live reloading changes made by an external editor doesn't seem to work for me, tried this on two different machines. In my understanding, since #51828 (which aims to address #10946) has been merged quite a while ago, it should.

I don't see any errors in the console or debugger, just nothing happens after I save the file with an external editor. I tried it with and without setting Use External Editor.

Update: Did some debugging (full story in the comments) and figured out that it does reload, but only if the editor window is focused after the file has been saved. I'd love a truly automatic reload though, without having to touch the editor first.

Steps to reproduce

I made a project to reproduce this, but it's pretty simple:

  1. Create a new project
  2. Create a new User Interface scene
  3. Add a Label node
  4. Attach a script to the Label node
  5. Add a _process function with $Label.text = "Test"

Steps to reproduce once the project is in place:

  1. Run the project
  2. Change the string "Test" to something else in the Godot script editor and observe that it live reloads
  3. Change the string in an external editor and observe that it does not live reload

Minimal reproduction project

external-editor-live-reload.zip

fhd commented 1 year ago

Also just tested this in 4.0 rc3, and it doesn't work either. That said, I'm just not 100% sure how/if it's supposed to work. I found a setting Auto Reload Scripts On External Change in both 3.5 and 4.0, but turning it off doesn't seem to help (nor would I expect it to, I guess).

fhd commented 1 year ago

Took some time to test this on a Windows 10 machine - same behaviour. Makes me wonder even more if this is even supposed to work.

fhd commented 1 year ago

Doesn't appear to be a regression either - just tested in 3.4.2, the release that first included this change, as well as my own build of https://github.com/godotengine/godot/commit/19301d4ad2ed8f66c93ea41529473c7ee68df506 (the commit that fixed this in the 3.x branch) - no luck.

Started to look into the code to try and figure out what's going on here - currently trying to understand all the cases in which update_modified_scripts_for_external_editor is being called, since that's what ultimately calls _trigger_live_script_reload after the PR that addressed this back then. One of these would have to be triggered by a file change on disk, I presume.

fhd commented 1 year ago

Alright, from reading the code, I think I figured it out! The changes are only reloaded if the editor receives focus after the changes are saved. Looks like that's the behaviour as implemented, but I would argue it would be more ideal if it wasn't necessary to change focus to the editor first.

KoBeWi commented 1 year ago

What's the use for automatic reload? If the editor is not focused, you are not using it. And there is no way to save a file externally without unfocusing the editor AFAIK.

PathogenDavid commented 1 year ago

What's the use for automatic reload?

My use-case is that I have multiple monitors. I have VS Code open on my left monitor, the editor on my middle monitor, and the running game on the right monitor.

Since I can still see the game running ideally I'd like to see my changes reflected as soon as I save. (Which is how it works if I use the built-in script editor.)

sztomi commented 1 year ago

I'm seeing the same behavior on Linux in 4.0.stable (GDScript version).

OmarShehata commented 1 year ago

It would be great to fix this. The editor is going to be NOT focused 100% of the time when you are editing code with an external editor, which you need to be doing if you want to see your code side by side with the scene editor.

goblinJoel commented 7 months ago

On Godot 3.5.3, Windows 10: I'd like to note that, on my own project, I don't get live reloading of scripts for a running game even when I switch focus from VS Code back to the editor after saving the change. It does reload tool scripts within the editor immediately though, no focus switch necessary.

It works fine if I edit the script from within Godot -- changes apply in a running game immediately.

I've tried with and without Editor > Text Editor > External checked.

OmarShehata commented 7 months ago

The fix was implemented here https://github.com/godotengine/godot/pull/82986. It does seem to work in v4.2.1.stable.official [b09f793f5]. I thought I saw it was backported to some 3.x version but I can't find that now.

gmanavarro commented 2 months ago

I'm using 4.2.2.stable and this is not working yet. I did all the required setup but when I save a script in Vscode, the running game is not reloading.

KoBeWi commented 2 months ago

Well according to the comment above, it does work in 4.2.1, so it should in 4.2.2 too. I just tried in 4.3 beta and the feature is also functional.

gmanavarro commented 2 months ago

I was testing right now and it does seem to work in some cases, e.g. I made some changes to the _ready function and it was not reloading at all, but changing _process or _init is reloading correctly. It seems like the _ready function is not being affected by the reload. Is this expected behaviour?

KoBeWi commented 2 months ago

_ready() function is called only when node enters scene tree for the first time, so modifying it won't call the method again. Not sure about _init(), it should also be called once, though maybe it has something to do with script being reloaded (recreated).

gmanavarro commented 2 months ago

Okay, so, if I make changes in _ready, I need to restart the scene to actually see the changes applied, is that right? Thanks a lot for your response

KoBeWi commented 2 months ago

More precisely - the changes are applied, but you need to restart the scene or add a new instance of the node to call the method again. You can also use request_ready() and remove/re-add the node to scene tree (though it's a dubious hack).

OmarShehata commented 2 months ago

@gmanavarro @KoBeWi I have the same use case, I'm hoping if we get this ticket resolved https://github.com/godotengine/godot/issues/47615#issuecomment-976454455 then the workflow can be:

For scripts that I want to edit at runtime and have their _ready() re-run, you could have a system that detects when the script is changed, and runs a swap(oldInstance, newInstance) callback. You can then decide what to do with oldInstance (the typical thin would be to copy all the state from old to new, OR you might want to re-initialize the state, essentially re-running _ready, or something else custom)

this is how the PlayCanvas engine does it and I think it works pretty well. Gives you full control over how to update things at runtime. See for reference: https://developer.playcanvas.com/user-manual/scripting/hot-reloading/

stayinsidegames commented 1 month ago

I think I am seeing the same issue, but I'm not sure because I'm using gdscript and some of the bug reports linked in this thread concern C#:

If I run the game from VSCode, hot reloading by editing the script in VSCode does not work. If I run the game from the editor, hot reloading by editing the script in VSCode does work. However, when the game is run from the editor, the debugging tools in VSCode do not work. I've written this up in a forum thread here.

I would like to both hot reload and use debugging from VSCode. I have tried this on both 4.2.2 and 4.3 rc-1 with a new project by putting the icon into a scene and changing its position in _process. The changes do appear when I restart the game.

stayinsidegames commented 1 month ago

This may be related, I've noticed that whether hot reload works, using VS Code, depends on whether you specify the debugger and debug server/adapter in launch.json. In short: If you specify those ports, then hot reload works but other VSC debugging functions (from the godot-tools plugin) do not work. If you do not specify those ports, then hot reload does not work but the other VSC debug functions (like looking at the active scene tree) do work.

Here is my writeup in a similar issue thread for the godot-tools plugin: https://github.com/godotengine/godot-vscode-plugin/issues/336#issuecomment-2254656526

DaelonSuzuka commented 1 month ago

If I run the game from VSCode, hot reloading by editing the script in VSCode does not work. If I run the game from the editor, hot reloading by editing the script in VSCode does work. However, when the game is run from the editor, the debugging tools in VSCode do not work. I've written this up in a forum thread here.

In short: If you specify those ports, then hot reload works but other VSC debugging functions (from the godot-tools plugin) do not work. If you do not specify those ports, then hot reload does not work but the other VSC debug functions (like looking at the active scene tree) do work.

Yes, this is the expected behavior.

Additionally, using the debugServer field is not supported with the Godot Tools extension. It completely bypasses 100% of the extension's features and invokes a generic debug interface in VSCode.