In a single-player game, you read input directly from the keyboard, using either a function or an event.
In multiplayer, GameMaker handles inputs for each player automatically. All you have to do is get the input for the correct player.
For example, if you are Player 0, that player will be controlled by your keyboard. Player 1 will be controlled by input from Player 1’s computer, probably in a land far, far away.
The inputs you define here are the ones you can read throughout your game.
Of course, your inputs may be different, so what you read will also be different.
In the Step event of your player, get the inputs, and check them using conditions:
Scrap your old input system, and transfer controls to this new one.
If your input system uses conditions like above, you can just swap out the conditions.
In this case, you need to move the code from these events, into the conditional blocks previously shown.
Make sure to remove your old input code.
You can now control the first player! The second one gets random input while testing offline, which you can disable.
Step 3: How to Test An Online Multiplayer Game
Time to test the game online. There will be bugs, and crashes, and we’ll fix them as we go.
Publishing your game on GX.games is covered in the GX.games publishing tutorial.
First, go to GX.games and sign in.
Go into your profile settings and change the “Default region” to your closest region. This region will be used for your multiplayer games, reducing lag.
Go to your big bang event, where you call rollback_create_game().
Set the second argument to false. (If you’re using GML Visual, disable Sync Test.)
GML Code
GML Visual: Disable “Sync test”
Select the GX.games target and run the game.
Start your game, so the multiplayer part begins.
Scroll down below the game window, and click on “Copy Share Url”.
Open this link in a second Opera GX window.
Make sure both windows are visible at the same time.
Start the game from the second window. Both players will connect online, and the game will begin!
…or, it’ll crash.
Fix 1: How to Fix ‘Managed Object’ Error In GX.games
Either immediately or after some time, you may get the following error:
This means you can’t modify a managed object before all players have joined.
❔What is a managed object?
All objects are "managed" by default. A managed object is part of your game loop and affects players.
You should disable this for objects that are only visual or auditory, but not for objects that are integral to your gameplay.
So, you can’t change any managed objects until all players have joined.
Until that happens, all managed objects should “sleep”.
Going back to our big bang example, it would look something like this:
How To Tell If Players Have Joined
When all players have joined, the Rollback Start event will be triggered in all objects. GameMaker will also set the rollback_game_running variable to true.
So, using the Rollback Start event, or the rollback_game_running variable, you can tell if the game has started.
Until that has happened, you want your managed objects to sleep, or technically, to deactivate.
How to Deactivate Objects
Luckily, GameMaker allows you to deactivate instances, and activate them when needed.
Go to your multiplayer big bang code, and before running the “join” or “create” function, deactivate all instances:
GML Code
GML Visual
This deactivates all instances except the one running the code.
❔If you need an object to remain activated, use instance_activate_object(<your_object>) to re-activate it immediately after deactivating all objects.
How to Re-Activate Objects
We want to re-activate everything once the multiplayer game has started.
Add the Rollback Start event into the same object, and activate all instances:
instance_activate_all();
Run the game in online mode.
All your objects will sleep until you join with the remaining players. This prevents your game from modifying its state before the game has begun.
How to manually freeze parts of your code
If the above method is not suitable for your game, you need to manually freeze parts of your code until the game begins.
Create
If you’re setting things off in a Create event, like creating instances and triggering alarms, move them over to the Rollback Start event instead.
This doesn’t mean you need to completely scrap the Create event – you can keep it for initialising variables.
Other Events
You might have Step, Draw or other events that may run at any time, but you don’t want them to run until all players have joined.
At the top of such an event, add this:
if (!rollback_game_running) exit;
This will exit the event if the game hasn’t started yet.
At this point, your crashes are hopefully fixed. Let’s fix other issues now.
Fix 2: How to Use Cameras in Multiplayer
👇 Skip to Fix 3: Interactions if your game doesn’t use a camera.
When you run your game in online mode, all games will be centred on the same player, no matter which one you’re controlling:
The camera just doesn’t know which player is local, so it follows the first player by default.
Thankfully, the fix is simple.
How to Follow the Local Player
In your player’s Create event, add this:
if (player_local)
{
camera_set_view_target(view_camera[0], id);
}
Run the game, and your camera will now follow the local player. This means each window centres on a different player:
❕The player_local variable tells if the player is local. You can use it in the Draw event to draw an icon above the local player only, to make it easier for the player to find where they are.
Fix 3: How to Interact With Game Objects
Interacting with game objects becomes less simple in multiplayer.
In a single-player game, there’s only one player, so “where is the player” is a simple question.
You can’t ask the same in multiplayer. If you do, only one player will be able to interact with other objects.
Let Me Tell You A Story
My game has a coin block. That block looks for obj_player every step, and reads variables from it:
if (place_meeting(x, y + 1, obj_player))
{
if (obj_player.yprevious > obj_player.y)
{
In multiplayer, this results in only one player being able to hit the block.
The first condition isn’t the problem: it’s the second one, which reads variables from obj_player directly: ‘obj_player.yprevious’.
This is the problem, as it means the block may collide with one player, and then ask for information from a different player.
How to Detect The Correct Player
Instead of assuming there’s just one player, the code should only ask for information from the player it collides with.
Here’s the fixed code:
var _inst = instance_place(x, y + 1, obj_player); // Find the colliding player
if (_inst != noone) // If a colliding player was found,
{
if (_inst.yprevious > _inst.y) // Read data only from that player
{
This allows any player to hit the block, as it looks for “a player”, and then reads info from that player instance.
You’ll likely find similar issues throughout your project. Find a similar solution using the “a player” concept to fix them.
Fix 4: How to Optimise a Multiplayer Game In GameMaker
The “state” of your game comprises all your managed objects.
The more managed objects you have, the more there is for GameMaker to keep track of, which may result in worse performance.
To improve network performance, disable “Managed” for objects that don’t need it.
Only those objects should be managed which interact with players or other gameplay elements, or have any code at all that affects the game’s outcome.
Objects that only appear as visuals, particles, or that never move or change, can be unmanaged.
GameMaker does not automatically synchronise the state among all players, it only synchronises input.
I recommend reading Rollback System in the GameMaker manual to further understand this.
Tip 1: Player Instances
GameMaker handles the creation and destruction of your players automatically, so make sure to not destroy player instances at any time during the game.
If you need to show a player as defeated, change its sprite, make it invisible, or use some other technique (like state machines) -- but don't destroy it.
Conclusion
Congratulations, your game is now multiplayer! There is much more you can do – find out in the manual.
Publish your game to GX.games for millions of potential players.
If you’re facing issues, experiment. Try different things to narrow down your problem.
When in doubt, just create a new multiplayer game. Add gameplay mechanics to it. There’s no better way to learn than practice.
Happy GameMaking!