godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Add a keyboard shortcut to perform frame-by-frame stepping when running a project from the editor #3105

Open Calinou opened 3 years ago

Calinou commented 3 years ago

Describe the project you are working on

The Godot editor :slightly_smiling_face:

Describe the problem or limitation you are having in your project

Troubleshooting bugs in your character/AI controller scripts or physics bugs can be difficult due to the real-time nature of the simulation. When a hitch is only visible for 1/60th of a second or sometimes even less, it's hard to see what can go wrong in real-time.

Describe the feature / enhancement and how it helps to overcome the problem or limitation

Add a keyboard shortcut to perform frame-by-frame stepping when running a project from the editor.

You may have seen a feature like this in console emulators. It's pretty similar in principle.

Describe how your proposal will work, with code, pseudo-code, mock-ups, and/or diagrams

I'm not sure which key this should be bound by default; ideas are welcome. (Note that this shortcut will be ignored in exported projects.)

Also, we may want to add a project setting to configure the kind of frame-by-frame advance used:

Alternatively, we could allow holding a modifier such as Shift to choose between the kind of frame-by-frame advance to perform.

If this enhancement will not be used often, can it be worked around with a few lines of script?

This can be implemented using an add-on. However, I expect this feature to be used relatively often in complex games where physics interactions can get dodgy when you're developing large character controllers and whatnot.

Is there a reason why this should be core and not an add-on in the asset library?

See above.

MaaaxiKing commented 3 years ago

This should also be a button in the debugger.

manuq commented 4 months ago

It was easy to prototype this in an autoload:

extends Node

func _ready():
    process_mode = Node.PROCESS_MODE_ALWAYS

func _input(event):
    if Input.is_action_pressed("pause-resume"):
        get_tree().paused = not get_tree().paused

func _process(delta):
    if Input.is_action_just_pressed("next-frame"):
        if get_tree().paused:
            get_tree().paused = false
        await get_tree().process_frame
        get_tree().paused = true