GameMaker: Studio is a game creation studio focused on 2D games.

The following is from

GameMaker uses the GML language, which I assume stands for GameMaker Language.

[Changes from version 1.4 to 2]


Game Maker Studio 2

Each workspace gets its own tab. You can drag tabs out to be their own window, and drag them back in to be tabs.

Navigate workspace chains:
Ctrl + Alt + ArrowKey: to move left/right along a chain. The selected subwindow is centered in your view.

Ctrl + Shift + NumberKey[1-9]: sets a bookmark on the window or line of code.
Ctrl + NumberKey[1-9]: Go to the selected bookmark.

Bookmarks only last for the current session; they are not saved on the project.


global.myVar = 5;

Convention is to declare and set all your global variables in one script during the Room Start Event.

GameMaker provides several global-scope variables that you can use without 'global.': score, health, lives.

Avoid naming instance variables with the same names as global variables.

! Verified that local variables can be the same name as global variables without causing error.

Init Room

The best advice I've seen for ensuring that your game initialize code (such as setting global variables) is run before anything else, is to use an Init Room.

This is an empty room that just have your initialize code in the Room Create Event. Then it automatically goes to your actual first room.

Otherwise, you have to keep the initialize code in the first object creation code to be run in the first room, which could change as you develop the game.


This is the suggested code, but it DOES NOT WORK for global variables nor to instance variables.

if(variable != undefined)

Version 2: instance variables:

if(variable_instance_exists(instance_id, string_variable_name))

var instance_variable = variable_istance_get(instance_id, string_variable_name); //returns undefined if variable does not exist

variable_instance_set(instance_id, string_variable_name);

Version 2: global variables:


var global_variable = variable_global_get(string_variable_name); //returns undefined if variable does not exist

variable_global_set(string_variable_name, value);


Had a bug like this:

var myArray;
myArray[0] = script_execute(scr_MakeCoordinate, -1, -1);
//for each row, col
    var coordinate = script_execute(scr_MakeCoordinate, row, col);
    //if something
    myArray[array_length_1d(myArray)] = coordinate;
I ended up with an array of length 2, where the second element changed each time I changed the coordinate variable.
So it was acting more like a pointer than a local variable.
Data Types


"undefined" is the null value in GMS.


Convert number to string

var myString = string(myNumber);

Numbers are stored with 32-bits, signed, so the upper limit is just over 2 billion (2,147,483,647). Overflow loops back through zero. ** I suspect the limit is actually lower due to problems with (11334 div 86400000) **

Convert large numbers to 64-bit when needed.

var x = int64(numA) + int64(numB);

Convert ascii code to character

var myChar = chr(ascii);



var length = string_length("fullString");

Find substring. Returns 0 if substring not found, else returns 1-indexed position.

var position = string_pos("subString", "fullString");

Get character at 1-indexed position. Returns "" if index is out of range.

var character = string_char_at("fullString", index);

Get substring. StartIndex is 1-based.

var substring = string_copy("fullString", startIndex, length);

Convert string to number

var num = real(myString);

Convert char to ascii number

var ascii = ord(myChar);

var upperCase = string_upper("string");
var lowerCase = string_lower("string");

Array Version 2

An array can contain multiple data types at once, including other arrays.


var myEmptyArray = [];
var myArray = ["x", 3, 5.7, ["abc", "def"]];

Array Version 1.4

An array can contain multiple data types at once.

Initialization is as you need it.

var myArray;
myArray[0] = 1;
myArray[1] = 56;

These are invalid ways of initializing an array.

var myArrayA = [];

var myArrayB = [1, 2, 3];

Array length

var lengthA = array_length_1d(arrayA);

var heightB = array_height_2d(arrayB); //refers to first dimension
var lengthB = array_length_2d(arrayB, heightIndex); //refers to second dimension for a specific first index

If you want a script to edit an array, you can pass the array in as an argument and then you must return the edited array.

myArray = script_execute(scr_EditArray, myArray);


Enums are implicitly global.
Enums have static values.

By default, enums are numbered 0 to N. You can also specify the integer values.

enum Colors { Red, Orange, Yellow, Green, Blue, Purple };

enum Styles { Bold=1, Italic=2, Underlined=4, Superscript=8 };

var x = Colors.Red;
var y = Styles.Italic;


Game Information

The game information window is a text scratch pad for the developer. It will not be visible to the player.

Thoughts on keeping code organized within GameMaker:

Do not put event code into objects. Have all objects call scripts even for simple tasks. That way you don't have to remember what is in the object and what is in a script.
- Exception: event_inherited() stays in the object
Ditto for room creation code.

Organize scripts into logical groups under parent scripts. If there is no logical script to make the parent, create a well-named dummy script to provide a name for the group.

Create a sprite folder per category, such as Buttons, Labels, Animations.
Create corresponding object folders.

Edit: maybe not. GameMaker does not allow drag-n-drop to move sprites into or out of a folder. You'd have to recreate the whole sprite to "move" it in the organization structure.

