GameMaker: Passing variables into Create event

Time to time I see questions being asked about whether it's possible to set variables prior to instance' Create event being executed or otherwise passing values into the freshly created instance.

Most often, people will say that, no, you can't do that, but here's a bunch of strange workarounds instead (executing in alarm event \ moving all Create code into a user event).

Now, as you might be suspecting by the title of the post, that is not quite correct - there's a bunch of substantially more valid methods of approaching the problem. This post covers them.

Current GameMaker versions

Starting with GMS2.3 (2020), instance_create_depth and instance_create_layer take an optional 4th argument being a struct with variables to add to the instance.

These are set after setting up Variable Definitions but before the Create event runs, meaning that you can do

instance_create_depth(x, y, 0, obj_player, { index: 1 })

and doing

show_debug_message(index)

in obj_player’s Create event will show 1 as expected. And if you’d like to give it a default value for when you don’t provide it, add a Variable Definition for the variable(s).

A straightforward method

The simplest approach to having some variables accessible in an instance' Create event is to store them somewhere where you can easily find them - in global variables, for example:

global.player_index = 1;
instance_create(x, y, obj_player);

And in the Create event you would have:

index = global.player_index;

Now, this requires you to not forget about setting variables prior to creating instances (at best you could assign undefined into the variable once done), but otherwise it's a perfectly good solution.

An organized method

What many people seem to want is passing arguments into a Create event.

And it would seem like you can't do that... or can you? Well, perhaps not the actual argument array, but there is nothing that stops you from making your own.

So you would make a macro with name like ct_argument and value being global.g_ct_argument, making it a "shortcut" to a global variable. And perhaps a ct_count with value being global.g_ct_count for convenience.

Then, you would make a variable-argument-count variant of instance_create script that would store the "excess" arguments in that global variable (and their quantity in other global variable):

/// 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;

In Create event, you would read the now-assigned variable,

index = ct_argument[0];

Permitting you to do

instance_create_v(x, y, obj_player, 1);

Which, I believe, is the best approach - you get timely error messages about forgotten arguments, you can have optional arguments, and you can even make some "wrapper" scripts for having argument name tooltips for cases that need it.

A delightful hack

And, let me close this post with something that you probably never considered for the mere fact of it looking like something you are not supposed to be doing.

Little known fact, but the way GameMaker stores object' instances in memory isn't like things usually work in stronger-typed programming languages - while it would appear like it has conventional inheritance system and instances belong to their corresponding object, internally a reference to the object' "type" is stored in an instance (and used in event lookups), meaning that no instance is actually "hard-linked" to an object type, and allowing a little function called instance_change to exist.

instance_change changes the executing instance' object on fly, at exact moment of execution. Any existing instance' variables are (conveniently) preserved, and you are also (again, conveniently) offered an option to execute the old object type's Destroy event and new object type's Create event during the change.

So the trick is simple enough - first, you add a special empty object, such as obj_blank. This object wouldn't have a parent, sprite, events, or anything else to it.

Then, you would structure your calls as following:

with (instance_create(x, y, obj_blank)) {
    index = 1;
    instance_change(obj_player, true);
}

Creating a blank instance, assigning variables to it, and only then changing it to the actual object, executing it's Create event.

And then you could do

show_debug_message(index);

in obj_player' Create event, and that would actually work.

One particular disadvantage of such approach would be that you would have to re-assign sprite_index/mask_index/physics properties explicitly, though that can be automated with a script.

In conclusion

Overall, while a purpose-specific thing, there are a plenty of valid ways to solve the problem.

Have fun!

Related posts:

11 thoughts on “GameMaker: Passing variables into Create event

  1. Thanks for this article, I read it often because I always need to do this in game maker.

    Also, I’ve found another way of doing it. I don’t know if it’s a good way but it’s so one I use, and I want to share it with you:

    // First create the instance, use the Optional Struct params

    instance_create_layer(x,y, “Instances”, oPlayer, {number : 10});

    // In the create event of oPlayer
    // use the func “variable_instance_exists”
    // if you don’t add an optional struct, it will be set to false, and you will create the var “number” here
    // if you add the optional struct in the instance_create function, it will be set to true, and won’t be read, which mean the var “number” will egal 10

    if !variable_instance_exists(id, “number”) {
    number = 0;
    }

  2. ins = instance_create(100,100,object0)
    ins.depth = 12345 //sprite_index, direction, image-angle can also be used as –
    ins.alarm[0] = 1 //value placeholders

    @alarm[0] of object0:
    my_value = depth
    depth = 0 //or whatever it needs to be

    • I mean, this was usefull for me when I needed to create hundreds of instances in 1 step for a map loading script. The objects had to get their height value of the map somehow.

  3. I love your organized method so much! Being able to pass arguments to a create function is a real game changer for me. Thanks!

  4. I just preffer the solution that you mentioned of calling the alarm[0]=1 on the create of all my objects.

    If I want to add a code that uses a variable that the programmer could like to modify I just put it there, that way I use create for declaration and alarm[0] for processing of initialized variables.

    The thing that I like about alarm[0]=1 is that it is executed just before the begin step event. And so you can do this.

    Create Misile:
    speed=10;

    //Dependent variables
    radianDirection=0;
    area=0;
    alarm[0]=1; //This is just always here
    Alarm 0 Misile:
    radianDirection=radtodeg(direction);
    area=sprite_width*sprite_height;

    And whenever I want to create a misile:
    with( instance_create(x, y, obMisile) ){
    direction=other.direction;
    sprite_index=spBigMisile;
    }

  5. Great article. Using instance_change like that is clever. I use instance_change for object state machines (obj_player_air, obj_player_land, etc.). I know that sounds weird, but it keeps things very organized. And as you pointed out, it works because variables are preserved from instance to changed instance.

  6. I use a script function and pass the variables into that…

    CreateHero(100, 200, 300);

    var ins = instance_create(argument0, argument1, hero_obj);
    ins.hp = argument2;

    • You still declare variables after the instance create event. In the article about how to change the variables directly in the create event.

  7. I’ve done it with instance_copy() and then instance_change()
    So you can clone yourself with all your variables, and then change it to whatever you need.
    Usually, I just save the created objects id and then use with () to pass down whatever variables I need.

  8. I do the Organized Method. And with GM2 you can now add helper comments at the top so that when you call it you can see what arguments to pass in.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.