Addressing Variables In Other Instances

In the sections dedicated to variables you found out how to create and use variables within a single instance, or on a global scope, but what happens if you want one instance to access a variable in another, different instance? There are many cases when you may want to do this, for example in a collision with a bullet object, you may want to find out how much damage the bullet does by accessing a variable in the bullet, or you might want to stop the motion of all the balls in a puzzle, or you might want to move the main character to a particular position, or any number of other situations you typically come across in any game. Thankfully the GameMaker Language comes equipped with mechanisms to achieve this.

One of the most common methods of accessing or changing a variable in another instance is to use its object name as an identifier, and then use a point . to tell GameMaker that the variable being referenced should be assigned or changed within that specific object's instance. This is known as "dot notation", and its syntax is as follows:

<object_id>.<variable> = <value>; 

In practice it would look like this:

obj_ball.speed = 0;

With the above code you are setting the speed of an instance of obj_ball. However if you have more than one instance of the given object in the room, then it will apply to ALL of them equally - unless you are using HTML5, in which case it will affect only one, but you have no way of knowing which one it will affect - so if you need to access all instances of an object, you should be using with, as that is 100% cross-platform compatible. In general, this format should only be used when you have a single instance of the object in the room, or (as you will see in the next part) when you have a specific instance ID.

You can also access a single instance of an object when there are multiple instances within the room using the unique instance name to tell GameMaker exactly which instance we wish to address. The instance name constant is the unique identifying constant that is given to each and every instance added to a room in your game. You can find this constant by double-clicking on an instance in The Room Editor:

The instance constant in the room editorNote that this name can be be edited and given a more descriptive name - although the name must be unique to the entire game - and it can be used as the left-hand side of the point:

inst_4DB70D2.speed = 0;

NOTE In-game, this name is a handle to the instance. See Data Types for more info.

By far the most common and practical method, however, is to use a variable on the left of the point, as long as the variable in question has stored a valid instance id. The following examples illustrate this.

// Example 1
var _inst = instance_position(mouse_x, mouse_y, all);
if instance_exists(_inst)
{
    _inst.speed = 0;
}

// Example 2
var _inst = instance_create_layer(mouse_x, mouse_y, "Enemies", obj_E_Parent);
_inst.direction = point_direction(_inst.x, _inst.y, x, y);
_inst.target = id;

In the above code for Example 1, there is an instance_exists call in the code block. This is because using the point method to access or change another instances value will give an error and crash the game if the instance does not exist, and there is the possibility that this is the case in that example. We don't need the check however in Examples 2 and 3 because we know that the instance is there since in Example 2 we created it, and in Example 3, its the other instance in a collision event. However, if there is any possibility that the instance could be destroyed, deactivated, or otherwise removed from the room while using this method, you should always check beforehand using the instance_exists function or the instance_number function.

Note that you cannot use the special keyword all with this method to target all instances (e.g.: all.val = 10; would give an error), but you can use the keywords other and self without issues. For example, using other in a collision event:

// Example 3 other.hp -= 10;
if (other.hp <= 0)
{
    other.sprite_index = spr_E_Dead;
}

It is also important to note that you cannot use any function by itself as the left-hand side of an assignment. For example, the following code would give you an error:

instance_nearest(x, y, obj).speed = 0;

The return value for the expression in that code example is an integer number (the unique ID value for the nearest instance) and so it must be enclosed in brackets ( ) to be used in this way and properly address the instance required. The above code would be correctly written as:

(instance_nearest(x, y, obj)).speed = 0;

//or

var _inst = instance_nearest(x, y, obj);
_inst.speed = 0;

These are all perfectly valid ways of reading, changing and setting variables in other instances, and work because the point is actually an operator. It takes a value as the left operand and a variable as the right operand, and returns the address of this particular variable in the indicated object or instance. All the object names, constants, IDs, etc., simply represent values and these can be dealt with like any other value.

The other way to reference variables in another instance is to use the GameMaker Language statement with

// This will affect all instances of the object "obj_Enemy"
with (obj_Enemy)
{
    target = other.parent;
}

// This will affect one instance of the object "obj_Enemy"
var _enemy = instance_nearest(x, y, obj_Enemy);
if instance_exists(_enemy)
{
    with (_enemy)
    {
        target.x = mouse_x;
        target.y = mouse_y;
    }
}