GML Debug Messages

samspade

Member
Using show_debug_message()

GM Version:
All
Target Platform: All
Download: NA
Links: NA

Summary
An explanation of show_debug_message, how to use it, and some helpful utility scripts.

Tutorial
What show_debug_message Does

Debugging is one of the most important skills in coding, and GM comes with a variety of tools to help you. One of these tools is the built in GML function show_debug_message. This function creates a custom message which will be printed in the output window at runtime - e.g. while the game is running.

Real-time information is incredibly useful for understanding how your game is working, a critical aspect of debugging. For example, I often use it to check whether code is running, what order code is running in, and receive updates on the various inner-workings of my projects - such as player or enemy state information.

How show_debug_message Works
show_debug_message accepts both strings and variables, but if you use both strings and variables at the same time, the variables must be converted to a string by using either string or string_format.

The following are valid uses of show_debug_message:

Code:
//single strings
show_debug_message("Hello World");

//multiple strings
show_debug_message("Hello" + " " + "World");

//variables which hold strings
var text = "Hello World"
var saddest_message_ever = "My battery is low and it's getting dark."
show_debug_message(text);
show_debug_message(saddest_message_ever);

//variables which hold strings and strings combined
show_debug_message(text + ". " + saddest_message_ever);

Code:
//single variables
var a = 10;
var b = 5;
show_debug_message(a); //10
show_debug_message(b); //5

//multiple variables
show_debug_message(a + b); //15

Code:
show_debug_message(text + ". I am " + string(a) + " years old."); //Hello World. I am 10 years old.

This is an incorrect use because the variable is not turned into a string.

Code:
show_debug_message(text + ". I am " + a + " years old.");

Utility Scripts
show_debug_message by itself is very useful. However, over time I have found that a number of custom scripts make it even easier to use.
  • print
  • print_start
  • print_end
  • print_instance_id
  • print_object_name
  • print_name_id
  • a
  • b
  • c

