Quick answer: A GameMaker timeline moment is measured against timeline_position, which advances by timeline_speed per step — not by real frames. If timeline_speed is anything other than 1.0, moments fire earlier or later than their labelled step. If timeline_running is false (common after the timeline finishes once), nothing advances at all. Check those three built-in variables before anything else.
You author a boss fight as a timeline: moment 0 plays an intro, moment 60 spawns minions, moment 180 triggers a telegraphed attack. You assign the timeline to the boss instance and start the fight. Step 60 passes, but the minions never spawn. Or worse, they spawn at step 90 the first time and step 45 on a retry. This article walks through the five variables that decide when a timeline moment actually runs.
The Symptom
Timeline moments fire at the wrong step number, or never fire at all. Sometimes the first run works, subsequent runs do not (or vice versa). Debug output of timeline_position does not match the step count since the object started running the timeline.
A particularly confusing case: the timeline fires correctly in the IDE debugger but not in a built executable. Or the timeline works when you start the game fresh, but stops working after you return to the menu and re-enter the level.
What Causes This
1. timeline_speed not 1.0. timeline_speed is a built-in per-instance variable controlling how many timeline steps happen per game step. Default is 1.0; any other value shifts when moments fire. A value of 0.5 means moment 60 fires at game step 120. A value of 0 stalls the timeline entirely.
2. timeline_running false. After the timeline’s last moment, timeline_running automatically sets to false. If you try to start the timeline again by setting timeline_position = 0 alone, it will not advance because timeline_running is still false.
3. timeline_index was not assigned. Assigning a timeline requires setting the timeline_index variable, not just timeline_running. A fresh instance starts with timeline_index = -1.
4. timeline_loop expected but not set. If you want the timeline to repeat, you must set timeline_loop = true. Without it, the timeline runs once and stops at the final moment.
5. Paused instance or deactivated instance. An instance created with instance_deactivate_object does not run its Step event, so timelines on it do not advance. Same for any pause system that gates the Step event with if (!game_paused) ... without explicit timeline handling.
The Fix
Step 1: Instrument the three key variables. Before anything else, prove what GameMaker thinks is happening.
/// Step event on obj_boss
if (keyboard_check_pressed(vk_f1)) {
show_debug_message("timeline_index = " + string(timeline_index));
show_debug_message("timeline_running = " + string(timeline_running));
show_debug_message("timeline_speed = " + string(timeline_speed));
show_debug_message("timeline_loop = " + string(timeline_loop));
show_debug_message("timeline_position = " + string(timeline_position));
}
Step 2: Set all five variables explicitly when starting. A “start timeline” helper avoids half-configured states.
/// Script: scr_start_timeline(tl, loop = false, speed = 1.0)
function scr_start_timeline(tl, loop, speed) {
timeline_index = tl;
timeline_position = 0;
timeline_speed = speed;
timeline_loop = loop;
timeline_running = true;
}
/// Create event on obj_boss
scr_start_timeline(tl_boss_phase_1, false, 1.0);
Step 3: Rewind properly for retries. Setting timeline_position = 0 alone does not restart a timeline that already finished.
/// Trigger: player dies, boss resets
scr_start_timeline(tl_boss_phase_1, false, 1.0);
// NOT: just timeline_position = 0. That leaves timeline_running = false.
Step 4: Handle pause correctly. If you use a global paused flag, decide whether timelines should pause too.
/// Step event on obj_game_controller
if (global.paused) {
// Stop all timelines but remember their state
with (all) {
if (timeline_index != -1 && timeline_running) {
saved_timeline_speed = timeline_speed;
timeline_speed = 0;
}
}
} else {
with (all) {
if (variable_instance_exists(id, "saved_timeline_speed")) {
timeline_speed = saved_timeline_speed;
}
}
}
Step 5: Put your moment code in the right slot. A common trap: moment code references an instance that was destroyed after the timeline started. Inside a timeline moment, always guard instance references.
/// Timeline tl_boss_phase_1, moment 60: spawn minions
if (instance_exists(obj_spawn_point_a)) {
with (obj_spawn_point_a) {
instance_create_layer(x, y, "Enemies", obj_minion);
}
} else {
show_debug_message("Spawn point missing at moment 60");
}
Step 6: Account for room_speed. Timeline moments are measured in timeline steps, which are tied to game steps, which are tied to room_speed. A timeline written assuming 60 fps runs half as fast in a 30 fps room and twice as fast in a 120 fps one. If your game supports variable rates, author timelines in seconds and convert: moment = seconds * room_speed.
Why This Works
GameMaker’s timeline system is a lightweight scheduled-callback mechanism. Each step, for every instance with timeline_index != -1 and timeline_running == true, GameMaker advances timeline_position by timeline_speed. It then runs any moment whose step number lies in the old-to-new position range. This is why a timeline_speed of 0.5 spreads moments across twice as many frames — the position crosses each integer once every two frames.
The automatic timeline_running = false at the end of the timeline is a sensible default for one-shot cutscenes, but it is the single most common cause of “timeline does not work the second time.” Always flip it back on explicitly when restarting.
Pause handling matters because the Step event is the only time timelines advance. Freezing the Step event (via instance_deactivate) freezes the timeline. Setting timeline_speed = 0 is a cleaner pause because the instance still processes its Step event and can respond to input or UI events.
"Treat timelines as state machines with four inputs: index, position, speed, running. Lose any one and the whole thing goes silent."
Related Issues
For sprite animation timing issues, see Fix: GameMaker image_index Not Advancing. If alarm events misbehave alongside timelines, check Fix: GameMaker Alarm Event Not Firing.
index + position + speed + running + loop. Miss one, miss everything.