Syncing custom variables

Before you start

In this post I'll explain how custom variables (anything other than direction, x, y, sprite_*, for example) should be synced. This tutorial assumes you already have a basic game that shows a login box and has a "player object" and an "other player object" set up. If you don't, the getting started tutorial covers the basics of creating a new game.

Clothing

Let's assume there's some kind of variable, I'll call it "clothing_sprite", that stores which sprite is drawn on top of the player sprite, like this:

draw_self();
draw_sprite(clothing_sprite,0, x, y);

We also want that sprite to appear on the other player object, and it should be the same sprite as the player is currently using. For the purposes of this tutorial, I'll assume sprites can be switched by pressing 1, 2, or 3. Add this code to the step event of the player object:

if(keyboard_check_pressed(ord('1')))clothing_sprite =spr_clothing_1;
if(keyboard_check_pressed(ord('2')))clothing_sprite =spr_clothing_2;
if(keyboard_check_pressed(ord('3')))clothing_sprite = spr_clothing_3;

Parent-object

I like to keep the amount of duplicate code in my projects to an absolute minimum. I don't want to have to update the drawing code twice if I decide I want to change it. Create a new object, and name it something like "par_players". It'll be the place where code for both the player object and the other player object can be placed.

Add the code for drawing the clothing to the draw event:

draw_self();
draw_sprite(clothing_sprite,0, x, y);

Initialize the variable in the create event:

clothing_sprite= spr_clothing_1

Set the parent of both the player object and the other player object to this new "par_players" object. If you've already got a draw or create event added to the player or other player object, make sure to invoke the inherited event as well:

event_inherited();

Synchronizing the variable

Lastly, the variable's value will need to be sent to the other clients. You won't need to take care of sending the variable to new players that connect, or making sure you only set the variable when changing it.

Add this code to the step event of the player object:

gms_self_set(“clothing_sprite”,clothing_sprite);

This piece of code will tell the extension that there is a variable named clothing_sprite that will need to be sent to the other players. The extension will then do all the hard work of deciding the best way to send the variable and when to send the variable.

Note: If you know a variable is not an integer value, make sure to round(...), floor(...) or ceil(...) the value if you only use the integer part of the number. If GameMaker Server will use less bandwidth if the variable is an integer. If you're sending a number as a string, convert it to a real fist. Strings generally use more bandwidth than numbers when sending them. gms_self_set_precision(...) can also be used to specify how precise the value needs to be sent.

Add this code to the draw event of the other player object:

clothing_sprite= gms_other_get(player_id, “clothing_sprite”)
event_inherited();

This will obtain the variable's value and store it in "clothing_sprite". Then, it calls the inherited draw event, which will draw the player's sprite and the clothing sprite on top. The player_id variable is automatically created by the extension, and is used to identify other players. It'll exist in every instance of the other player object created by the extension.

Replies (58)

Last message on 21 Apr 2020

R3styn on 8 Jun 2019, 14:55:31
Pls help! I have an obj_player obj_other_player and par_player objects....
I have a timer and when time runs out I want it to randomly pick a player who gets a "hot potato"
when a player has a hot potato and passes 120 seconds I want to explode
PLS ADMINS HELP ME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
Bluecore on 8 Jun 2019, 15:04:51
You will need to share your code if you want help. Try making sure you are able to get the tutorial above working before you try something on your own.
R3styn on 8 Jun 2019, 15:33:21
R3styn on 8 Jun 2019, 15:30:14
which code?
BabyGolden12 on 5 Apr 2020, 04:16:38
so how would i use this check player xp?
so obj_stats.hp =100 how would i make this so i can check anybody?
Size43 (Administrator) on 5 Apr 2020, 18:23:04
If you set that variable using gms_self_set, you can then use gms_other_get(player_id, ...) to read it on the other clients.
PainiteOfficial on 30 Mar 2020, 19:19:02
But how exactly can i change a variable for all the players? For example, let's say that above my character (obj_player) there is drawn a variable that can be either 0 or 1. When i press enter let's say, the variable changes (my_variable = !my_variable). It will change for myself, but I want all the players to have the exact same variable above their heads, so when i change the o above my head into a 1 i want all the other players to have a 1 on their heads as me and vice versa. I tried to describe this example as good as I could. can anybody please help me with this?
Size43 (Administrator) on 4 Apr 2020, 15:58:38
Sounds like you might want a global variable. See gms_global_set and related scripts.
PainiteOfficial on 30 Mar 2020, 16:07:26
so i was trying to sync a variable called "global.audio_play" that should play and stop the music at all the players at the same time. It worked but not well because it keep changing from 0 to 1 so the music will glitch out, stopping and starting. Any suggestions? (while i was alone it worked well but when another player joined it started glitching.)
Size43 (Administrator) on 4 Apr 2020, 15:57:59
Could the issue here be that multiple players are changing the variable at the same time? You can use gms_self_ismaster(), which will return true for just one player in a session. If you guard all modifications to the audio_play variable with a check for whether the player is master, you can ensure that only one player has control over the variable.
PainiteOfficial on 10 Apr 2020, 18:44:03
Thank you so much for responding size!
I've set the condition that only the master player can change the variable but it still didn't work.
I'm thinking it's something about how the variable gets distributed from a player to another but i'm not sure.

