Legacy GM Checking if Variable Exists?

E

Ethanicus

Guest
Hey all.

In my game I'd like the player to be able to interact with objects, but only if they're tagged with a certain variable set to 1. The issue is, it's unnecessary and time- and resource-consuming to tag EVERY possible object with the variable.
Can I use some sort of function to check if the object has a variable in the first place?

Thanks.
 
T

The5thElement

Guest
To check if an object has a specific variable you can use the following code.
Code:
var inst = instance_nearest(x, y, TreasureChest_obj);

if(inst.interact != undefined){
     //Do work
} else {
     /*
     The variable interact does not exist for the
     TreasureChest_obj object
     */
}
 
Last edited by a moderator:

Mick

Member
You could instead create a parent object named obj_interactable and set the parent of all interactable objects to that.
 
E

Ethanicus

Guest
To check if an object has a specific variable use can use the following code.
Code:
var inst = instance_nearest(x, y, TreasureChest_obj);

if(inst.interact != undefined){
     //Do work
} else {
     /*
     The variable interact does not exist for the
     TreasureChest_obj object
     */
}
Works perfectly, thanks! I thought undefined was only a function, but hey, guess I was wrong. :D

You could instead create a parent object named obj_interactable and set the parent of all interactable objects to that.
Yes, I was planning to do that, but realized there was already a mixup with parents and I couldn't change it on the objects.
 
T

The5thElement

Guest
Works perfectly, thanks! I thought undefined was only a function, but hey, guess I was wrong. :D
Glad I could help. I forgot to add it in the code but you should always check if the object exists in the room before running an instance_nearest check.
Code:
if(instance_exists(TreasureChest_obj)){
     inst = instance_nearest(x, y, TreasureChest_obj);
     if(inst.interact != undefined){
          //Do Work
     }
}
 
E

Ethanicus

Guest
Glad I could help. I forgot to add it in the code but you should always check if the object exists in the room before running an instance_nearest check.
Code:
if(instance_exists(TreasureChest_obj)){
     inst = instance_nearest(x, y, TreasureChest_obj);
     if(inst.interact != undefined){
          //Do Work
     }
}
Oh yeah. XD I'm doing it with instance_position and position_meeting.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
with all variable_i_do_not_want_to_type_out_manually = 0;
This is a bad idea. Aside of taking the longest amount of time possible with current instances (by picking through every single one of them), this will reset the variable for any instances that already have it set.
 
