• 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!

Using other with "with" statements

L

LawH

Guest
When I create an object using a with statement in another object, basically like this;


//In obj_group
with create_obj_unit {
this = other.this;
}

Does this mean that "this" will forever be connected to the obj_group "this", or can the variable now live it's own life in the newly created object?

I thought it would be so, but after a little testing, it seem that the obj_unit.this will change with obj_group.this after creation. There might be a little error somewhere since I am doing testing, but just to know whether these two objects are now connected forever or the variable will not change according to the other object once it has been created?

EDIT: Just to add, does it also depend on naming them the same or something different? If one creates multiple units using a for loop, then all of those units would share the same variable, when in fact the variable should be different. This feels strange to me.
 

TsukaYuriko

☄️
Forum Staff
Moderator
Variable assignments are performed exactly once when you execute them. Setting one variable to another will set the variable by value, not by reference, so changing the original will not change the copy.

Another story entirely is the meaning of the value you store. If you store, say, an instance ID, this instance ID can then be used to address the linked instance. Retrieving any attribute of that instance this way will give you the up-to-date attributes of that instance - not because the variable you used to store is magically updating alongside the other instance, but because you're just directly accessing the original instance.
 
L

LawH

Guest
Ok so for some reason, when I create an object from other object, and this newly created object has no events whatsoever, that units variable still keeps increasing by 1 forever, like it was a ++ command in a step event.

Let me show you the code.

///Create Units According to Group Size
for (i = 1; i < size; i ++) { //Create enough units
unit_number_i ++;
with create_unit { //what information does the unit need on creation
unit_group_id = other.id; //Get the unit
unit_number = other.unit_number_i; //Give the unit a number, which decides position
}
}

Just to mention again, there are no events in the newly created object, but the number still keeps increasing on the newly created unit.

Oh, the only event that there is is of course the drawing of the unit_number.

For some reason, the unit number keeps increasing on both the creator and created unit, even though the for loop should stop at size (which is 10 at the moment).

What gives?
 

Nidoking

Member
with create_unit
I don't see a definition of create_unit. Is it the name of an object type? Then the with is referring to all of them. Is it an instance ID from an earlier call to an instance_create function? You don't seem to be changing it or creating new units inside this loop, so you're affecting the same unit every time.
 
L

LawH

Guest
create_unit = instance_create(x,y,obj_unit);

Here is my code now as I am trying to get the hang of it;

for (i = 1; i < size; i ++) { //Create enough units
with instance_create(x,y,obj_unit) {
unit_number = other.i;
}
}

This seems to create enough units, however, the unit_number is not transferred into the created object.

It gives an error;

Variable obj_unit.unit_number(100025, -2147483648) not set before reading it.
at gml_Object_obj_unit_DrawEvent_2 (line 2) - draw_text(x,y,unit_number); ############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_obj_unit_DrawEvent_2 (line 2)

And also, what do you mean it affects all of them? Should the for loop not create an instance, then loop back and create another one?
 

Nidoking

Member
I suspect you're creating an obj_unit elsewhere and not setting that value.

And also, what do you mean it affects all of them? Should the for loop not create an instance, then loop back and create another one?
I was referring to the with, if create_unit (which you had not defined) were an object. It is not. Therefore, that statement is moot in this case.
 
When I create an object using a with statement in another object, basically like this;


//In obj_group
with create_obj_unit {
this = other.this;
}

Does this mean that "this" will forever be connected to the obj_group "this", or can the variable now live it's own life in the newly created object?
Nope. This means that obj_create_unit has a variable called "this" that will be set to whatever value obj_group "this" is currently set to.
We don't have pointers in GML, so we simply can't "link forever" variables from different instances together in that manner.
 
L

LawH

Guest
Ok I don't understand anymore, this has happened so many times. I start a project, I change nothing, and suddenly nothing works anymore. It's as if my code just doesn't do anything.

Suddenly, when I exited my testing game, removed a debug text from a draw event, and now no more unit instances are being created. Absolutely nothing changed.