Here's my code:

Parent Object:
Create: global.audio_play = 0
Step:
if (global.audio_play = 1) {
audio_resume_all()
if !audio_is_playing(mModular) { //mModular is the name of the song
audio_play_sound(mModular,10,0)
}
} else if (global.audio_play = 0) {
audio_pause_all()
}
Draw: draw_text(x,y-40,global.audio_play) //Just to display the variable on top of the players

Player object:
Step :
if (gms_self_ismaster()) {
if (keyboard_check_pressed(vk_left)) {
global.audio_play = !global.audio_play
}
}
gms_self_set("global.audio_play",global.audio_play);

other Player:
Step:global.audio_play = gms_other_get(player_id,"global.audio_play")

Of course i've added event_inherited() to both the player and the other
Thank you!
Size43 (Administrator) on 21 Apr 2020, 10:19:15
You should move the gms_self_set call into the if as well, as that's the thing that finally sends the value to the serverand you don't want multiple clients to be sending conflicting values.

Also, if I understand correctly you want to sync a single variable that will be the same for all players. In that case, gms_global_get/set will be more suited. You can then also move the _get call from the other player object into the else-branch of the gms_self_ismaster check, making sure it is only read out when the client is not the master.
Bluecore on 25 Dec 2018, 07:05:58
In my player object (objPlayer), I have this code in the create event.
[quote]
WalkDown = sprCharaWalkDown;
WalkLeft = sprCharaWalkLeft;
WalkRight = sprCharaWalkRight;
WalkUp = sprCharaWalkUp;
gms_self_set("WalkDown", WalkDown);
gms_self_set("WalkLeft", WalkLeft);
gms_self_set("WalkRight", WalkRight);
gms_self_set("WalkUp", WalkUp);
[/quote]

In my player other object (objPlayerOther), I have this code in the create event.
[quote]
player_id = gms_self_playerid();
WalkDown = gms_other_get(player_id, "WalkDown");
WalkLeft = gms_other_get(player_id, "WalkLeft");
WalkRight = gms_other_get(player_id, "WalkRight");
WalkUp = gms_other_get(player_id, "WalkUp");
[/quote]

Lastly in my player other object (objPlayerOther), I have this code in the draw event.
[quote]
sprite_index = WalkUp;
draw_sprite(sprite_index, image_index, 0, 0);
[/quote]