Start with an empty Initialization Room and make sure it is the first in the list so it is run first. Put all initialization code in this room's creation event to guarantee it is run before anything else. Then move to the real first room.

(5: Warning)
If you name a sound file "music" and you also have an included file called "music.ogg", the sound file will be set to "undefined" and will not run.

A single image, or a sequence of images creating an animation.

Sprites are applied to objects to make them visible.

Prefix sprite names with "spr_" for legibility.

Sprites can be loaded from JPG, BMP, PNG, GIF, SWF vector sprites, and Spine JSON skeletal animation sprites.
It is recommended to use PNG or BMP over JPG due to superior image quality.

Before importing an animation strip, give the suffix "_stripXX", where XX is the number of tiles in the strip. When imported, this will be automatically broken into XX individual images.

For background music and sound effects.

Accepts Wave (.wav) and MP3 files.

Sounds can be assigned to audio groups, that can be loaded/unloaded in memory all at once and can use the same volume controls.


Wave files are usually used for sound effects because the format allows the sound to be played instantly.

You can also play multiple wave files simultaneously.


Use MP3 format for background music. GameMaker only allows you to play one at a time.


Play a sound resource once. This will only work if your IDE is set to use the old audio engine.


Play any sound resource, possibly in a loop. This will only work if your IDE is set to use the new audio engine.

audio_play_sound(name_of_sound, priority, loopSound);
Lower (lesser) priority sounds may be canceled if too many sounds are playing at once. Priorities are arbitrary integers.

Set sound volume, for all future times the sound is played.
0 = silent, 1 = full volume

sound_volume(name_of_sound, volume);
Sound volume is logarithmic, so ~0.8 is half the volume of 1.

You can also set the default volume per sound in the sound's properties. The properties volume slider appears to be linear rather than logarithmic.

To stop a sound:


Backgrounds are images that you can set as room backgrounds.

Backgrounds can be a single large image, or smaller tiled images. Tiles are preferred by the engine. You can use irregular tile sets.

Image formats accepted are PNG, GIF, BMP, and JPG.

Prefix your background names with "bck_" for legibility.


You can set the bottom-left pixel of the image as the transparent color.

Instances of objects are placed in rooms. Ex: player character, a wall, an enemy, a cloud...

Objects require a sprite to make them visible.

Objects can be given actions that occur on certain events. You can define the behavior of the objects such that they interact with each other automatically.

Prefix object names with "obj_" for legibility.


//two ways to refer to object settings
var x = objectId.setting;

    var y = setting;

Visible: instances start visible or invisible.

Solid: can other objects collide with this one? Only use this for immobile objects.

Depth: higher depth means further in the background, lower means upfront.

Persists: false means instances disappear when the room changes. True means instances persist into the next room and must be destroyed explicitly. Game restart also destroys persistent instances. Deactivated persistent instances do not persist between rooms.

Parent: objects inherit code, actions, and events from their parent.

Mask: masks govern collisions. An object can have a different mask than the default from its sprite.

Uses Physics: the instance is goverened by the physics rules you set up.

Instance Variables

You can create custom instance variables simply by setting a value to an undeclared variable name. Each instance of the object will have its own value.

life = 5;
name = "John Smith";

The rest of these are built-in instance variables.

id: unique object id (number)

self: the current instance - you do not need to say "self" in object actions, just use the self variables directly

x: current x position
y: current y position

sprite_index: id of sprite assigned to object. -1 means there is no sprite, in which case the dimensions may be reported as zero and/or infinity.

sprite_width: read only; updates to display width when image_xscale is changed
sprite_height: read only; updates to display height when image_yscale is changed

image_speed: the rate at which the sprite animation is run. Set to zero for freeze frame. Set to 1 to cycle one image per game step.
image_index: the index of the current sprite animation frame. Index starts at 0.
image_alpha: control transparency, 0 to 1 with 1 being fully opaque.

speed: velocity in pixels per game step
direction: direction of motion in degrees. 0 = right, 90 = up, 180 = left, 270 = down

image_xscale: change width of image; 0.5 = half normal width; -1 = normal width but flipped
image_yscale: change height of image

image_angle: degrees of rotation counter clockwise (if object has a draw event, read more)

object_index: the object index of the object this is an instance of

var objectName = object_get_name(object_index); //returns the string name of the object

var objectName = string(obj_name);

var assetIndex = asset_get_index("object_name"); //returns index of asset, or -1 for not found
//asset index of an object == object index of its instance


Object instances can be added to a room in the room edit window, if you know the object must be present.

Version 2: Create object instance in script:

var instance_id = instance_create_depth(x, y, depth, object); //create instance at depth

var instance_id = instance_create_layer(x, y, layer_id_or_name, object); //create instance on layer

Version 1.4: Create object instance in script:

var instanceId = instance_create(x, y, obj_myObject); //object names are keywords not strings
with(instanceId) //creates local scope
    speed = 5;




