Pause: gameplay, interface and timers
ProcessMode, physics, signals and CreateTimer; working pause and resume buttons.
Run pause with a working interface
Add ProcessCounter2D.cs and PauseDemo2D.cs to a 1.0.0 C# project. Attach PauseDemo2D to an Entity2D in a separate level, set a 640×420 viewport, build and press F6. Pausable stops after Pause; Always and the status keep updating. Resume restores gameplay time.
ProcessCounter2D.cs
using Reckfell;
public partial class ProcessCounter2D : Entity2D
{
public double Elapsed { get; private set; }
public int ProcessCalls { get; private set; }
public int PhysicsCalls { get; private set; }
public override void _Process(double delta) { Elapsed += delta; ProcessCalls++; QueueRedraw(); }
public override void _PhysicsProcess(double delta) => PhysicsCalls++;
public override void _Draw()
{
DrawCircle(Vector2.Zero, 36, new Color(.08f, .09f, .11f));
DrawCircle(Vector2.FromAngle((float)Elapsed * 2) * 27, 8, new Color(.25f, .45f, 1));
DrawString(ThemeDB.FallbackFont, new Vector2(-40, 64), Name.ToString(), fontSize: 17);
}
}PauseDemo2D.cs
using Reckfell;
public partial class PauseDemo2D : Entity2D
{
public ProcessCounter2D GameClock { get; private set; } = null!;
public ProcessCounter2D UiClock { get; private set; } = null!;
public Label Status { get; private set; } = null!;
private bool _previousPause;
public override void _EnterTree()
{
ProcessMode = ProcessModeEnum.Always;
_previousPause = GetTree().Paused;
}
public override void _Ready()
{
bool ru = TranslationServer.GetLocale().StartsWith("ru");
AddChild(new Label { Position = new Vector2(28, 24), Text = ru ? "Пауза: игровое время и интерфейс" : "Pause: game time and interface" });
GameClock = new ProcessCounter2D { Name = "Pausable", Position = new Vector2(180, 225), ProcessMode = ProcessModeEnum.Pausable };
UiClock = new ProcessCounter2D { Name = "Always", Position = new Vector2(440, 225), ProcessMode = ProcessModeEnum.Always };
AddChild(GameClock);
AddChild(UiClock);
Status = new Label { Position = new Vector2(28, 340) };
AddChild(Status);
var pause = new Button { Position = new Vector2(28, 82), Text = ru ? "Пауза" : "Pause" };
var resume = new Button { Position = new Vector2(160, 82), Text = ru ? "Продолжить" : "Resume" };
pause.Pressed += () => GetTree().Paused = true;
resume.Pressed += () => GetTree().Paused = false;
AddChild(pause);
AddChild(resume);
}
public override void _Process(double delta)
{
if (Status is not null) Status.Text = "Paused: " + GetTree().Paused + " | Pausable: " + GameClock.ProcessCalls + " | Always: " + UiClock.ProcessCalls;
}
public override void _ExitTree() => GetTree().Paused = _previousPause;
}This demo owns global pause and restores the original state on exit. In a game choose one responsible controller; independent components changing one Paused flag can clear each other's pause.
Choose ProcessMode
| Entity mode | Behavior |
|---|---|
| Inherit | Inherits through the Parent hierarchy |
| Pausable | Processes while EntityTree.Paused = false |
| WhenPaused | Processes while Paused = true |
| Always | Processes in both states |
| Disabled | Ordinary processing is disabled; children with explicit modes can differ |
Mode inheritance follows Parent rather than serialization Owner. IsProcessing reports an enabled callback without guaranteeing that pause and active-tree conditions currently allow it. CanProcess addresses those conditions. SetProcess(false) and ProcessMode solve related but different tasks.
The resume-button controller must process while paused: a Pausable interface can lose the input intended to resume it. Signals and direct calls, including CallGroup, do not stop merely because Paused is true. Losing _Process callbacks does not make an object inaccessible to other calls.
Physics and waits
EntityTree.Paused stops the 2D/3D physics servers in ordinary use. Always can continue _PhysicsProcess callbacks without restarting simulation. The fixture verifies an advancing Always counter alongside a stopped RigidBody2D. Running physics-step code and integrating a body are different operations.
| Wait | Pause behavior |
|---|---|
| CreateTimer(seconds) | Defaults to processAlways = true and keeps running |
| CreateTimer(seconds, processAlways: false) | Stops until the game resumes |
| A Timer Entity | Follows its ProcessMode and separate Timer properties |
| A signal subscription/await | Can finish if its source emits during pause |
Pause is neither Engine.TimeScale = 0 nor object deletion. Slow motion, ignoring time scale and physics-step timers need their own settings. Checks cover both EntityTreeTimer policies, Pausable/Always Timer entities, signals and resuming; application suspension and all platform events are not covered.