GM:S 1.4 Checking if Variable Exists?

Discussion in 'Programming' started by Ethanicus, Oct 20, 2016.

  1. Ethanicus

    Ethanicus Ethan L!

    Joined:
    Jun 26, 2016
    Posts:
    230
    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.
     
  2. 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: Oct 20, 2016
    Dagoba, Online Handle and Ethanicus like this.
  3. Mick

    Mick Member

    Joined:
    Jun 30, 2016
    Posts:
    720
    You could instead create a parent object named obj_interactable and set the parent of all interactable objects to that.
     
    kraifpatrik likes this.
  4. Ethanicus

    Ethanicus Ethan L!

    Joined:
    Jun 26, 2016
    Posts:
    230
    Works perfectly, thanks! I thought undefined was only a function, but hey, guess I was wrong. :D

    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.
     
  5. 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
         }
    }
     
    Quailfail likes this.
  6. Ethanicus

    Ethanicus Ethan L!

    Joined:
    Jun 26, 2016
    Posts:
    230
    Oh yeah. XD I'm doing it with instance_position and position_meeting.
     
  7. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,781
    with all variable_i_do_not_want_to_type_out_manually = 0;
     
  8. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,381
    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.
     
  9. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,781
    Meh. I just define all my variables via dictionaries anyway. I don't like the undefined methods.
     
  10. stainedofmind

    stainedofmind Member

    Joined:
    Jun 20, 2016
    Posts:
    701
    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))
    
     
  11. Ethanicus

    Ethanicus Ethan L!

    Joined:
    Jun 26, 2016
    Posts:
    230
    It doesn't seem to? I mean I tested with other things and they didn't crash. o_O
     
  12. stainedofmind

    stainedofmind Member

    Joined:
    Jun 20, 2016
    Posts:
    701
    It might have been fixed if that's the case. I haven't tested it using an equation for a while.
     
  13. Drewster

    Drewster Member

    Joined:
    Jun 21, 2016
    Posts:
    222
    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;
    
     
  14. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,449
    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.
     
    Guest and Wraithious like this.
  15. HoTerMin

    HoTerMin Member

    Joined:
    Dec 27, 2017
    Posts:
    6
    Where should I put this code? In which object?
     
  16. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    909
    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
     
    HoTerMin likes this.
  17. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,449
    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.

    That function is for GMS 2 and legacy GM only, just not GMS 1.x.

    Now look at the subject tag of the topic.
     
  18. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    909
    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: Dec 27, 2017
  19. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,381
    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.
     
  20. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    909
    its in the manual now, which is useful cus it tells you what it returns if nothing is found and the array of names
     
  21. HoTerMin

    HoTerMin Member

    Joined:
    Dec 27, 2017
    Posts:
    6
    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?
     
  22. Joe Ellis

    Joe Ellis Member

    Joined:
    Aug 30, 2016
    Posts:
    909
    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
     
  23. Wadlo

    Wadlo Member

    Joined:
    Dec 16, 2017
    Posts:
    40
    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.
     
  24. TheouAegis

    TheouAegis Member

    Joined:
    Jul 3, 2016
    Posts:
    6,781
    undefined is for data structures. You should never be checking if a variable exists. How are you defining apple?
     
  25. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,381
    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
     
    Wadlo likes this.
  26. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    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: Dec 31, 2017
  27. YellowAfterlife

    YellowAfterlife ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ Forum Staff Moderator

    Joined:
    Apr 21, 2016
    Posts:
    2,381
    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.
     
  28. GMWolf

    GMWolf aka fel666

    Joined:
    Jun 21, 2016
    Posts:
    3,393
    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: Dec 31, 2017

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice