Quick answer: The most common cause is the “Reset global variables on start” project property being set to “Yes.” Open Project Properties and change it to “No.” If you are using local variables instead of global ones, they will always reset because they are scoped to a single event block or tick. For robust persistence, store critical state in LocalStorage before layout transitions.

You set up a global variable to track the player’s score, health, or level progress. Everything works perfectly within a single layout. Then the player dies, you restart the layout, and the score resets to zero. The health goes back to full. All progress is gone. This is one of the most commonly reported issues in Construct 3 projects, and it has a straightforward fix once you understand how Construct 3 handles variable scope and layout lifecycle.

The Symptom

You have declared a global variable — for example, Score set to an initial value of 0 — and your events increment it during gameplay. When you use the Restart Layout action (or Go To Layout to navigate to a different layout and back), the variable snaps back to its initial value. Any accumulated state is lost.

This affects all global variables simultaneously. If you have Score, Lives, and CurrentLevel as global variables, all three reset at the same time. The behavior is consistent: every layout start triggers the reset, whether the player navigated there from another layout or restarted the current one.

You might also notice that instance variables on objects behave differently — objects that are placed in the layout editor reset their instance variables on layout start, but objects created at runtime via Create Object simply cease to exist when the layout restarts.

What Causes This

There are three common causes for global variables resetting unexpectedly:

1. The “Reset global variables on start” project property is enabled. This is the cause in the vast majority of cases. Construct 3 has a project-level setting called Reset global variables on start, found under Project Properties. When set to Yes (which was historically the default in older project templates), every global variable reverts to its initial value whenever any layout starts. This means layout restarts, layout transitions, and even the first layout load all trigger a reset. Many developers set initial values like Score = 0 and then are surprised when the engine dutifully sets it back to zero on every layout change.

2. You are using a local variable instead of a global variable. In Construct 3, local variables are scoped to the event block they are declared in. They reset on every tick or every time the parent event runs. If you declared a variable inside an event group or a function rather than at the top level of the event sheet, it is local, not global. Local variables always start at their initial value each time the event block runs — they have no persistence at all, not even within the same layout.

3. You are using Restart Layout when Go To Layout would be more appropriate. The Restart Layout system action fully tears down and rebuilds the current layout, including resetting all objects to their editor-placed state. While this does not inherently reset global variables (that depends on the project property), it does destroy all dynamically created objects and reset all instance variables. If you are storing state in instance variables on runtime-created objects rather than in global variables, a layout restart will wipe that state.

The Fix

Step 1: Disable “Reset global variables on start” in Project Properties.

Open your project in Construct 3. In the Project Bar on the right, click on the project name at the top to open Project Properties. Scroll down or search for Reset global variables on start and set it to No.

// Project Properties
Reset global variables on start: No

// With this set to No, global variables like:
Global variable Score = 0
Global variable Lives = 3
Global variable CurrentLevel = 1

// ...will retain their runtime values across layout transitions
// and restarts, rather than reverting to 0, 3, and 1.

Step 2: Verify your variable is truly global.

Open the event sheet where the variable is declared. A global variable appears at the top of the event sheet, outside of any event block, and is labeled with a globe icon. A local variable appears inside an event block and has a different icon. If your variable is local, right-click it and check its scope.

// GLOBAL variable (persists across layouts):
// Declared at the TOP of the event sheet, outside all events
Global variable PlayerScore = 0

// LOCAL variable (resets every tick or event run):
// Declared INSIDE an event block
Event: On start of layout
  Local variable TempScore = 0   // This resets every time!
  Set TempScore to PlayerScore + 10

If you need the variable to persist, move it to the global scope by declaring it at the top level of the event sheet.

Step 3: Use Go To Layout strategically instead of Restart Layout.

If you want to reload the current layout but preserve all global state, you can use Go To Layout and select the current layout. Both actions rebuild the layout, but the distinction matters when combined with other project settings:

// To restart the current layout while keeping globals:
Event: Player health <= 0
  Action: System > Go to layout > GameLevel

// Avoid Restart Layout if you have complex state to preserve:
// Restart Layout can behave differently with certain plugins
// that hook into the restart lifecycle.

Step 4: For critical state, use LocalStorage as a safety net.

If you absolutely cannot risk losing a value — for example, the player’s purchased upgrades or progression — write it to LocalStorage before the transition and read it back on the next layout start:

// Before transitioning layouts, save critical state:
Event: On function "SaveState"
  Action: LocalStorage > Set item "player_score" to Score
  Action: LocalStorage > Set item "player_lives" to Lives

// On the new layout, restore the state:
Event: On start of layout
  Action: LocalStorage > Get item "player_score"

Event: LocalStorage > On item get
  Condition: LocalStorage.Key = "player_score"
  Action: System > Set Score to int(LocalStorage.ItemValue)

Step 5: Use a Dictionary on a global object for complex state.

For games with many values to track, create a Dictionary object, place it on a layout that is always active (or mark the object as Global in its properties), and use it as a central state store:

// Create a Dictionary called GameState on a persistent layer
// Mark the Dictionary object as Global = Yes in properties

// Storing values:
Event: On function "UpdateState"
  Action: GameState > Add key "score" value Score
  Action: GameState > Add key "level" value CurrentLevel
  Action: GameState > Add key "health" value PlayerHealth

// Retrieving values after layout change:
Event: On start of layout
  Action: System > Set Score to GameState.Get("score")

Why This Works

Construct 3’s layout lifecycle has a specific order of operations when a layout starts. First, the engine recreates all objects placed in the layout editor, resetting their instance variables to editor-set values. Then, if “Reset global variables on start” is enabled, it resets all global variables to their declared initial values. Finally, it fires the On start of layout trigger.

By disabling the reset property, you remove step two from this sequence. Global variables retain whatever value they had when the previous layout ended. This is the intended behavior for most games — you want the score, lives, and progress to carry over between levels and retries.

The local vs global distinction matters because local variables are not part of the global variable pool at all. They exist only within their enclosing event scope and are re-initialized every time that scope executes. No project property can change this behavior because it is fundamental to how local variables work in Construct 3’s event system.

Using LocalStorage adds a persistence layer that survives not just layout transitions but also browser refreshes and game restarts. This is essential for save systems but is overkill for simple layout-to-layout state transfer where the project property fix is sufficient.

“The first thing I do in every new Construct 3 project is set ‘Reset global variables on start’ to No. It should be the default, but it is not, and it catches everyone at least once.”

Related Issues

If your game crashes entirely rather than just losing state, check out fixing WebGL context lost errors which covers GPU memory issues that can cause Construct 3 games to fail on certain devices. If your layout is not starting at all, see loader layout stuck not progressing for issues with the loading screen hanging. For multiplayer games where state synchronization is the real problem, read about multiplayer signaling connection failures. And if your objects appear but in the wrong visual order after a layout restart, Z order not updating at runtime explains how rendering order works in Construct 3.

Check the project property first. It is almost always the project property.