• 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 Getting Object Variables?

M

MadTinkerer

Guest
Getting the value of instance variables is easy. You can just say myNumber = obj_OtherObject.myNumber or something like that and it will work. You can also get the value of certain variables. object_get_sprite will get the sprite index of an object. object_get_parent will get the index of the parent object of an object.

But is there a way to get the value of an object variable set in the object editor without creating a new instance of the object? You can use event_perform_object to perform the event of an object. But as far as I can tell, you can't get, let alone set, the value of an object's object variable unless you instantiate it into an instance and check that instance's variable. If I change an instance's variable and I want to check what the variable was originally set in the object editor, do I really need to make a new instance of it?

Am I missing something?
 
Last edited by a moderator:

samspade

Member
Getting the value of instance variables is easy. You can just say myNumber = obj_OtherObject.myNumber or something like that and it will work. You can also get the value of certain variables. object_get_sprite will get the sprite index of an object. object_get_parent will get the index of the parent object of an object.

But is there a way to get the value of an object variable set in the object editor without creating a new instance of the object? You can use event_perform_object to perform the event of an object. But as far as I can tell, you can't get, let alone set, the value of an object's object variable unless you instantiate it into an instance and check that instance's variable. If I change an instance's variable and I want to check what the variable was originally set in the object editor, do I really need to make a new instance of it?

Am I missing something?
As far as I know, no, you can't. If you really need it, you could create a instance of one that doesn't change, or even a parent object that just has the default variables you can reference, or have a separate unchanging version of the variable in the object itself.

Is there any particular reason you need to do this?
 
M

MadTinkerer

Guest
Well in my case I wanted to be able to compare the "default" values of two different instances by checking what the values of the object variables were set to in the object editor. When I went to look up how to do this, I was surprised that I couldn't. I was probably thinking of the various object_get functions and didn't realize there wasn't a function to get the value of an object variable at runtime. I'm a little surprised that an instance can know it's object resource, and can know whether that object is set to visible or solid or persistent, but can't find out what a specific variable was set to in the object editor.
 

TheouAegis

Member
You could do event_perform_object(), but then its variables would be yours. LOL

The object_index, sprite_index, mask_index, and whatnot are all built-in functionality. GM can store all that info sequentially just fine in its data. There are already pointer references for all of those values. But variables YOU create don't exist until an instance has been created. As for built-in variables you try to modify, the value you set in the create event has no way of getting stored as an easily referenced value. The create event code is stored in a different area of memory than the default values.
 
T

Taddio

Guest
You could always save the default value in a list (or even a stack, depending on what you're after) after setting it in the room editor. Comparing/getting/changing values would be quite simple after that
 
F

FerretLeader

Guest
Getting the value of instance variables is easy. You can just say myNumber = obj_OtherObject.myNumber or something like that and it will work. You can also get the value of certain variables. object_get_sprite will get the sprite index of an object. object_get_parent will get the index of the parent object of an object.

But is there a way to get the value of an object variable set in the object editor without creating a new instance of the object? You can use event_perform_object to perform the event of an object. But as far as I can tell, you can't get, let alone set, the value of an object's object variable unless you instantiate it into an instance and check that instance's variable. If I change an instance's variable and I want to check what the variable was originally set in the object editor, do I really need to make a new instance of it?

Am I missing something?
I think that you're looking for variable_instance_get_names(). It should get the "custom" object variables that you made.
 
J

Joe Banko

Guest
What I'm trying to do is have 6 slots each with a different type of projectile. The player would have a current slot based on what weapon would work best against the current enemy. I have more than 6 types of projectiles so I would like each slot to carry a pointer to projectile objects in the resource tree and when the player is going to fire a projectile the object id of the current projectile could be used in this statement:
var i_weapon = instance_create_layer(x - 10, y - 30, "Projectiles", cur_weapon );
where cur_weapon points to the selected projectile object. Does that make sense????

Thanks,

Joe B
 
J

Joe Banko

Guest
Duh, sorry guys, I saw some of these posts after I was responding so I have some food for thought and research.
Thanks for the help/suggestions!
Joe B
 
J

Joe Banko

Guest
Duh#2!
Thanks samspade. I already have a parent object that all projectiles derive from. So I could delete all the child objects and just use the parent object, setting the specific instance variables inherited from the parent object where necessary; sprite, speed, damage,etc.
Genius!

Thanks,

Joe B

ps THANKS for all the responses!
 
J

Joe Banko

Guest
Hmmm, was looking at using an array, but took a quick look at maps. Wifey just informed me I needed to crawl out of my cave for dinner and spend Fathers Day with the fam.

Later,

Joe B
 
J

Joe Banko

Guest
Still a little up in the air about arrays vs maps vs ds_list.
Ideally I'd like to have a static data structure that i create when the game starts. It would hold all the projectile types along with their parameters, 10. In the Create of the child of the parent o_projectile I could do a lookup based on the unique name, projectile_id, the first column of the data structure, populate the parameters for the projectile and let it go. My question is which of the data structures would handle this setup best without causing memory leaks or any other issues?

Thanks!

joleb
 
Well arrays can't memory leak. But there's no real way anything can leak without you doing something wrong, so you shouldn't be basing your thoughts off of that. Maps are slower to access than lists, until a list gets to a certain size, in which case access speed to maps is faster (this is because maps take roughly the same amount of time to access an entry regardless of size, whereas access times for lists grows with list length). Arrays are essentially lightweight lists and they are slightly faster to access over lists, I believe. However, this, also, is a very minor point unless you are building like 10, 000 entry long lists.

Maps take a key (essentially a string) and use that as their pointer for entries. Lists and arrays both are index based, so they take a number. Personally, I would use a map and have each map entry hold a list, with the list entries being the individual parameters. But in general, this is all sort of personal preference. It's very unlikely to tank your FPS no matter which you use, so use the one you feel most comfortable with. Like using arrays? Use enums for your weapons and then store arrays in an array. Like lists? Do essentially the same. Like maps? Do as I said just above (or however you want to implement it).
 
B

booksmaster

Guest
Ok I will also answer. You are thinking of your predefined variables as of something that is being created and stored somewhere during the runtime. But your variables are just a code that is being executed in response to the event being triggered. So if you put something into Create event of some object(no matter is it variables or some math or creating some other instances) it will run only when the corresponding event will be trigered and that will only happen when the instance of that object will exists to handle those events.
 

Zyl

Member
Bumping to provide the only solution I ultimately found:

1. Create a new object obj_default_whatever or such and make it the parent of the desired object. (Using a new parent object for this makes sure any existing code checking against object index doesn't jump at the sight of this new object)

2. Move all the variables from the object to the newly created parent object.
Warning: you will have to remove variable definitions from the child first, which will cause all variable overrides in instances and children to be lost and require to set them again.

3. Create instance of newly created parent object in first room of your game. Move it somewhere where it is less likely to cause trouble, such as coordinates -64, -64.

4. Give it a nice name and make it persistent. Also set instance fields to prevent interactions with drawing and collision logic.
1703983752120.png

Instance creation code:
GML:
persistent = true;
sprite_index = noone;
mask_index = noone;
visible = false;
1703983302306.png

5. If needed, also add checks in your code to "sedate" the instance so it doesn't act on its own, using an additional boolean variable if necessary. (Shouldn't be necessary if you made a blank parent object as described)

6. Reference the instance in code as though it was the object with desired defaults.

This isn't perfect, largely due to having to set all variable overrides again, but it's the best way I was able to figure out.

The alternative is to update your code to smell out the dummy instance when necessary, which is an option when the amount of variable overrides needing to be set again is obscenely large. It's definitely worse long-term though, so, pick your poison. (Or maybe find a way to correctly modify the source files outside of GameMaker, which I haven't tried to do.)
 
Last edited:
Bumping to provide the only solution I ultimately found:

1. Create a new object obj_default_whatever or such and make it the parent of the desired object. (Using a new parent object for this makes sure any existing code checking against object index doesn't jump at the sight of this new object)

2. Move all the variables from the object to the newly created parent object.
Warning: you will have to remove variable definitions from the child first, which will cause all variable overrides in instances and children to be lost and require to set them again.

3. Create instance of newly created parent object in first room of your game. Move it somewhere where it is less likely to cause trouble, such as coordinates -64, -64.

4. Give it a nice name and make it persistent. Also set instance fields to prevent interactions with drawing and collision logic.
View attachment 59858

Instance creation code:
GML:
persistent = true;
sprite_index = noone;
mask_index = noone;
visible = false;
View attachment 59857

5. If needed, also add checks in your code to "sedate" the instance so it doesn't act on its own, using an additional boolean variable if necessary. (Shouldn't be necessary if you made a blank parent object as described)

6. Reference the instance in code as though it was the object with desired defaults.

This isn't perfect, largely due to having to set all variable overrides again, but it's the best way I was able to figure out.

The alternative is to update your code to smell out the dummy instance when necessary, which is an option when the amount of variable overrides needing to be set again is obscenely large. It's definitely worse long-term though, so, pick your poison. (Or maybe find a way to correctly modify the source files outside of GameMaker, which I haven't tried to do.)
Iā€™d probably just use a global variable instead of setting all that up. Make it a struct if you need extended functionality, otherwise an array would work fine.

(also holy necro Batman!)
 
