Quick answer: Mark the object persistent in its properties, OR move state to global variables (e.g. global.score). Persistent instances survive room changes; globals survive no matter what. Use both together: persistent Game Manager holding globals.

Here is how to fix GameMaker instance variable not persisting across rooms. You store player’s gold in obj_player.gold. Walk to the shop room. Gold is 0 again. The player instance was destroyed on room change and a fresh one spawned with default values. GameMaker’s room model expects instances to reset unless told otherwise.

The Symptom

Instance variables reset to defaults when changing rooms. State that should follow the player (health, inventory, XP) resets. Persistence-dependent features break after the first room change.

What Causes This

Non-persistent instances die on room change. By default, every instance in a room is destroyed when the room ends (room_goto, etc.). The new room instantiates fresh instances listed in its layout. Variable values from the old instance are gone.

Persistent flag inherits across rooms. If you mark the object persistent in Object Properties, instances move with the player across rooms. Create event does not re-fire. But duplicates appear if the destination room also has the object placed, so manage instance uniqueness.

Globals survive everything. Variables prefixed with global. (e.g. global.score) live in a program-wide scope that survives every room change. Only ends when the game exits.

The Fix

Step 1: Use globals for pure data.

// obj_player Create event
// Initialize globals once
if (!variable_global_exists("gold")) {
    global.gold = 0;
    global.max_hp = 100;
    global.current_hp = global.max_hp;
}

// In any step/event, use global.x
// obj_pickup Collision with obj_player
global.gold += 10;

Globals never reset on room change. Perfect for inventory, stats, progress.

Step 2: Persistent object for continuing behavior. For the player character that should keep walking across rooms:

// Object properties for obj_player
// Persistent: checked

// Room End event in obj_player
// Reposition to spawn point in next room if needed
x = global.next_spawn_x;
y = global.next_spawn_y;

Persistent player moves into new rooms automatically. Create event does not re-run, so initialization state persists.

Step 3: Handle duplicate instances. If you mark an object persistent and also place it in destination rooms, you get duplicates after room change. Solutions:

  1. Remove the persistent object from destination rooms (keep only in start room)
  2. Use instance_number(obj_player) > 1 check and destroy duplicates
  3. Use a Controller pattern: one persistent Game Manager spawns player in each room
// obj_player Create event (runs once on first spawn)
if (instance_number(obj_player) > 1) {
    instance_destroy();
    exit;
}

Step 4: Controller pattern. One persistent obj_game_controller manages game state, spawns the player on Room Start:

// obj_game_controller Create (persistent, placed only in start room)
global.game_started = false;

// obj_game_controller Room Start event
if (!instance_exists(obj_player)) {
    var p = instance_create_layer(
        room_start_x, room_start_y, "Instances", obj_player);
    // Assign persistent data
    p.hp = global.current_hp;
    p.max_hp = global.max_hp;
}

Controller manages lifetime; globals hold state; player is non-persistent but spawned with saved state. Clean separation.

Saving to Disk

Persistent objects and globals survive room changes but not game quit. For save games, serialize globals to a file:

function save_game() {
    var data = {
        gold: global.gold,
        hp: global.current_hp,
        inventory: global.inventory
    };
    var file = file_text_open_write("save.json");
    file_text_write_string(file, json_stringify(data));
    file_text_close(file);
}

“Persistent for behavior, global for data. Both together for state that follows the player across rooms and sessions.”

Related Issues

For save-related issues, see GameMaker DS List Not Persisting Save. For alarm behavior, GameMaker Alarm Not Firing.

Globals for data. Persistent for behavior. Controller pattern to tie them.