Why does the player other object use sprController sprite, instead of sprCharaWalkUp? This is a 3D game, also ran out of space to type full code
Bluecore on 25 Dec 2018, 08:11:42
Okay so it seems gms_other_get keeps returning 0 when I use it, which happens to be the same sprite id as sprController. Time to find out why this happens.
Bluecore on 25 Dec 2018, 08:31:20
Ah and fixed.
"The player_id variable is set after the create event, so you cannot use it in the create event." ~ Size43
So using gms_self_playerid(); in the create event was a no go. I just had to move the create event code into the step event. A bit, unfortunately, but it works. Might be able to get it to work with an alarm that goes off right after the create event, I'll have to do some testing.
Size43 (Administrator) on 28 Dec 2018, 22:15:38
The player_id variable is automatically set by the extension (for all other player objects created by the extension), you don't need to use gms_self_playerid() at all in this case.
Ptown01 on 29 Jul 2018, 01:32:27
One last question: In this line of code- gms_self_set(“clothing_sprite”,clothing_sprite); what is supposed to be in the parentheses? I thought it was the original clothing but I never knew for sure.
Size43 (Administrator) on 8 Aug 2018, 11:27:20
The first argument - "clothing_sprite" - would be the name of the variable you're syncing, "clothing_sprite" is fine. The second argument is the value you want to send, so in most cases that'd be the variable in which you're storing the clothing that the player is wearing.
Ptown01 on 21 Jul 2018, 08:16:03
My game just crashes as soon as I login. I did it exactly as it said, only difference is the word clothing was changed to hat as I had already had an almost identical system in place.
Size43 (Administrator) on 22 Jul 2018, 14:51:16
Does it show an error message, and if so: what does it say?
Ptown01 on 26 Jul 2018, 04:16:55
the only thing I changed was and I added an if statement if the image xscale = -1
Size43 (Administrator) on 28 Jul 2018, 16:30:59
I vaguely remember there being a bug in GM at some point that crashed the game when you set the image_xscale to a certain value. Can you try setting it to -1.5 instead to see if that fixes the problem?
Ptown01 on 22 Jul 2018, 23:20:31
No, it starts the game up with the login screen, then I hit login and it just closes the game, no error messages and nothing in compilier.
innominato on 10 Jan 2016, 11:43:43
Why this code works on Windows and not on android?

if (GMS.master == false ){
seed = (gms_other_get(player_id, "seed")); //on Android, the seed isn't received
random_set_seed(seed);
}
Size43 (Administrator) on 11 Jan 2016, 12:15:48
Are you properly connected to the server on android? What do gms_info_isconnected and gms_info_isloggedin return?

Also note that GameMaker does not guarantee that a seed will generate the same set of numbers on different platforms.
Forgeio on 5 Jul 2015, 16:38:31
Hey Size, in my game when the player presses spacebar, it creates a sword depending on the direction he is facing. I have everything set up, and it looks great, except I have it so that in case he attacks while moving, the sword will jump to the players position. This messes the whole game up, so that when you attack the other player attacks and when the other player attacks you attack. Please help! I cant figure out which way to sync this!
Size43 (Administrator) on 7 Jul 2015, 15:07:32
Are you using something like "with" (=applies to object in D&D) to move the sword?
Forgeio on 7 Jul 2015, 16:19:42
no, I just tried doing this example except having it jump to obj_player1.x obj_player1.y
Forgeio on 8 Jul 2015, 02:48:29
sorry forget what I just said, inside of the step event of the sword object it has it jump to the obj_player1.x and obj_player1.y
Size43 (Administrator) on 14 Jul 2015, 21:58:17
Check if gms_instance_is_owner(id) is true before making the instance jump to the position of the player :)
Forgeio on 17 Jul 2015, 00:18:48
can you give me an example code? sorry but I tried it and it didn't really work :/
Size43 (Administrator) on 19 Jul 2015, 22:28:07
if gms_instance_is_owner(id)
{
    x = obj_player1.x
    y = obj_player1.y
}

should work.
Forgeio on 20 Jul 2015, 21:36:53
so I should just keep (id) as id? nothing has to go there?
Size43 (Administrator) on 24 Jul 2015, 15:34:45
If you're syncing the instance with the is_full flag - Yes, you can just keep id there.
Forgeio on 24 Jul 2015, 18:32:27
can you just give me the full code for it? I just cant seem to figure it out. What all should go in the step event of the object for the sword? also, how would I have it sync its rotation and sprite change etc.
Size43 (Administrator) on 28 Jul 2015, 20:13:08
That is the full code, it should be in the step event. You can sync other variables using gms_instance_set(...) and gms_instance_get(...).
Forgeio on 29 Jul 2015, 00:04:10
it didn't work though, on the other player the sword does not follow the player. Maybe its just lag though...
Size43 (Administrator) on 9 Aug 2015, 14:19:53
Apologies for my delayed responses. As you may know, Outlook is blocking all GameMaker Server mails which means I don't get notified when you post a reply.