If you don't know the object id of the object you want to find, you can search for it like this. Index starts at zero.

var index = 0;
var ithObjectId = 0;
while(ithObjectId != noone) //keyword
    ithObjectId = instance_find(obj_nameOfObject, index);


Objects can inherit events, actions, and code from parent objects.

Objects DO NOT inherit the sprite from their parent.

When events occur, they can trigger actions in objects.

As long as the game is open, the game loop is iterating. A step is the smallest unit of time in the game loop. A series of events can be triggered every step. The exact order of events each step is not reliable.


Objects inherit all events from their (optional) parent object. If an event defined in the parent is also defined in the child (ex: Create Event) then the child event will override the parent event and the parent event will not be run.

You can explicitly run the parent event code inside the child event code, so that both will be run.

//inside child event
event_inherited(); //runs the parent event of the same type

User Events

Each object can have up to 16 user events defined on it. User interactions are not linked to user events, they can only be triggered programmatically.

Trigger user event:

event_user(index); //index 0 through 15
Note: don't say "self.event_user", just "event_user".

User events (like all events) do not accept arguments and do not return values.

User events use inheritance the same as other object events.

Enter Room

These events always happen in the same order.
1) Create - for each instance
2) Instance Creation - for each instance
3) Game Start (only in very first room)
4) Room Creation
5) Room Start - for each instance

In a room, you can set the order of instances being created.


These events always happen in the same order.
1) Begin Step
2) Step - just before instances are put in their new positions
3) End Step


GameMaker has a large list of standard actions that can occur on an event. You can also code your own.

Self: refers to the current instance.
Other: refers to the other instance in a collision event.
Object: referes to all current instances of this object.

Relative: delta values are relative to current values, instead of absolute.


Current mouse position

var mouseX = mouse_x;
var mouseY = mouse_y;


Given a stack of overlapping objects, many of them having a mouse event triggered by the same mouse-button-event, how do you stop the event from propagating through the whole stack?

So we want the mouse event to start at the top of the stack and stop at the first object that takes an action on it. There are conditions when a higher object does and does not take the action.

Example is for event on right-button-released.

//in first action
    var x = mouse_check_button_released(mb_right); //true
    mouse_clear(mb_right); //clears mouse event
    //normal action code

//in second action - which does still trigger despite clearing the mouse event
var y = mouse_check_button_released(mb_right); //false
    //action that only occurs if first event did not trigger

The problem is that GameMaker makes no guarantee about what order the objects will be handled in. It isn't necessarily ordered by depth, although it often seems to be.

So, instead, you can set a global mouse event handler that checks the whole room for what was clicked on, and enforces the correct order. Note that this will not work reliably if it is possible for more than one instance of a particular object to be clicked on at the same time, because instance_position returns at most one id.

To make a global event handler, add a normal object to the room and set it's Global Mouse Events. They will be triggered if the mouse clicks anywhere in the room.

var objectClicked = instance_position(mouse_x, mouse_y, obj_set); //was an instance of this object clicked?
if(objectClicked == noone)
    return false; //no, it was not
//yes it was, run event code here
return true;


Key down: triggers repeatedly as long as you hold the key down.
Key press: triggers once when the key is pressed down.
Key up: triggers once when the key is released.

var charCode = keyboard_key; //get the last pressed key
var char = chr(keyboard_key); //convert ascii code to character
Note that all letters come in as upper-case, regardless of the state of caps lock or shift keys.

var aDown = keyboard_check(ord('A'));

There does not seem to be any way to check if caps lock is on or off (just if the button is currently pressed down or not). So just looking at shift keys for now.

var isUpperCase = (keyboard_check_direct(vk_lshift) || keyboard_check_direct(vk_rshift));

Keyboard constants: vk_nokey, vk_anykey, vk_left, vk_right, vk_up, vk_down, vk_enter, vk_escape, vk_space, vk_shift, vk_control, vk_alt, vk_backspace, vk_tab, vk_home, vk_end, vk_delete, vk_insert, vk_pageup, vk_pagedown, vk_pause, vk_printscreen, vk_f1 ... vk_f12, vk_numpad0 ... vk_numpad9, vk_multiply, vk_divide, vk_add, vk_subtract, vk_decimal, vk_lshift, vk_lcontrol, vk_lalt, vk_rshift, vk_rcontrol, vk_ralt


A room is like a screen or a page. A menu, credits, tutorial, starting room, etc.

Rooms can contain a background image and instances of objects.

The first room in the list of rooms will be the room the games starts with.


room_width: width of current room in pixels
room_height: height of current room in pixels


room_set_background_colour(rm_myRoom, colour, true); //true means "make visible"
You cannot set the color of the current room.

Scripts are custom GML named functions.

A script action can pass up to 5 arguments. The code editor can pass up to 16 arguments. Argument types are real, string, boolean, and special.

//Version 1.4 or 2
script_execute(scr_myScript, arg0, arg1, ...); //script names are keywords not strings

