[GameMaker] Why shouldn’t you use game_restart.

Categories: GameMaker


GameMaker offers a lot of powerful functions and flexibility for many of our needs. However, some of these functions are done in a sort of black box state. While many of GameMakers own functions/systems are genuinely fine, the problem becomes very apparent in the long run. More so when you start to build a very complex game, and let GameMaker handle more of the work than you. game_restart, being one of them.


What’s wrong with game_restart?

To understand what’s wrong exactly with using game_restart, we first need to know how it works.
Here I’ve written some pseudo code that you can more or less replicate within GameMaker.

function pseudo_game_restart() {
	// This will destroy all instances. 
	// Yes, this will run their cleanup events as well as well as their destroy event.
	with(all) {
		// Executes the instance game end event, if any
		event_perform(ev_other, ev_game_end);
		instance_destroy();	
	}

	audio_stop_all();

	// Go to the very first room, as per room order
	room_goto(room_first);
  
	// Some internal system that tells instances to run game start event, 
	// upon going to the very first room.
	// call_later, which was later introduced in 2022.8, will suffice.
	call_later(1, time_source_units_frames, function() {
		with(all) {
			event_perform(ev_other, ev_game_start);	 
		}
	});
}

As you can see here, not a whole lot is going on. But this also lies in some of the many problems that happen with game_restart.

I’ll summarize the issues into dot points.

  • Doesn’t cleanup any dynamic resources (such as data structures, assets that were created outside of the IDE and buffers).
  • Doesn’t reset any global variables/states that were changed (states such as the GPU state, functions/constructors with static variables and game speed).
  • Doesn’t reset resources that were defined in the IDE and modified in game.
  • Does not stop any time sources.
  • Kills all persistent instances.
  • In some reports by users, can cause rare oddities/bugs on some specific platforms.
  • In some more extreme reports, can even produce memory leaks in a blank project.
  • It is not “production ready”.

The first three points aren’t only true, but it’s stated within the manual.
4th and 5th points refer to less from my experience, but more from others experience amongst the GameMaker community. Take that as you will. The last point, as summarized above and with the pseudo code, more or less demonstrates why you shouldn’t use it in a big project. game_restart is meant for prototyping and debugging purposes only. It’s not meant to be used in an actual game project. Additionally, some libraries do not support game_restart for these points above. It’s not predictable enough for developers to consistently rely on for their actual projects.

But then, what do we use if we do want to restart the game? It’s simple. We make our own game_restart function. Now the code I’ve posted above can be more or less used as is (I would advice removing the event_perform from it as you may not want to execute game end events). You can add/change how it works. And it works well enough for a basic start. But I’m going to take it a step further by hijacking game_restart.


Hijacking game_restart

“What? How can that be?” You might ask yourself. Truthfully, there’s technically a way. But it’s not what you think. We’ll be using macros to accomplish this.

Macros in GameMaker Studio 2 are very powerful. You can give it essentially any keyword and a value and it’ll replace every last one of that keyword with your new value. And because they are compile time, there’s no real drawback from using them. Below you can see an example of how you can write a macro.

#macro HELLO_WORLD show_debug_message("Hello World!")

From above. It will take HELLO_WORLD and replace it with show_debug_message("Hello World!"), going from

// Create Event of an instance
z = 32;
hp = 100;
ammo = 0;
weapon = undefined;

HELLO_WORLD;

to changing it to:

// Create Event of an instance
z = 32;
hp = 100;
ammo = 0;
weapon = undefined;

show_debug_message("Hello World!");

Pretty nifty, right? This also works for functions as well.

So now that you get a small gist of it, let’s begin. Starting with by using the code above. For the sake of simplicity, I want my custom game_restart to not execute game start and game end events. Giving me complete control on what I initialize at the beginning of the game and in between restarts. So I’ll be removing event_perform(ev_other, ev_game_end) for myself. So creating a new script and calling it __game_restart, fill in this code.

function __game_restart() {
  // This will destroy all instances. 
  // Yes, this will run their cleanup events as well as their destroy event.
  with(all) {
	instance_destroy();	
  }

  audio_stop_all();
  draw_texture_flush();


  // Go to the very first room, as per room order
  room_goto(room_first);
}

Now that we’ve got a blank slate to work from, we can make a macro and add it to the top of the script file. Like so.

#macro game_restart __game_restart

function __game_restart() {
  // This will destroy all instances. 
  // Yes, this will run their cleanup events as well as their destroy event.
  with(all) {
	instance_destroy();	
  }

  audio_stop_all();
  draw_texture_flush();

  // Go to the very first room, as per room order
  room_goto(room_first);
}

We can now use game_restart to call our custom function. Game Start and Game End will never execute beyond their intended purposes. Allowing us to set and forget things we don’t want changing at all in the Game Start event. And everything else can be defined in the other events as per normal.

We can extend __game_restart to do just about anything that we like. For example, handling some or all of those edge cases that game_restart doesn’t do. I won’t cover it here, as that would go in much further detail. But with some minor tweaks to the code, you can pull it off with ease.


Summary

I hope this not only brings out the issues with game_restart, but encourages you to look beyond what you expect from how your project should handle things when it restarts the game.

If you would like some further explanation for the macros example I wrote above, I would recommend reading up this blog post by Katsaii. https://nuxiigit.github.io/content/blog/post/gml+library+extensions.html

»

    Leave a Reply

    Your email address will not be published. Required fields are marked *

    This site is protected by reCAPTCHA and the Google Privacy Policy and Terms of Service apply.