What does your instance syncing code look like? (the part where you call gms_instance_sync(...))
Forgeio on 9 Aug 2015, 19:19:31
gms_instance_sync(id,is_full,'x','y');
if gms_instance_is_owner(id)
{
x = object0.x
y = object0.y
}

that's the whole code I have in the create event of the sword
Size43 (Administrator) on 12 Aug 2015, 20:02:09
Try moving this part to the step-event instead of the create-event:

if gms_instance_is_owner(id)
{
    x = object0.x
    y = object0.y
}
Forgeio on 13 Aug 2015, 01:02:35
thanks
Forgeio on 15 Sep 2015, 03:53:11
it still doesnt work... sorry for being such a bother ;-;
Size43 (Administrator) on 21 Sep 2015, 19:29:25
Hey,

Sorry for my late reply. I don't have as much free time as I expected, so I haven't been able to even touch any GameMaker Server code in almost a month. If I recall correctly you've sent me a mail with an example of what's not working. I had a quick look at it and there are indeed some bugs that need to be fixed. I'm hoping for things to slow down a bit so that I can fix it next weekend.
Forgeio on 5 Mar 2016, 08:14:30
Did you forget about me? Lol
Size43 (Administrator) on 6 Mar 2016, 17:11:29
Oops, sorry. To be honest, I've got no idea if I actually fixed what I found, or what the bug actually was. There have been 3 updates since I posted that, please check if you're still having this problem on update 1.8.8.

If it's still not fixed, let me know and I'll promise to fix it within a week or so :)
Forgeio on 20 Sep 2015, 05:32:27
hello??
Forgeio on 6 Jul 2015, 03:26:51
sorry about so many questions, but also, how do I make commands? like /spawn and admin commands like /ban?
Size43 (Administrator) on 7 Jul 2015, 15:06:12
You can use gms_script_set_chat_verify to see a chat message before it's sent. You can intercept the commands using normal string functions and then return false to prevent the message from being sent.
Forgeio on 8 Jul 2015, 15:27:37
can you give me an example code?
Size43 (Administrator) on 14 Jul 2015, 22:02:17
Something like this:

if string_pos("/ban", argument0) == 1
{
    // Handle command using normal GM functions
    return false;
}// Check for other commands
return true;
Forgeio on 16 Jul 2015, 02:55:19
thank you so much :D
kaikalii on 14 May 2015, 03:23:38
What do I need to do in order to sync changes in the player's sprite?
Currently, I have certain conditions that change the player's sprite via "sprite_index = spr_new_sprite;"
Do I need to implement it as a draw function in order to sync it?
Without syncing, you cannot see other players' sprites change.
Size43 (Administrator) on 14 May 2015, 17:49:41
Make sure you're not drawing a specific sprite in the draw event of the other player. If that's not the case, please try adding gms_optimize_variables(true, true) right below the gms_settings call.
SaitoZero on 20 Sep 2014, 16:45:03
Hey Size, may you turn everything in Documentation into a file( html help, txt, docx, ect...) and upload it? I can't always be online 'cause my net isn't very good and my laptop has such low RAM that browser takes about 40%, so it's lagging and I can't use Game Maker when browsing the internet.
Size43 (Administrator) on 20 Sep 2014, 16:46:44
I'll see what I can do :)
namlunthkl on 3 Nov 2014, 16:46:34
I will help you to make some example but.... You have to create a page to post Example first!!! :)
LightVelox on 18 Aug 2014, 16:55:35
how i get the player id?i put

if team=1{player_id=p1 other_player_id=p2}
if team=2{player_id=p2 other_player_id=p1}


sorry for that questions i have a little problem with id and instance syncs
Size43 (Administrator) on 19 Aug 2014, 20:22:22
There's gms_self_playerid for the playerID of the player object, and a variable named player_id is created automatically for all other player objects. You don't need to add any other code for that.