if(inst.interact != undefined){
Careful with that line. If 'inst.interact' has a value other then 'undefined', you'll get an error, since 'undefined' is its own separate data type. The same thing would happen if you tried to compare a string value and a real value directly. A safer line of code would be:

Code:
if (!is_undefined(inst.interact))
 
E

Ethanicus

Guest
Careful with that line. If 'inst.interact' has a value other then 'undefined', you'll get an error, since 'undefined' is its own separate data type. The same thing would happen if you tried to compare a string value and a real value directly. A safer line of code would be:

Code:
if (!is_undefined(inst.interact))
It doesn't seem to? I mean I tested with other things and they didn't crash. o_O
 
D

Drewster

Guest
It might have been fixed if that's the case. I haven't tested it using an equation for a while.
Neither of those work. They will both crash and give you an error about the variable not having been set before reading it.

So for example, let's say you are going to create a custom sprite at runtime with sprite_create_from_surface, that gets replaced on each run.

Ideally you'd like to be able to do something like:

Code:
if (is_undefined(spr_myCustomSprite)
    sprite_delete(spr_myCustomSprite);
spr_myCustomSprite = sprite_create_from_surface(....
However, that will crash. So what you need to do is something like this.

In your CREATE event (or room init code or whatever):
Code:
CustomSpriteCreated = false;
Then later:
Code:
if (CustomSpriteCreated)
    sprite_delete(spr_myCustomSprite);
spr_myCustomSprite = sprite_create_from_surface(....
CustomSpriteCreated = true;
 

FrostyCat

Redemption Seeker
Rather than tagging things with variables that may exist in one place but not in another, why not add the instance ID into a map?

At the beginning of the main game sequence:
Code:
global.tagged = ds_map_create();
To mark an instance:
Code:
global.tagged[? id] = true;
To check if an instance is marked:
Code:
if (ds_map_exists(global.tagged, id)) {
  //...
}
To unmark an instance:
Code:
ds_map_delete(global.tagged, id);
Another variation of this would be to use an array or list instead of a map, which is better if you loop through the tagged instances more often than checking the tag status of isolated instances.
 
H

HoTerMin

Guest
Rather than tagging things with variables that may exist in one place but not in another, why not add the instance ID into a map?

At the beginning of the main game sequence:
Code:
global.tagged = ds_map_create();
To mark an instance:
Code:
global.tagged[? id] = true;
To check if an instance is marked:
Code:
if (ds_map_exists(global.tagged, id)) {
  //...
}
To unmark an instance:
Code:
ds_map_delete(global.tagged, id);
Another variation of this would be to use an array or list instead of a map, which is better if you loop through the tagged instances more often than checking the tag status of isolated instances.
Where should I put this code? In which object?
 

Joe Ellis

Member
variable_instance_exists(instance_id, string variable_name)

returns 0 - 1

You could easily make a script that runs at the beginning of the level, asking each instance if it has the interactable variable, and if it doesnt set it to 0, that'd get rid of having to always remember to tag an object when you create it,
as for the memory, its a toss up between asking "if variable_instance_exists(instance, interactable)" every collision, or having an array in the player object storing interactable instances and only check for collisions with those instances < this way would probably be fastest, and you can easily build this array in the script that checks whether the interactable variable exists
 

FrostyCat

Redemption Seeker
Where should I put this code? In which object?
I clearly said for the first piece "at the beginning of the game sequence". This means either the first room or a room between the main menu and the levels, in the Room Start event of a main controller object placed there or the room's Creation Code.

The subsequent pieces can be run from instances being tagged, but can also be run elsewhere as long as id is replaced by some other expression also holding a valid instance ID.

variable_instance_exists(instance_id, string variable_name)

returns 0 - 1

You could easily make a script that runs at the beginning of the level, asking each instance if it has the interactable variable, and if it doesnt set it to 0, that'd get rid of having to always remember to tag an object when you create it,
as for the memory, its a toss up between asking "if variable_instance_exists(instance, interactable)" every collision, or having an array in the player object storing interactable instances and only check for collisions with those instances < this way would probably be fastest, and you can easily build this array in the script that checks whether the interactable variable exists
That function is for GMS 2 and legacy GM only, just not GMS 1.x.

Now look at the subject tag of the topic.
 

Joe Ellis

Member
Its in the latest version of gms 1.4, I've started using it alot cus its really useful for stuff like this, theres also:

variable_global_exists
variable_global_get
variable_global_set
variable_instance_get
variable_instance_get_names
variable_instance_set
 
Last edited:

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
That function is for GMS 2 and legacy GM only, just not GMS 1.x.

Now look at the subject tag of the topic.
It is not mentioned in manual or auto-completion, but the function is available in current release of GMS1.4. My GMLive extension also makes use of variable_instance\variable_global functions to avoid having to generate accessor scripts for projects.
 

Joe Ellis

Member
its in the manual now, which is useful cus it tells you what it returns if nothing is found and the array of names
 
H

HoTerMin

Guest
variable_instance_exists(instance_id, string variable_name)

returns 0 - 1

You could easily make a script that runs at the beginning of the level, asking each instance if it has the interactable variable, and if it doesnt set it to 0, that'd get rid of having to always remember to tag an object when you create it,
as for the memory, its a toss up between asking "if variable_instance_exists(instance, interactable)" every collision, or having an array in the player object storing interactable instances and only check for collisions with those instances < this way would probably be fastest, and you can easily build this array in the script that checks whether the interactable variable exists
I think I`m doing something wrong, but it doesn`t work. When I`m making variable - it is local, so it doesn`t interact with other objects, even if i`ll create the same variable in them, no?
 

Joe Ellis

Member
local means it only exists in the current script its in, when you do var something;

its an instance variable which the variable_instance functions refer to, it belongs to 1 certain instance and lasts for the instance's lifetime until its destroyed or if the variable is set to a local variable (but that can only be done in an "execute a piece of code", not a script) with a script every local variable can be reused in multiple scripts at the same time and they don't affect each other, which is useful for things like var i = 0; ++i in a loop, and also recursive scripts,

with the variable function you need to put the colliding instance's id in the variable_instance_exists(instance_id, "variable") part, which you'd have to get with a collision function that returns the collided instance's id, like instance_place, collision_point, circle etc.

And also make sure the variable name is in "speak marks" cus it has to be a string not the actual variable, cus then it would be referring to that variable as if it belonged to the instance calling the function (the player) and you'd get a "variable - not set before reading it" error, or if the player did have this variable but it wasn't a string you'd get an "incorrect type - expecting a string" error
 
W

Wadlo

Guest
It is not mentioned in manual or auto-completion, but the function is available in current release of GMS1.4. My GMLive extension also makes use of variable_instance\variable_global functions to avoid having to generate accessor scripts for projects.
I am using GMS 1.4, and I don't have any of these functions that were listed above. Using the is_undefined() doesn't work to check variables either. It just comes up with an error message saying the variable was never set.

So, how can I check if a variable is undefined?
Here's my code.

Code:
//Comes up with an error message
if is_undefined(apple) {
    show_message("apple is not defined");
}

//also comes with an error message.
if apple == undefined {
    show_message("apple is not defined");
}
Thanks for your help.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
I am using GMS 1.4, and I don't have any of these functions that were listed above. Using the is_undefined() doesn't work to check variables either. It just comes up with an error message saying the variable was never set.

So, how can I check if a variable is undefined?
Here's my code.

Code:
//Comes up with an error message
if is_undefined(apple) {
    show_message("apple is not defined");
}

//also comes with an error message.
if apple == undefined {
    show_message("apple is not defined");
}
Thanks for your help.
Code:
if (variable_instance_exists(self, "apple")) {
    show_message("apple is not defined");
}
if compiler says that it's not a function at all, may have to update to 1.4.1773
 

GMWolf

aka fel666
Whoa whoa whoa....
You can called is_undefined on an undefined variable?
Whoa..... I had no idea. I though it would only work if the variable was defined (and it would check if the value was the undefined data type).

This changes a lot. Time for duck typing shenanigans.

[Edit] I wrongly use declare and definined interchangingbly
 
Last edited:

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
Whoa whoa whoa....
You can called is_undefined on an undefined variable?
Whoa..... I had no idea. I though it would only work if the variable was defined (and it would check if the value was the undefined data type).

This changes a lot. Time for duck typing shenanigans.
You can't - as they have said, that throws an error. There's a separate internal value for unset variables but you can't do much with it directly.
 

GMWolf

aka fel666
You can't - as they have said, that throws an error. There's a separate internal value for unset variables but you can't do much with it directly.
Right that's what I thought....

It's a shame really. We are missing out on a lot of the advantages duck typing offer.

Like having interfaces defined by what methods are declared. (Declare 'interact' and the object becomes an interactible object. Declare 'damage' and it becomes a damageable object... No dependencies. Flexible code. Just namespacing hell but we have dealt with it so far)

I think I'll have to write an extension for this. I have a few ideas.

[Edit] I wrongly use declare and definined interchangingbly
 
Last edited:
Top