GML [SOLVED] Assign code to just-created instance BEFORE it runs its create event?

XirmiX

Member
I've found trouble doing this. It essentially boils down to having the create event code from the object be placed inside the object/script that creates it. The "with" variable does not help at all, wish it did, seems redundant otherwise.

What happens is:
Object creates an instance of another object >
new object instance runs its creation code >
object that created the instance changes its parameters

What I want to happen:
Object creates an instance of another object >
object that created the instance changes its parameters >
new object instance runs its creation code

Is this at all possible in any shape or form? I often run into this issue and it is annoying to deal with when I can't. So much code needs to be placed where I don't want it to be, and the instances being created end up not being allowed to have any creation code at all as a result.
 

Raul Rivera

Member
What parameters do you want the created object to have changed by the object creating it?

I think that adding a variable to hold the new instance information, and then using instanceVar.parameter (where Var is your variable, and parameter is what you want to change) should allow you to change things like speed, or direction, or whatever else you need to adjust.
 

XirmiX

Member
@YellowAfterlife I think the extra argument solution would be good may be, if it works how it's portrayed, but I'm having trouble wrapping my head around one thing:

Code:
/// instance_create_v(x, y, object, ...args)
var n = argument_count - 3; 
ct_argument = undefined;
ct_count = n;
for (var i = 0; i < n; i++) ct_argument[i] = argument[3 + i];
var r = instance_create(argument[0], argument[1], argument[2]);
ct_argument = undefined;
ct_count = undefined;
return r;
How exactly am I passing the forth argument (argument[3]) and beyond here into the created instance from this instance_create_v() script? Or how am I at least supposed to have the created instance know that ct_argument[1] is set in the script that it is being created from and take the argument? This is mentioned to be placed in the instance's Create event:

Code:
index = ct_argument[0];
But how does it get the value of ct_argument[0] without a "with()" statement?

I should stress that I'm looking to avoid globals here as well. For what I'm doing here, I need no globals to be used during the instance creation procedure.
 
Uhhh, why can't you use a global? The script that yellowafterlife provided is totally fine (they're probably a better programmer than 99.9% of the people on this board). You macro the global, then whenever you run the script, the global gets given a value, the instance grabs the value from the global, then the global doesn't matter anymore and can be used for another instance_create_v with no problems. I'm failing to see why that would be a problem, unless you specifically already have a global called global.g_ct_argument in which case, what the hell? And just change the name of the global that is being macroed. If you're concerned because people talk about not using globals sometimes, ignore them. Globals are faster to access than any other variable type and this script is a perfect example of a good use of globals. Just don't -overuse- globals (a common mistake would be making an enemy health variable global and then complaining because every enemy loses health when one does...but you're not that silly are you? ;) )
 

XirmiX

Member
I really hate using globals, particularly when it's just for creating instances in ways that I want to. Would have been great if you could pass parameters to instances without using globals of any kind at all like this. The engine could have easily done this by allowing extra parameters to begin with, or some method that holds create event execution, so that an instance exists and have values be assigned to it before going forward. With a macro, that's more or less how it works, though a macro is a global. Guess it's the only way that makes sense to do it.

EDIT: looks like I have to use regular globals, macro means it's a global constant variable.
 

YellowAfterlife

ᴏɴʟɪɴᴇ ᴍᴜʟᴛɪᴘʟᴀʏᴇʀ
Forum Staff
Moderator
But how does it get the value of ct_argument[0] without a "with()" statement?
As the post explains, the macro serves as a shortcut to the global variable so that you don't have to use global.ct_argument or declare it as globalvar (which is deprecated in GMS2 and generally not a good thing to use).

So, with setup intact, ct_count = n would change a global variable's value, and then the object's Create event would be able to access that secretly-global variable without extra typing on your side.
 

Neptune

Member
Pretty much every object i create has this structure in the step event (notice it only runs one time...):
Code:
if !ini
{
    ini = true;
    switch(enum_value)
    {
        case ITEM.Seed_Tree_Spruce:
            sprite_index = s_seed_tree_spruce;
            max_minute = 200;
            grow_sound = snd_tree_grow;   
            grow_object = o_tree;
            grow_object_enum = RESOURCE.tree_spruce;
            grow_object_variant = choose(true,false);
            is_tree = true;      
        break;
    }
}
That being said, I really like to use enum values...
This kind of setup allows you to have very few objects in your resource tree, but you can create all sorts of different entities just by changing the initialization enumerated value.

This also allows all the code dealing with all forms of a particular object to be in one place, and not being passed around by scripts or other instances etc.

I have a more complex version of this, but im not gonna go into it unless someone is interested.
 
Last edited:

Ido-f

Member
I really hate using globals, particularly when it's just for creating instances in ways that I want to. Would have been great if you could pass parameters to instances without using globals of any kind at all like this. The engine could have easily done this by allowing extra parameters to begin with, or some method that holds create event execution, so that an instance exists and have values be assigned to it before going forward. With a macro, that's more or less how it works, though a macro is a global. Guess it's the only way that makes sense to do it.

EDIT: looks like I have to use regular globals, macro means it's a global constant variable.
You could also use a manager object's instance variable.
Gml is so abstracted behind the scenes to be convinient rather than efficient that I wouldn't be surprised if it didn't make any difference, but in other languages that's how you'd avoid using the global.
 

XirmiX

Member
@Ido-f "manager object's instance" variable? Not sure what that implies. And well, in this case, it is counter-convenient. It is probably more efficient for me to just use a global of sorts the way it's already set, even if there was a basic way I could just use some sort of a statement, like, even when using a with statement in some form. It would be cool if the following simply executed the code within the statement before the create event is executed.

Code:
before with(instance_create(x,y,obj_something)){
    //code to execute before executing Create event of the newly created instance...

    //After this section, Create event of the created instance is run...
}
Or, in my case, even better if I could do this:
Code:
before with(instance = instance_create(x,y,obj_something)){
    //code to execute before executing Create event of the newly created instance...

    //After this section, Create event of the created instance is run...
}

return instance;
 

samspade

Member
@Ido-f "manager object's instance" variable? Not sure what that implies. And well, in this case, it is counter-convenient. It is probably more efficient for me to just use a global of sorts the way it's already set, even if there was a basic way I could just use some sort of a statement, like, even when using a with statement in some form. It would be cool if the following simply executed the code within the statement before the create event is executed.

Code:
before with(instance_create(x,y,obj_something)){
    //code to execute before executing Create event of the newly created instance...

    //After this section, Create event of the created instance is run...
}
Or, in my case, even better if I could do this:
Code:
before with(instance = instance_create(x,y,obj_something)){
    //code to execute before executing Create event of the newly created instance...

    //After this section, Create event of the created instance is run...
}

return instance;
While this question is already solved, and I personally normally use @YellowAfterlife's script, a version I've been using more and more often is user events. While this doesn't work in every instance, in works in most and sometimes I think is a little easier to understand as the probably with the variable script is that there's no good way to know what the extra arguments are for - you just have to remember them.

Essentially, the create script of an object contains dummy values and the user event 0 contains the 'traditional' game maker create event then you create an object you do this:

Code:
///example used
var new_object = instance_create....
with (new_object) {
    //set any variables you want here
    //or run other code
    event_user(0);
}
This is a pretty flexible method and also allows you to set up different 'create' events, but it doesn't work in every case.

Edit: You can also do the above with a script rather than a user event, but this keeps an object's code a little more in one place which I like. But there are some cases where a script might be a lot better.
 
Top