GML "With" priority?

D

DIYDamian

Guest
Hello. I have a question regarding the with construction. When you create an object with the with construction, does the code within the with construction or the objects create event code occur first?

An example would be if there was an object named objThing. This is the create event code of objThing:
Code:
avar = 10;
Another outside object would then create objThing through a with construction:
Code:
with (instance_create(x, y, objThing)){
   avar = 30;
}
What I'm wondering is that when objThing is created through with, will the variable avar stay the value of the create event code or the value assigned by the with construction?
 
Z

zendraw

Guest
it will take the newly assigned var from the 'with' call. so avar=30;
and i think everything in the create event of objthing is runed furst, then everything inthe with statement.
its the same with
var obj=instance create
obj.avar=30;

but here you have a diffrent kind of freedom. like access to temporary vars created in the instasnce creating thing object.
 

NightFrost

Member
You can take it as a general rule. When you do an instance_create the create event code will run immediately, before anything else happens, without exception.
 
D

Dave M

Guest
Instead of using (with)
Why not just do something like:

Code:
create=instance_create(x, y, objThing)){
create.avar = 30;
 

Paskaler

Member
When you create an object with the with construction, does the code within the with construction or the objects create event code occur first?
with is a statement. It either takes an instance id or an object index. If you pass it an instance id, like passing it the return value of instance_create, instance_place, etc. it will change the scope, meaning you can access instance variables without the dot notation: <instance>.<variable>.
If you pass it an object index it functions as a for-each loop. It will go through all of the active instances of the object you passed in and execute the code within the code block.
 

FrostyCat

Redemption Seeker
Instead of using (with)
Why not just do something like:

Code:
create=instance_create(x, y, objThing)){
create.avar = 30;
Because doing it the way you did pollutes the instance scope. A lot of people around here, especially rookies, make a complete pig sty of their instance scope by failing to use var on temporary values. Even if you want to do it without with, you should have used var.
Code:
var created = instance_create(x, y, objThing);
create.avar = 30;
The only exception for this is if this constitutes an ongoing association, for example a player creating a companion that follows it. That's when the return value of instance_create() should be stored in instance scope.
 

TheouAegis

Member
This reminds me, the reason we don't prefer using with on an instance that was immediately created is because with forces an existence check. So the prepended local variable method is a bit faster as a result. However, the manual used to say, and maybe it still does say, that the instance_create function will return a negative value if the function fails. Which has led me to wonder, has anybody ever actually encountered a situation in which the function fails and would precipitate the prepended variable method to fail?
 

FrostyCat

Redemption Seeker
This reminds me, the reason we don't prefer using with on an instance that was immediately created is because with forces an existence check. So the prepended local variable method is a bit faster as a result. However, the manual used to say, and maybe it still does say, that the instance_create function will return a negative value if the function fails. Which has led me to wonder, has anybody ever actually encountered a situation in which the function fails and would precipitate the prepended variable method to fail?
I've never had the function return a fail before, but one borderline case worth considering is the self-destruct-on-create situation.

Consider the following Create event:
Code:
avar = 10;
instance_destroy();
This causes an unknown-variable crash:
Code:
var inst = instance_create(0, 0, obj_example);
inst.avar = 30;
This proceeds just fine:
Code:
with (instance_create(0, 0, obj_example)) {
  avar = 30;
}
You can argue for the crash being the desired behaviour because it alerts the developer to the lost instance, or you could argue for the lack of a crash being the desired behaviour because it doesn't get in the player's face. Either way, there is an exploitable difference between the two methods.
 

GMWolf

aka fel666
would this not be way nicer if we had constructor like systems?
As it stands we have to circumvent the create event completely if we want to initialize different sized data structures, etc
 

TheouAegis

Member
Well, you could use a global var and check in the create events what to do based on what that global was set to.
 

FrostyCat

Redemption Seeker
Well, you could use a global var and check in the create events what to do based on what that global was set to.
That's a viable approach only when instance creations are NOT RECURSIVE (i.e. instances creating other instances also needing parameters this way), and even then you'll end up with a pig sty in your global scope if too many object types use it.
 

GMWolf

aka fel666
Not necessarily. I thought I proposed a solution for this last time, but you seem not to have taken notice.
Because it's fighting against Gamemaker.
At that point I may as well write my own stack programming language...

It's also not that great:
Say I already have an object that makes use of object variables as parameters to initialize data structures, or whatever.
During most of the development I only instatiinst the object in the room editor, and set the variables there.

But now, I want to add procedural generation... I need to rewrite my object to make use of a variable stack? Now it won't work in the room editor anymore.

It's a mess.

You even say it yourself:
While this finally satisfies all 4 conditions, I'm still inclined to believe that this should have been a runner-level functionality.
Besides you are missing a 5th major condition:
The object should still be usable in the room editor.
 

NicoFIDI

Member
Time to share my little stone of knowledge.
This it's the solution I use when I need Object-oriented constructors.

Step 1 make this script
Code:
/// instance_create_ext(x, y, obj, arg0, ... , arg12)
var xx = argument[0];
var yy = argument[1];
var obj = argument[2];

var argsSize = argument_count - 3;
global.inst_arguments = undefined;

for (var i = 0; i < argsSize; i++)
    global.inst_arguments[i] = argument[i+3];

instance_create(xx,yy,obj);
Step 2 you make this on the create event of your object
Code:
/// Argumented instantiation (angle)
var args = global.inst_arguments;
// This makes sure you have your own arguments for this whole script

if (array_length_1d(args) > 0) {
    var angle = args[0];
  
    direction = angle;
    image_angle = angle;
}
Step 3 create your object
Code:
/// Create a object
instance_create_ext(obj_player.x, obj_player.y, obj_bullet, obj_player.direction);
Pros: really not so complex if you know a little bit of code, and it solves the problem.
Cons: you have to check what arguments the object take manually
you do need some extra code and magic, so forgetting it will make you grab your head :/

But there's no solution without sacrifice.

EDIT:
If you are careful and organized you don't even need all the validations.
You can make your create event like this.
Code:
/// Argumented instantiation (angle)
var angle = global.inst_arguments[0];

direction = angle;
image_angle = angle;
 
Last edited:
Top