All you need to do to "sedate" is to deactivate it. (However, if you want it persistent, then you'll need to re/deactivate it across room changes.) You can still refer to it directly, but with will no longer see it, and it won't run/update code like all the active instances. But, as others have said, you might as well just store the default values you need in some global thingy.

(yes Robin)
 

TheouAegis

Member
That doesn't seem to work. The instance can no longer be accessed.
Unable to find any instance for object index '100003' name '<undefined>'
What code did you use that gave that error? Deactivated instances are indeed accessible, but your code options are pretty much limited to dot notation.
 

Zyl

Member
What code did you use that gave that error? Deactivated instances are indeed accessible, but your code options are pretty much limited to dot notation.
The concrete line is move_speed = inst_default_box.move_speed;:

1704039722024.png

1704039645419.png

Maybe deactivated instances don't survive room changes or something?
 

TheouAegis

Member
The concrete line is move_speed = inst_default_box.move_speed;:

View attachment 59868

View attachment 59867

Maybe deactivated instances don't survive room changes or something?
Oh, yeah if you change rooms then that would delete it. Also, it wouldn't persist across rooms. You would have to reactivate it, make it persistent, go to the next room, then deactivate it in the next room. And ideally if your next room it's not persistent, you could simply deactivate that object in its room start event, otherwise you would need to set an alarm or something.
 
I still fail to see why a global variable of some structure isn't a better solution to this? I'm not entirely sure what "redundancy" means in this context, but surely having an array that holds a few structs that have the information you need access to globally is a better solution than trying to jump through hoops with deactivation and persistence, etc. If you need the struct to have default values, just build it from a constructor that initializes those values correctly I guess?
 

Bart

WiseBart
You can actually get Object Variables in a much easier way, as I more or less described here:


It's always necessary to create an instance of the object. The idea is to call variable_instance_get_names as the first thing in the Create event to get the object variable names. This works because object variables are the first variables that are initialized in a newly created instance. Essentially, at the start of the Create event the only variables the instance has defined are those variables (technically also the variables passed through the var struct of instance_create_depth and instance_create_layer, but you can decide if you pass any or not).

If you combine that with a global DS map in which the names are stored per object index, it could look something like this:
GML:
/// Script Asset (global scope)

// Global map to store variable names per object index
map_object_vars = ds_map_create();
GML:
/// Create Event

// Get object variables here
var _map = global.map_object_vars;
if (!ds_map_exists(_map, object_index)) {
    _map[? object_index] = variable_instance_get_names(self);
    // instance_destroy();  // Optional
}

// Actual creation code begins here

// This now goes after (!) the code to get object variables
event_inherited();

// ...
The commented call to instance_destroy is optional though it could be good to destroy the instance there at that point if the only goal of creating that specific instance is to get the object variables of its object (which it likely will be the first time).
Destroying the instance at that point will also prevent any interaction, which should also do away with all assignments to instance variables that seem to complicate things quite a bit in the discussion above.
 
Last edited:

Yal

šŸ§ *penguin noises*
GMC Elder
You can get some variables via functions, though none of them are your own custom ones:
1704054578393.png

Though honestly, IMO having to use introspection for a case like this just feels like doing it wrong - if you want to remember something for later you should store it yourself. If you want to reset things to a "known good" state you could make a function for it, keeping all the resettable variables in one place:
1704054787850.png
This could be hardcoded values (as in this example) or you could store a "my default values" structure in the Create event using the name-struct approach mentioned above, and then copy those to current ones when you reset the object. Since IDE variables can be overridden by child objects or even on a per-instance basis in the room editor, this data needs to be tracked on a per-instance basis if you want full accuracy anyway.
 
Maybe deactivated instances don't survive room changes or something?
That's why I said,
All you need to do to "sedate" is to deactivate it. (However, if you want it persistent, then you'll need to re/deactivate it across room changes.)
$F^ J

More seriously, though, this demonstrates you used a suggestion without reading how it works in the manual. $:^ (
The GM Manual said:
a persistent object that has been deactivated will not be moved to the next room unless it is re-activated first (effectively deleting it from the game).
I hope you'll improve on that in the future,
Bob
 

Zyl

Member
I'm not entirely sure what "redundancy" means in this context
I was thinking you'd end up having to maintain the value twice (object and some variable initialization in code). Of course, if you can read them once on creation, that wouldn't be a problem, though you'll still be updating your struct when you add/remove variable definitions.

I hope you'll improve on that in the future,
I definitely should. I am not used to manuals containing useful information (something which I guess happens when first learning in obscure modding scenes), so I have a bad habit of only scanning pages with Ctrl+F for things I suspect should be in there somewhere.

Thanks everyone for all the input.
 
I was thinking you'd end up having to maintain the value twice (object and some variable initialization in code). Of course, if you can read them once on creation, that wouldn't be a problem, though you'll still be updating your struct when you add/remove variable definitions.
No, you'd maintain the struct, and then just read the struct for any objects that require those initialisation values. There's only one place the values are kept, the struct. Anything else will read from that struct.
 
Top