//Version 2
scr_myScript(arg0, arg1, ...);

Scripts can be imported from *.txt files. Scripts in GameMaker are saved as *.gmx.

If you make this syntax error, you can get strange behavior, like an entirely different script being called (this happened to me).

script_execute(scr_myScript(arg0, arg1));


Syntax looks like basic JavaScript.

All variables are declared 'var'.
Lines end in ;
//Comments /*Comments*/

Naming a code box - custom code in an object action

///The Action Name
//place that line at the top of the code


var x = argument[0];

var count = argument_count; //number of arguments passed in


The scripts resource tree does not allow subfolders. It allows child scripts. That means that a script in the tree, when opened, could contain several child scripts that do not show up in the tree, but can be called like normal. The parent script and child scripts all display as tabs in the parent script editor.

To add a child script to a parent script, open it and click on the <plus empty tab> that is next to the open tab.


You can search for text within a script by opening the script and using the Search feature there.

You can search all scripts (anywhere that can contain code) at once from main menu Scripts > Search Scripts. Double-clicking on a result will open that script to the indicated line.

Common Commands


In GameMaker, macros are global constant variables. They can also contain functions.

Name macros with all-caps for legibility.

Values can be a number, a "string" in quotes, or a function call with arguments specified (arguments must all be global as well).

As of Game Maker 2, macros are listed under the Scripts tree and are defined in code.

    #macro VARIABLE_BEST_TIME "BestTime"
    #macro DEFAULT_BEST_TIME -1
    #macro BEST_TIME_COUNT 5
Note: No equal signs, No semicolons.

GameMaker comes with Arial 12pt font included. For any other font, you'll need to add it.

Prefix your font name with "fnt_" for legibility.

Include in Asset Package: only use this if you have licensed the font for distribution. You usually won't use this.

When you include the font in the package, the actual font file is distributed with the program. If you don't do this, you are actually saving a sprite of each character (in range) in the font.
Note: as of July 2019, you cannot include a character lower than 32 (space).


The range specifies which ASCII characters will be included in the font. If you know you only need a small range, specify it.

Display Text

Usually, all draw commands must be within an object's Draw event. An instance of this object must be in the room, drawing the text. The text must be drawn within the visible area of the instance.

draw_set_colour(c_black); //set font color to black
draw_set_alpha(1); //0 = fully transparent, 1 = fully opaque
draw_text(x, y, "text");

Special character '#' will cause a line break in the text.
Special character '\#' will display as a hash sign.

Multiline text

draw_text_ext(x, y, "text", pixelsBetweenLines, maxPixelWidthBeforeLineBreak);

Text alignment

draw_set_halign(fa_left); //constants: fa_left, fa_center, fa_right
draw_set_valign(fa_top); //constants: fa_top, fa_middle, fa_bottom

String height

var height = string_height(text); //returns pixel height of string based on current font

String width

var width = string_width(text); //returns pixel width of string based on current font


Set global variable cursor_sprite to any loaded sprite index.
The default cursor is -1;

The sprite image_index and image_speed cannot be set.

cursor_sprite = spr_myCursor;


Set game to register a left-double-click as a single-right-click.

If user is on a Mac, their computer settings may override this and (for example) set a two-finger-left-click as a single-right-click. If so, it will register correctly in the game.

Operating System (OS)

To check what OS the game is running on:

if(os_type == os_windows)
if(os_type == os_macosx)


Here's what I've used to access my Included Files on each OS.

var filename = working_directory;
if(os_type == os_windows)
    filename = filename + "\\" + myIncludedFilename;
else if(os_type == os_macosx)
    filename = filename + "_" + myIncludedFilename;
For some reason, Mac prefixed my included files with "_".

You can create named layers in a Room.

You can also create layers through scripts.

Do not try to manually manage Depths and use Layers at the same time. It looks best to use one or the other.

Types of Layers:
1. Instance Layers may contain instances of objects. Use this instead of depth settings.
2. Asset Layers may contain sprites without objects. This can be used for special animations, color blending, and transformations.
3. Tile Layers may contains tiles. They provide faster collision detection and ?word building?.
4. Background Layers may contain sprites. This is where you put your background images. They may be animated, stretched, and/or tiled.
5. Path Layers may contain one path each. They are only for editing paths within the IDE, not for runtime use.

At runtime, these differentiations disappear. You can put things where you want them to go, but I expect it is best to stay organized.

For named layers created in the Room Editor, depths are automatically set 100 units apart from each other.

Get id of named layer:

var id = layer_get_id(name);

Create layer at runtime:

var id = layer_create(depth);

Get depth of layer:

var depth = layer_get_depth(layer_id);

Get the element ids of everything on a layer:

var id_array = layer_get_all_elements(layer_id_or_string_name);
These ids may be for object instances, backgrounds, sprites, tile maps, tiles, or particle systems.

Toggle visibility of entire layer:

layer_set_visible(layer_id, bool);
var is_visible = layer_get_visible(layer_id_;
Does this affect user interaction events?

Views are used to show part of a room when the room is larger than the display.
You can show a view scaled or 1:1.

You can have up to 8 views of the same room active at once.
Included File

You can include miscellaneous files with the final game. Locally, the files are stored in *.gmx/data-files.

Included files can be organized into a folder structure.

Included files can be marked included/excluded for various game platforms.


Right-click on an included file and select "Properties" or "Edit" to set which platforms this file will be included with. The default seems to be "All".

Read Text

Filename is relative to the Included Files tree root.

var fileId = file_text_open_read(working_directory + "\" + filename);

    var line = file_text_readln(fileId);




The window is the application window.

"true" will expand window to full screen.
"false" will shrink window to its previous non-full-screen size.

window_set_size(width, height);
Window contents will be automatically scaled to fit a 1:1 ratio to the background image. It works better to change the window size programmatically than to let the user manually change it.

var width = window_get_width();
var height = window_get_height();


The display seems to be the entire screen.

var width = display_get_width();
var height = display_get_height();


In Global Game Settings > Windows > Graphics, you can set the options "Allow the player to resize the game window" and "Allow switching to fullscreen".

To allow full screen size in Mac, the default Game Setting must be "start in full screen mode".

Console Message

Output to console log.

show_debug_message("Text: " + string(numberVar));

User Message

Output popup message to user with an "Ok" button.

show_message("Error: my error message");

Throw Error

show_error(message, bool);
Set bool to true to end the program immediately.

You'll see the error message and the location of the error in the dialog that pops up.


You can only have one ini file open at a time. Data is not saved until the close function.

You're INI files can be called anything valid.

Save example

ini_open("saveData.ini"); //open file or open empty file
ini_write_real("SectionHeader", "variableNameA", value); //save a number
ini_write_string("SectionHeader", "variableNameB", value); //save a string
If the file did not exist, and you wrote to it, it will be created

Load example

ini_open("saveData.ini"); //open file or open empty file
var a = ini_read_real("SectionHeader", "variableNameA", defaultValueA);
var b = ini_read_string("SectionHeader", "variableNameB", defaultValueB);

Use "real" for numbers and booleans.

If Else

if(x > y)
else if(a > b)

Version 2 introduced ternary operator:

var a = (b > 0) ? 15 : -1;

Do Until

} until(x > 100);


for(var i = 0; i < 10; i++)




    case 0: break;
    case 1: break;
    default: break;


Enter scope of instance by id

    //now in instance local scope
You can also access the instance variables directly

instanceId.myVariable = 5;

Iterate through all instances of an object

    //now in each instance local scope


Exits the current script, and may return a value.


Exits the current script. If this script was called from an object event, it also exits the entire event.


Restarts the game: runs Game End event, runs Game Start event. Does not reset global variables automatically, you'd have to code that.



Ends the game, exits the game. Finished the current Step and runs Game End event first.


This method is against the restrictions of the Windows 8 and iOS marketplaces, because it causes an error. It will silently fail on the HTML5 module.

This method is intended for Steam Workshop, Windows, Windows Phone, Android, Linux, and Mac.
Misc Functions

Min Max

var myMin = min(numA, numB, numC, ...);
var myMax = max(numA, numB, numC, ...);


GameMaker always initialized with the same random seed. Therefore, you must run randomize at the beginning of your game to get a new random seed.


Get random decimal from 0 to limit, not including limit

var a = random(limit);

Get random decimal from min to limit, not including limit

var a = random(min, limit);

Get random integer from 0 to max, including max

var a = irandom(max);

Get random integer from min to max, including both

var a = irandom_range(min, max);


Comparisons and arithmetic function as expected.

div: integer result of division

var x = 60 div 49; //1 because 49 fits into 60 once
var y = 60 div 100; //0 because 100 doesn't fit into 60

mod: remainder result of division

var x = 60 mod 49; //11
var y = 60 mod 100; //60


Note that drawing is not limited to the region of the current object. It'll let you draw anywhere on the screen in the "Draw" event of an object.

draw_set_alpha(1); //1=100%

Colour constants: c_aqua, c_black, c_blue, c_dkgray, c_fuchsia (sp?), c_gray, c_green, c_lime, c_ltgray, c_maroon, c_navy, c_olive, c_orange, c_purple, c_red, c_silver, c_teal, c_white, c_yellow

Make custom colors

var myColor = make_colour_rgb(red, green blue);

draw_text(x, y, text); //(x,y) = upper-left corner of text

draw_rectangle(x1, y1, x2, y2, false); //false means FILL, true means OUTLINE


To display the current time, in the default time zone:

var hour = current_hour();
var minute = current_minute();
var second = current_second();

To display the current date:

var month_day = current_day(); //value 1 to 31
var week_day = current_weekday(); //value 0=Sunday to 6=Saturday
var month = current_month(); //value 1 to 12
var year = current_year();


Returns the number of microseconds since your game started (1 million microseconds per second).

var microseconds = get_timer();

Returns the length of one STEP in microseconds, so you can account for different computer speeds.

var microseconds = delta_time();

Icon files (.ICO) include multiple copies of the image, at sizes 16x16, 32x32, 48x48, and 256x256 pixels.

To create an ICO file from Inkscape:
    1) save the image at each size
    2) install ImageMagick
    3) in console, run "magick convert 16.png 32.png 48.png 256.png icon.ico"
    4) verify the file is correct with "identify icon.ico"
If you don't want to save multiple sizes from Inkscape, you can use ImageMagick for that, too.
    1) "magick convert master.png -resize 32x32 32.png"
To load the icon into GameMaker:
    1) open Global Game Settings
    2) in the Windows tab, update the Game Icon
    3) probably the same thing on the Mac tab


Assumes you are running Game Maker on Windows.

To make an executable installer:
1) File > Create Application
2) Select Windows NSIS Installer
3) Save
4) Run the installer to install the game on Windows

Publish With Steamworks

Version: Game Maker 2 with Steamworks SDK 1.42


Windows files locations:
- Steam games are installed at "Program Files (x86)\Steam\steamapps\common\"
- Steam game icons are saved at "Program Files (x86)\Steam\steam\games\"

Steamworks locations:
- Your Steam App Id is the number in parentheses after your game name in the "Unreleased Apps" table on
- It is also visible at the end of the url for the Steamworks pages for your app

Check [ > Guides > GMS2 Required SDKs] for updates to what Steamworks SDK goes with what version of Game Maker.

Good walkthrough of store page setup and steps to release game:

More references:
Watch (how to use Steampipe to upload games to Steam)

Steamworks SDK

One-time setup:
1) Download the version of the Steamworks SDK specific to your operating system.
2) Unzip the sdk to a stable location

1) ...there's a thing you need to run once...

1) open Terminal > navigate to sdk/tools/ContentBuilder/builder_osx/osx32/
2) run "chmod +x steamcmd"
3) in Terminal still > navigate to sdk/tools/ContentBuilder/
4) run "sh ./builder_osx/"
(to open Terminal, open Finder > Applications > Utilities > Terminal)

Per-game setup:
1) Navigate to Steamworks sdk folder > tools > ContentBuilder > scripts
2) rename the "app_build" script to include your game's App Id
3) edit the app_build script
- - replace the default App Id with your App Id
- - edit Description if you want to (it will show up on Steamworks App Admin > Edit Steamwork Settings > SteamPipe tab > Builds page)
- - under Depots, make sure the actual Depot Id and app_depot script filename are set
4) rename the "depot_build" script to include your game's Depot Id for this platform
5) edit the depot_build script
- - replace the default Depot Id with your Depot Id
- - set Content Root to the full path to the SDK's ContentBuilder folder
- - set Local Path to a folder such that everything inside the folder will be packaged for this depot
- - - the starting . location of Local Path is the Content Root folder
- - - so I added a Windows_Content folder there and set Local path to ".\content\Windows_Content\*"
6) copy all files from your Game Maker build to that "Local Path" folder
7) navigate to Steamworks sdk folder > tools > ContentBuilder
8) rename default run_build.bat to run_build_<game>.bat
9) edit run_build_<game>.bat
- - replace "account password" with just your Steam username (this will prompt you to enter your Steam password when the command is run)
- - replace "app_build_1000.vdf" with "app_build_<yourAppId>.vdf"
- - add line "pause" at the end so that you can read any messages before the command prompt closes
- - (Mac only) make sure it starts with "builder_osx/steamcmd +login"


Instructions valid as of 6/25/2018.

Download the Steamworks SDK and unzip it to a stable location.

Game Maker > Game Options > Main Options > General
- set the "Steam Id" to your Steam App Id

Game Maker > Game Options > Platforms > Windows
- check "Enable Steam"

Game Maker > File > Preferences > Platform Settings > Steam
- set the "Steam SDK Location" to the "sdk" folder that was part of the Steamworks SDK download
(You should now be able to run your game from Game Maker and use SHIFT+TAB to open/close the Steam overlay. That will prove you have setup Game Maker with Steamworks properly.)