print: functions just like show_debug_message except that it automatically casts variables to strings. I prefer it over show_debug_message because it saves on typing and makes things a little more readable. (You could modify this script to automatically add spaces between arguments, but I've left that out of this version.)

Code:
/// print(args...)
/// @description automatically turns non-strings into strings
/// @param args ....

var final_text = "";

for (var i = 0; i < argument_count; i += 1) {
   if (is_string(argument[i])) {
       final_text += argument[i];
   } else {
       final_text += string(argument[i]);
   }
}

show_debug_message(final_text);


///example use
print("Player HP: ", hp, ". Player Shields ", shields);
print_start and print_end are simply visual markers to delineate debug messages. This can be very useful if you are going to use a lot of debug messages in a row.

Code:
///print_start(args...)
/// @description Marks the start of a debug message
/// @param description(s)... string

var arg_string = ""

for (var i = 0; i < argument_count; i += 1) {
   arg_string += argument[i];
}

show_debug_message("\n////////// " + arg_string + " START //////////");

///print_end()
/// @description Print Start

show_debug_message("////////// END //////////\n");

///example use
print_start("Player Health");
print("Player HP: ", hp, ". Player Shields ", shields);
print_end();
print_instance_id, print_object_name, and print_name_id all do exactly what you would think - print the instance id, object type, or both object type and instance id of the calling object. This can be very useful if you have multiple instances running the same debug message.

Code:
///print_instance_id();
/// @description Print the Instance Id
show_debug_message("INSTANCE ID: " + string(id));

///print_object_name();
/// @description Print the Object Type
show_debug_message("OBJECT: " + object_get_name(object_index));

///print_name_id();
/// @description Print Object Name and Instance ID
print_object_name();
print_instance_id();


///example - the following will loop through all enemies
///print out the object name (which is useful if you have more than one type of child)
///print out the specific instance ids of each instance
///and then print their location
if (keyboard_check_pressed(ord("0"))) {
   print_start("Enemy Locations");
   with (enemy_parent) {
       print_name_id();
       print("Enemy location: ", x, y);
   }
   print_end();
}
Finally, scripts a, b, and c are the most basic scripts that I use for simple checks. All they do is print out the letter A, B, or C to the output window along with the current time (useful if you want to call them every step).

Code:
/// @description Debug Script A
show_debug_message("A " + string(current_time));

/// @description Debug Script B
show_debug_message("B " + string(current_time));

/// @description Debug Script C
show_debug_message("C " + string(current_time));

While the simplest, they might be the ones I use the most. Write some code, run the game and nothing happens? Add a() to the code and you can find out if it is running. Have a complex event (maybe in a state machine or over several different objects) and you want to know which code is running in which order? add a(), b(), and c() - or as many as you want - around and see which order they show up.


Being very lazy, I actually have one modification to the above which will only work on GMS 2 due to how it uses macros and it looks like this:

Code:
/// @description Debug Script A
#macro A a();
show_debug_message("A " + string(current_time))
Now all you need type is the letter A to achieve the same results.

Conclusion

Hopefully, this helps, and if you have your own custom debug scripts I would love to hear them.
 
Last edited by a moderator:

immortalx

Member
Nice article Sam. I've made this script sometime ago:
Code:
/// @description print comma seperated strings in output
/// @arg msg

var args = argument_count;
var out = "";

for (var i=0; i < args; ++i)
{
    out += string(argument[i]);
   
    if (i < args - 1)
    {
        out += " , "
    }
}

show_debug_message(out);
 

samspade

Member
I've updated the utility scripts for GameMaker Studio 2.3:

GML:
// Script File for Show Debug Message

#region //macros

#macro A show_debug_message("A " + string(current_time));
#macro B show_debug_message("B " + string(current_time));
#macro C show_debug_message("C " + string(current_time));

#endregion

#region //utility functions

/// @function print(...arg)
/// @param {variables} ....args
/// @description Functions like show_debug_message except that it
///                 automatically turns non-strings into strings and
///                 different arguments are separated by a common.
///                 Example: print("Hello World. This is ", name, "!", " I am ", age);
///                 where name is variable that holds a string and age
///                 is a variable which holds a number.
function print() {
    var final_text = "";
    for (var i = 0; i < argument_count; i += 1) {
       if (is_string(argument[i])) {
           final_text += argument[i];
       } else {
           final_text += string(argument[i]);
       }
    }
    show_debug_message(final_text);
}


/// @function print_start([optional_string])
/// @param {string} optional_string
/// @description A function that can be used make the start of
///                 a debug message in the output window more visible.
///              can take an option argument
function print_start() {
    var _optional_string = argument_count = 1 ? (" " + argument[0]) : "";
    print("\n//////////", _optional_string, " START //////////");
}


/// @function print_end([optional_string])
/// @param {string} optional_string
/// @description A function that can be used make the end of
///                 a debug message in the output window more visible.
function print_end() {
    var _optional_string = argument_count = 1 ? (" " + argument[0]) : "";
    print("//////////", _optional_string, " END //////////\n");
}


/// @function print_object_and_instance_id()
/// @description Print the object id of the instance this scrip is called in.
function print_instance_info() {
    print("INSTANCE ID: ", id, ". INSTANCE OF OBJECT ", object_get_name(object_index));
}

#endregion

If you don't want to copy and paste this into a script file, you can get the free asset here.
 

Appsurd

Member
Perhaps a useful addition (< GMS 2.3) is the following. I have created/downloaded this script, which automatically adds Time, object name and event type to the outputted debug message:

Code:
/// @description scr_debug_console(arg1,[arg2, arg3,...])
/// @param arg1
/// @param [arg2
/// @param  arg3
/// @param ...]
//
// Script:      Improved version of show_debug_message
// Date:        2017-05-31

var time = date_time_string(date_current_datetime());
var obj = object_get_name(object_index);
var str = "";

for(var i=0; i<argument_count; i+=1)
{
    str += " "+string(argument[i]);
}

switch(event_type)
{
    case 0: var event = "Create"; break;
    case 1: var event = "Destroy"; break;
    case 2: var event = "Alarm"; break;
    case 3: var event = "Step"; break;
    case 4: var event = "Keyboard"; break;
    case 5: var event = "Mouse"; break;
    case 6: var event = "Collision"; break;
    case 7: var event = "Other"; break;
    case 8: var event = "Draw"; break;
    case 9: var event = "KeyRelease"; break;
    default: var event = "Event "+string(event_type); break;
}

show_debug_message(time+" | "+obj+" | "+event+" |"+str);
 
Top