Exit requests: confirm or cancel
Keep the game running until confirmation and saving have completed.
A window close request, a menu Exit button and a direct Quit() call are separate paths. EntityTree.AutoAcceptQuit and EntityTree.QuitOnGoBack are enabled by default. For custom confirmation, disable both automatic exits and route requests to one controller.
Exit controller
Use a Reckfell 1.0.0 C# project. Save this as ExitController.cs and attach it to an Entity that stays in the tree while the confirmation menu is active. For multiple levels, use an autoload.
using Reckfell;
public partial class ExitController : Entity
{
[Signal] public delegate void ConfirmationRequestedEventHandler();
public bool ConfirmationPending { get; private set; }
public override void _Ready()
{
GetTree().AutoAcceptQuit = false;
GetTree().QuitOnGoBack = false;
}
public override void _Notification(int what)
{
if (what == NotificationWMCloseRequest || what == NotificationWMGoBackRequest)
RequestExit();
}
public void RequestExit()
{
if (ConfirmationPending) return;
ConfirmationPending = true;
EmitSignal(SignalName.ConfirmationRequested);
}
public void CancelExit() => ConfirmationPending = false;
public void ConfirmExit()
{
if (!ConfirmationPending) return;
ConfirmationPending = false;
GetTree().Quit();
}
}The script does not draw a dialog. Connect it to your interface:
- The
ConfirmationRequestedsignal opens a menu with Exit and Stay buttons. - The main menu Exit button calls
RequestExit(). - Stay calls
CancelExit()and hides the menu. - Exit calls
ConfirmExit(). If saving is required, complete the save and check its result first; on failure, keep the menu open and do not callConfirmExit().
A repeated request while confirmation is pending does not create another dialog. ConfirmExit() without a pending request does nothing. This controller does not save the game: see saving data for complete write, backup and load examples.
Engine behavior
| Action | Result |
|---|---|
| Window close request | The window propagates NotificationWMCloseRequest and emits CloseRequested. Automatic exit for the main window depends on AutoAcceptQuit. |
| Back request | Delivers NotificationWMGoBackRequest; automatic exit depends on QuitOnGoBack. Disabling only AutoAcceptQuit is insufficient. |
GetTree().Quit(23) | Requests termination with exit code 23. Does not send the close notification, open confirmation or save data itself. |
Root.PropagateNotification(...) | Synchronously notifies the root and descendants. Propagation itself does not terminate the process; a handler may call Quit(). |
Do not place an await after Quit() and expect saving to finish. Await the operation first, then request exit. Do not propagate close notifications from every close handler: that invokes the same handlers again.
Verify and diagnose
- Press Exit twice: confirmation should open once. Choose Stay: the game continues.
- Request exit again and confirm: the process terminates. Use
RequestExit()for your own menu, rather than callingQuit()directly. - The game exits before confirmation: check both tree flags and other
Quit()calls; the controller must have entered the tree in time. - Saved state is incomplete: look for asynchronous work followed by
Quit()without awaiting completion, and handle write errors.
On mobile devices and during forced termination, do not rely on an exit confirmation. Save checkpoints during gameplay and test background handling on the target platform. No final callback before process destruction is guaranteed here.
Verified in the installed engine: this exact controller, notifications, repeated requests, cancellation, confirmation, default main-window signal connections and exit code 23. The check uses synthetic signals and notifications in headless mode; native window close clicks, dialog appearance, mobile lifecycle and exported builds were not separately tested.