And for some reason none of the variables from the with statement are read. It did read the unit number before, so I added a few more, and now it reads none of them. First it stopped transferring variables without me changing anything, now after removing a debug line, even the units are not created anymore.

Everytime I start working on something, I have to completely redo it.
 
L

LawH

Guest
///Create Units According to Group Size
for (i = 1; i < group_size; i ++) { //Create enough units
with instance_create(x,y,obj_unit) {
group_size = other.group_size;
formation = other.formation;
unit_number = other.i;
formation_width = other.formation_width;
unit_separation = other.unit_separation;
group_id = other.group_id;
}
}

None of these variables are read, it gives an error at launch;
Variable obj_unit.group_id(100027, -2147483648) not set before reading it.
at gml_Object_obj_unit_StepNormalEvent_1 (line 4) - x = (group_id).x + (unit_number * unit_separation); //Puts unit directly in spot ############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_obj_unit_StepNormalEvent_1 (line 4)

group_id is an id, and it worked before, now it doesn't, and I changed nothing.

And just to add, there are no units created outside this for loop. I checked that I hadn't accidentally placed one somewhere. There are no instances of the unit object anywhere. They are only created here.
 
Last edited by a moderator:

TsukaYuriko

☄️
Forum Staff
Moderator
To put that differently: If you do have a variable called group_id, show us where you're declaring it. Please also post the code the error message revolves around, as it's not in the code you included in the previous post.
 

TheouAegis

Member
Do you have any instances incorrectly parented so that they are inheriting code which they shouldn't be inheriting?

Did you put var anywhere in your code? Looking at your for loop, I would suspect not, but improper use of var would cause this error also.
 
L

LawH

Guest
I have no uses of var in the code.

I have no parent objects at this stage.

The variable group_id is declared right before the for loop.

This is in the group object
///Init and Creation Events
group_size = 10; //How many men

running = false; //Is unit running

walk_speed = 1; //How fast they walk
run_speed = 3; //How fast they run
move_speed = walk_speed; //Default movement speed

formation = "line"; //Formation
formation_width = 5; // How many men until new line is formed

unit_number = 1; // Dud for giving a number to a unit
unit_separation = 0; //Dud for distance between units
i = 0; //Test dud for for loops

group_id = id;

array_units = array_create(group_size); //Units in group
create_unit = instance_create(x,y,obj_unit); //if this is used, it either creates identical units, or creates only one of them

///Create Units According to Group Size
for (i = 0; i < group_size; i ++) { //Create enough units
with instance_create(x,y,obj_unit) {
group_size = other.group_size;
formation = other.formation;
unit_number = other.i;
formation_width = other.formation_width;
unit_separation = other.unit_separation;
group_id = other.group_id;
}
}

