• Hey Guest! Ever feel like entering a Game Jam, but the time limit is always too much pressure? We get it... You lead a hectic life and dedicating 3 whole days to make a game just doesn't work for you! So, why not enter the GMC SLOW JAM? Take your time! Kick back and make your game over 4 months! Interested? Then just click here!

GameMaker How come variable_instance_set is only adding to my variable once?

For my game, everytime my player moves, every other objects energy variable is added their speed variable. When an objects energy variable is equal to or greater than the players speed variable, the enemy can make a move. Here's a bit of code from my player movement script:

Code:
if keypress = 4 {
        if (gridX > 0) && (obj_Collision.a_grid[gridX - 1, gridY] == 0){
     
            x -= 16
            with(all)
        {
        if(object_index != obj_Player and obj_LevelGen and obj_variable_controller and obj_Collision and obj_Version and obj_turncontroller and obj_Level and obj_Selector)
        {
            if variable_instance_exists(id, "speedy") and variable_instance_exists(id, "energy") {
            Speedy = variable_instance_get(id, "speedy");
            Energy = variable_instance_get(id, "energy");
                        show_debug_message("Speedy = " + string(Speedy));
                        show_debug_message("Energy = " + string(Energy));
            variable_instance_set(id, "energy", +Speedy);
            }

        }
    }
Now when I move around, it displays the correct speed and energy values in my debugger, except it shows that energy is set to the same value as speed, and it never changes beyond that once I move. I'm trying to have it added speed everytime I move. So if energy starts at 0, and speed is 5 by default, then step 1 energy = 5, step 2 energy = 10, step 3 energy = 15, etc.

So how do I go about this? What's wrong with variable_instance_set(id, "energy", +Speedy)? How would I rewrite it to work in this case?
 
Last edited:

chamaeleon

Member
For my game, everytime my player moves, every other objects energy variable is added their speed variable. When an objects energy variable is equal to or greater than the players speed variable, the enemy can make a move. Here's a bit of code from my player movement script:

Code:
if keypress = 4 {
        if (gridX > 0) && (obj_Collision.a_grid[gridX - 1, gridY] == 0){
      
            x -= 16
            with(all)
        {
        if(object_index != obj_Player and obj_LevelGen and obj_variable_controller and obj_Collision and obj_Version and obj_turncontroller and obj_Level and obj_Selector)
        {
            if variable_instance_exists(id, "speedy") and variable_instance_exists(id, "energy") {
            Speedy = variable_instance_get(id, "speedy");
            Energy = variable_instance_get(id, "energy");
                        show_debug_message("Speedy = " + string(Speedy));
                        show_debug_message("Energy = " + string(Energy));
            variable_instance_set(id, "energy", +Speedy);
            }

        }
    }
Now when I move around, it displays the correct speed and energy values in my debugger, except it shows that energy is set to the same value as speed, and it never changes beyond that once I move. I'm trying to have it added speed everytime I move. So if energy starts at 0, and speed is 5 by default, then step 1 energy = 5, step 2 energy = 10, step 3 energy = 15, etc.

So how do I go about this?
Why on earth would you use
GML:
Speedy = variable_instance_get(id, "speedy");
Energy = variable_instance_get(id, "energy");
variable_instance_set(id, "energy", Energy + Speedy); // +Speedy is not some kind of expression that increments the value energy
The whole point of using those functions are when you need the variable name to not be fixed, but passed as a string so you can have some kind of general functionality.
GML:
var Speedy = speedy; // implicitly using id.speedy, for the current instance, as we are referencing an instance variable
var Energy = energy; // implicitly using id.energy, for the current instance, as we are referencing an instance variable
energy = Energy + Speedy; // implicitly using id.energy, for the current instance, as we are referencing an instance variable
The above would be equivalent without any need for using the instance variable functions. And in this case, using the temporary Speedy and Energy variables is not necessary, of course.
GML:
energy += speedy; // just use the instance variables without all the extra lines of codes
It is of course possible you need to check for the presence of speedy and energy using variable_instance_exists() still, although that seems like code smell to me, and instances should be properly initialized beforehand so the variables have sensible values before this code executes.
 

Nidoking

Member
if(object_index != obj_Player and obj_LevelGen and obj_variable_controller and obj_Collision and obj_Version and obj_turncontroller and obj_Level and obj_Selector)
Also, what are you intending this to do? Because whatever it is, it's not doing that. You can't "and" objects.
 
Why on earth would you use
GML:
Speedy = variable_instance_get(id, "speedy");
Energy = variable_instance_get(id, "energy");
variable_instance_set(id, "energy", Energy + Speedy); // +Speedy is not some kind of expression that increments the value energy
The whole point of using those functions are when you need the variable name to not be fixed, but passed as a string so you can have some kind of general functionality.
GML:
var Speedy = speedy; // implicitly using id.speedy, for the current instance, as we are referencing an instance variable
var Energy = energy; // implicitly using id.energy, for the current instance, as we are referencing an instance variable
energy = Energy + Speedy; // implicitly using id.energy, for the current instance, as we are referencing an instance variable
The above would be equivalent without any need for using the instance variable functions. And in this case, using the temporary Speedy and Energy variables is not necessary, of course.
GML:
energy += speedy; // just use the instance variables without all the extra lines of codes
It is of course possible you need to check for the presence of speedy and energy using variable_instance_exists() still, although that seems like code smell to me, and instances should be properly initialized beforehand so the variables have sensible values before this code executes.
I thought variable instances and stuff were a key part in this. As you can probably tell I'm still a super amateur coder haha. Thank you very much! This works great

Also, what are you intending this to do? Because whatever it is, it's not doing that. You can't "and" objects.
I was trying to say, if the indexed object is any one of these listed, then don't do the following. It hasn't given me any problems so far, but that's probably because I used variable_instance_exists. I'll be changing that for the long run.
 

Roldy

Member
I was trying to say, if the indexed object is any one of these listed, then don't do the following. It hasn't given me any problems so far, but that's probably because I used variable_instance_exists. I'll be changing that for the long run.

The way you would want to say that is:

GML:
 if((object_index != obj_Player) and (object_index !=obj_turncontroller) and (object_index !=obj_LevelGen)) {
     // Do Stuff
 }
The way you are doing it isn't going to give you the results you want.
 
The way you would want to say that is:

GML:
 if((object_index != obj_Player) and (object_index !=obj_turncontroller) and (object_index !=obj_LevelGen)) {
     // Do Stuff
}
The way you are doing it isn't going to give you the results you want.
Thank you very much!
 

Nidoking

Member
I thought variable instances and stuff were a key part in this.
Variables, yes. Instances, yes. The variable_instance functions? Never. Ever. Reflection is as much a programming concept as a rabid wolverine is a babysitter. I mean, sure, you can put it in the house with the babies and tell it what you want it to do, but there won't be any babies when you get back. But at least you could read its name right from the code!
 

chamaeleon

Member
For the conditional execution of code depending on the object type, I think you'd be well served by using parent/child object hierarchies instead of checking if the direct object of the instance is not one of some big set, using multiple checks like you had initially. I'm assuming you have more than one object for which you'd want to execute code for or it'd be wasteful to check for all the ones it is not, instead of the one it is.
GML:
// Check if instance variable object_index has my_parent as an ancestor in the object hierarchy, and if so, do stuff
if (object_is_ancestor(object_index, my_parent)) {
    ... // do stuff with energy
}
What to name my_parent, and what objects belong under it depends wholly on what objects you envision having.
 
Top