Steamworks home is at
Steamworks App Admin > Edit Steamworks Settings
- fill in Application Name, Application Type, Supported Operating Systems, and anything else applicable
Steamworks App Admin > Edit Steamworks Settings > Installation tab > General
- fill in Installation Folder
- click "Add New Launch Option"
- - set Executable to the actual name of the executable
- - set Operating System
- - if the game will run on multiple platforms, add one Launch Option per OS
- - - for Windows, I used
- - - - "<game>.exe"
- - - - Launch Type "Launch (Default)"
- - - - Operating System "Windows"
- - - - CPU Architecture "Any"
- - - for Mac, I used
- - - - "<game>.app\Contents\MacOS\Mac_Runner"
- - - - - "<game>.app\Contents\MacOS\<game>" was recommended but did not work
- - - - Launch Type "Launch (Default)"
- - - - Operating System "Mac OS X"
- - - - CPU Architecture "Any"
- - - for Linux (haven't verified)
- - - - "<game>.x64"
- - - - Launch Type "Launch (Default)"
- - - - Operating System "Linux"
- - - - CPU Architecture "Any"
Steamworks App Admin > Edit Steamworks Settings > SteamPipe tab > Depots
(a depot is a package of all the files Steam will download when the user downloads a game)
(you can have several depots under one Steam App Id)
- on the default depot, set the name to "<game> Depot Windows", set OS to Windows
- click Add New Depot
- on the new depot, set the name to "<game> Depot Mac", set OS to Mac
- click Save
Steamworks App Admin > Edit Steamworks Settings > Publish tab
(yes you do this before uploading game files to Steam)
(if your game is already released, this will affect your users)
- click Prepare For Publishing > enter the confirmation text > click Really Publish
- - there should be a message at the bottom of the page like "Publishing successful"

Follow instructions for uploading files from each operation system before continuing here.

Steamworks App Admin > click "Edit Steamworks Settings" > SteamPipe tab > Builds
- you can click on a Depot Id to see a list of files in the depot
- for the depot that customers should download by default, set "Set Build Live on Branch..." to "default" for that depot
- click "Preview Change"
- - if you then click "Set Build Live Now", then your build will be set live to users
- - if your game is unreleased, this will not make your game live to customers
- click "Set Build Live Now"

If you are uploading more than one depot, set the first depot's build as default, then set the second depot's build as default. Steam will automatically combine the two builds into one default build.

open Steam normally on your desktop > open Library > install your game
play-test your game

You can update a game even after it's release by uploading a new build, setting it as the default, and setting it live. The changes will be auto-downloaded when the user next opens Steam.
Steamworks ratings for games
if you do not have an official rating from an agency, leave the rating blank
- - from > App Admin > Steamworks Settings > Community menu > Assets
- - setup the community capsule (jpg file) and icon (ico file) > App Admin > Steamworks Settings > Installation menu > Client Images
- - setup all these images
(this is the icon that will be used when installing the game, the Game Maker icon setup is irrelevant)
set pricing at App Admin > All Associated Packages... > select package > Propose Pricing
- - it will take about a day for Steam to approve proposed prices

recording game trailer in Windows 10
1) open game
2) type Window+G to open XBox game bar
3) type Window+Alt+R to start recording
4) type Window+Alt+R to stop recording again
5) click the folder icon to open the location the recordings are saved to

Assumes you are running Game Maker on Windows.

Assumes you've already setup the Windows Steamworks SDK.

Export executable from Game Maker:
1) Click the "Create Executable" button in the toolbar
2) Save the compressed zip file
3) Extract the compressed zip
4) Copy the extract files to the "Local Path" location listed in your "depot_build" script

Upload game to Steamworks:
1) navigate to Steamworks sdk folder > tools > ContentBuilder
2) run batch file "run_build_<game>.bat"
- - you should get a message like "Successfully finished appId <your app id> build (BuildId <build id>)
Your Windows build has now been uploaded to Steamworks.
Mac: One-Time Setup

Assumes you are running Game Maker on a Mac.

Assumes you've already setup the Mac Steamworks SDK.

General Setup:
1) Get an Apple Id
2) Get an Apple Developer Account
3) Associate your Mac account with your Apple Id
4) Mac desktop > click on the Apple icon in the upper left corner > System Preferences > Users & Groups > select your user and set the Apple Id
- - (I couldn't get this option to show up for me, so I only have the Apple Id set in XCode)
5) Install XCode on the Mac (requires MacOS version 10.13.2 or later)
6) Link your XCode to your Apple Id (this is so the right certificates are loaded)
- - XCode > Preferences > Accounts > add Apple Id account

You will need to set up Apple certificates on your developement Mac, even if you aren't selling your app through the Apple App Store.

You'll need one User Certificate per development Mac - it will be used for all games developed on the computer.

You'll need one Development Certificate per development Mac to test your game locally.

You'll need one Distribution Certificate per development Mac to publish your game.

Setup Apple User Certificate:
1) from your Mac > sign into > Account with Apple Id
2) click Certificates, IDs, and Profiles
3) click Certificate Signing Request
4) select iOS App Development under Development
5) select App Store and Ad Hoc under Production
6) follow the instructions for requesting a User Certificate
- - do this once per computer, it will be used for all games made on that computer:
- - - Mac desktop > Finder > Applications > Utilities > Keychain Access > Keychain Access menu > Certificate Assistant > Request a Certificate From a Certificate Authority
- - - - User Email Address = your email address
- - - - Common Name = name of certificate such as "John Smith Dev Key"
- - - - CA Email Address - leave it empty
- - - - Request Is = Saved to Disk
- - - click Save
7) back in the browser > Continue > Choose file (select your newly saved certificate request) > Continue
8) Download the certificate to your Mac > double click the downloaded *.cer file > add the files to default (login) keychain > Done