/*

Once the code in the step event of the unit object runs, I get this error

############################################################################################
FATAL ERROR in
action number 1
of Step Event0
for object obj_unit:

Variable obj_unit.group_id(100027, -2147483648) not set before reading it.
at gml_Object_obj_unit_StepNormalEvent_1 (line 6) - x = (group_id).x + (unit_number * unit_separation); //Puts unit directly in spot
############################################################################################
--------------------------------------------------------------------------------------------
stack frame is
gml_Object_obj_unit_StepNormalEvent_1 (line 6)

If I add "group_id = 0" into the unit creation, the error does not happen, but then the variable will be 0. I can add them all there, but the creation event runs after the with statement, so they overwrite the variables.

If there is some trickery to make things work, please do let me know.
 
Last edited by a moderator:

Nocturne

Friendly Tyrant
Forum Staff
Admin
If I add "group_id = 0" into the unit creation, the error does not happen, but then the variable will be 0. I can add them all there, but the creation event runs after the with statement, so they overwrite the variables.
This is incorrect. The Create event runs the INSTANT an instance is created and then the rest of the code in the "with" runs. If you are getting this error then it's because of something else you are doing. Initialising a variable in the Create event then overwriting it on create using "with" is standard GML behaviour and has always worked this way. You should be setting the group ID variable to an initial value in the create event. And the "with" should be overwiting it. If it's not then something else is going on. What version of GameMaker are you using? You should be able to add a breakpoint to the code and then step through and check what variables are on the instance being created and what their values are.
 
You have this in your create event
GML:
create_unit = instance_create(x,y,obj_unit); //if this is used, it either creates identical units, or creates only one of them
Just to be clear, this WILL NOT create a fresh unit if you call var newUnit = create_unit;
I'm just confused with the comment you put in there
 
L

LawH

Guest
You just created an obj_unit here and didn't set the group_id variable. This is exactly the problem.
That creates a unit? Strange, I would have imagined that it creates a variable, like a shortcut through which one can create the unit. That's how it has been portrayed to be before at least in tutorials I watched ages ago.

I've lost faith in this engines capabilities by having issues with it constantly (I've sent my projects to people and some issues have been fixed by some dubious means if at all), that I no longer trust it at all. It's like having a bug in a puzzle game, you can no longer trust that it will work, and whether you are stuck because you are missing something or if the game itself is broken.

I've used this way before as well, and it has never either created an object in the shortcut, or it has but it has been hidden somehow, which makes me wonder.
 

Nocturne

Friendly Tyrant
Forum Staff
Admin
Sorry, but the way it works hasn't changed in... 20 years? And if you'd read the documentation you'd quickly realise that:

GM8: https://documentation.help/Game-Maker-8/403_05_instances.html
GM:S 1.4: https://docs.yoyogames.com/source/dadiospice/002_reference/objects and instances/instances/instance functions/instance_create.html
GMS 2: https://manual.yoyogames.com/GameMa...anagement/Instances/instance_create_layer.htm

In all examples from the last 20 years of this function they ALL state that the function returns the ID, and two of them even show examples that show this ID being assigned to a variable.

I've lost faith in this engines capabilities by having issues with it constantly (I've sent my projects to people and some issues have been fixed by some dubious means if at all)
You should get into the habit of checking the manual and trying to resolve issues for yourself rather than sending projects to people so they can "fix" them for you... Or make more topics here as we're always willing to help out in any way we can, and most people here are very knowledgeable (far mor than me in most cases, probably... 😅 ).

No offense intended, btw, I just don't like it being made to look like the engine is somehow at fault when (in this case) it's clearly not and the documentation is extremely clear on how to do things. GMS has it's failings, and yes it has it's bugs, but this is not one of them. ;)
 
Last edited:

chamaeleon

Member
Strange, I would have imagined that it creates a variable, like a shortcut through which one can create the unit.
If that is what you imagine, you will be in for a bit of shock as the current behavior is the same as any other major programming language you can care to name. You are calling a function and storing its return value. Just about the most fundamental aspect of programming there is, and it works just like C, C++, C#, Javascript, Python, and so on. The return value in this case is a reference to the created instance, which will be stored in the variable to be be used to affect the instance in desired ways, be it in a with() statement or something else.
 

kburkhart84

Firehammer Games
Don't let this confuse you, just store the knowledge for later.

The whole "shortcut" to run a code thing to store it in a variable....that DOES exist. It is called a function. Basically, you put the code in a function, and then call the function, and that is the shortcut. In versions between 2.3, you would put your functions in script files, but in 2.3, the declaration format for those changed, and the system was extended to where you can declare local functions on objects(called methods), and you can do other neat things with them that didn't exist before. So yeah, I'm guessing that the tutorials you saw were actually using this but you didn't have that detail clear.
 
Blaming the nails, the hammer and the planks when your house falls down is, although NOT the good way to view things in life in general, somewhat a rite of passage for every programmer.
We have ALL thought at one point or another than the machine was against us (spoiler: it doesn't!). Use that to learn and don't be shy to put the blame where it belongs when things fail (i.e. on yourself).

Sorry, but the way it works hasn't changed in... 20 years?
Damn it, Mark! Did we really need another reminder that "20 years ago" is not 1980 anymore? 😂
 
Top