XCode Certificate Types
Apple Codesigning Certificate Types: Names:
- iOS Development: iPhone Developer: Team member name used to run an iOS app on devices and use certain app services during development
- iOS Distribution: iPhone Distribution: Team name used to distribute your iOS app on designated devices for testing or to submit it to the App Store
- Mac Development: Mac Developer: Team member name used to enable certain app services during development and testing
- Mac App Distribution: 3rd Party Mac Developer Installer: Team name used to sign and submit a Mac Installer Package, containing your signed app, to the Mac App Store
- Developer Id Application: Developer Id Application: Team name used to sign a Mac app before distributing it outside the Mac App Store
- Developer Id Installer: Developer Id Installer: Team name used to sign and distribute a Mac Installer Package, containing your signed app, outside the Mac App Store

Setup Apple Development Certificate:
1) Mac desktop > XCode > XCode menu > Preferences > Accounts > select your account > Manage Certificates
- - (you should see your User Certificate listed)
2) click + (plus)
3) click "Developer Id Application"
(This will add a Development Certificate to your Mac

Setup Apple Distribution Certificate:
1) Mac desktop > XCode > XCode menu > Preferences > Accounts > select your account > Manage Certificates
2) click + (plus)
3) click "Developer Id Installer"

That's it, XCode will add the certificates to your Keychain Access.
If you think you've made a mistake, you can delete the certificates and start over.
Certificates can also be Revoked through the Apple Developer webpage.
You can view and delete the certificates at
- Finder > Applications > Utilities > Keychain Access > My Certificates in left-hand sidebar
- - right-click on a certificate > Get Info to view details
- - right-click on a certificate > Delete to delete certificate

Mac: Per-Game Setup

Create an Apple App Id
1) login into > Account > Overview > Certificates, Identifiers, and Profiles
2) click App Ids
3) click + (plus) to add a new one, fill in the form
- - (Apple App Ids are formated as XXX.YYY, where XXX is your Team Id and YYY is a bundle id)
- - App Id Description = name of your App
- - default is to select Explicit App Id
- - Bundle Id = com.<company name>.<app name>
- - select the App Services your game needs
4) click Continue > Register > Done

Your Apple Team Id is visible on your developer Account page > Membership > Team Id

Game Make Settings
1) Game Maker > Preferences > Platform Settings > macOS
- - set Team Id > Apply
2) Game Maker > Preferences > Platform Settings > Steam > set Steamworks sdk location to the "sdk" folder
3) Game Maker > Game Options > Platform Settings > Mac OS
- - set "App Id" to the "com.<company>.<game>" id you created online
- - set "Team Identifier" to the one listed on developer website > My Account as "Team Id"
- - set "Signing Identifier" to the name of your distribution certificate (usually the default of "Developer ID Application:" is fine)
4) Game Maker > Game Options > Platform Settings > Mac OS > Images
- - set 1024x1024 png icon (not required if publishing through Steamworks)
4) Game Maker > Game Options > Platform Settings > Mac OS > Packaging
- - uncheck Build for Mac App Store

Export game from Game Maker
1) Game Maker > Click the "Create Executable" button in the toolbar > save <game>.zip
- - you may need to enter your Mac password into a dialog for Codesign, if so select "Always Allow" because it will keep asking
2) copy the files extracted from that zip to the ContentBuilder/content/Content_Mac folder
3) open Terminal > navigate to ContentBuilder folder
4) run "bash run_build_<game>.bat"
Steamworks Settings
1) Log into
2) navigate to your game's App Admin page > All Associated Packages, DLC, Demos and Tools
3) click on your game's package
4) make sure all your depots are listed in "Depots Included"
5) publish again if you made an changes

If you are testing installation on Mac from Steam, and you need to uninstall and try again, you may need to manually remove the folder \Users\<you>\Library\Application Support\com.<company>.<game>"
- - you can easily go to a file location in Mac with Command+Shift+G

Mac: Icon

Mac icon file format: *.icns

How to make one on a Mac by copying and modifying an existing incs file
1) Go to /System/Library/CoreServices/CoreTypes.bundle/Contents/Resources/
2) Copy one of those icns files to a working location
3) Open the copy in Preview, should see the 4 resolution sizes it contains
4) You'll need 4 sizes of your custom tiff (or png): 16x16, 32x32, 128x128, 512x512
5) For each size:
- - open the tiff in Preview
- - select the corresponding size in the copied icns Preview
- - click the enlarged image itself one time
- - type Command-a to select all
- - type Delete to remove that image
- - click the enlarged image itself in the tiff Preview
- - type Command-a to select all
- - type Command-c to copy the selection
- - click in the empty icns Preview window
- - type Command-v to paste
6) save the icns file when complete