From c81da74b2be653546aae97dba5cea9e818c28088 Mon Sep 17 00:00:00 2001 From: gurpreetsinghmatharoo Date: Wed, 18 Sep 2024 11:56:35 +0530 Subject: [PATCH 01/12] docs(feature): Fix back link on array_find_index - case sensitivity --- .../GML_Reference/Variable_Functions/array_find_index.htm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Manual/contents/GameMaker_Language/GML_Reference/Variable_Functions/array_find_index.htm b/Manual/contents/GameMaker_Language/GML_Reference/Variable_Functions/array_find_index.htm index 44566e577..5e00db3bc 100644 --- a/Manual/contents/GameMaker_Language/GML_Reference/Variable_Functions/array_find_index.htm +++ b/Manual/contents/GameMaker_Language/GML_Reference/Variable_Functions/array_find_index.htm @@ -41,7 +41,7 @@

Example:

+ + + \ No newline at end of file diff --git a/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/noone.htm b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/noone.htm new file mode 100644 index 000000000..52f28f9c9 --- /dev/null +++ b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/noone.htm @@ -0,0 +1,53 @@ + + + + + + noone + + + + + + + + + + +

noone

+

It may seem odd, but many times while programming your games will you find the need to check if there are no instances found at a location, in a collision, etc. In those cases you would use this keyword to check for nothing, something like this:

+

if (instance_nearest(x, y, obj_enemy) != noone)
+ {
+     //do something as there is an enemy instance near
+ }

+

In this example, the function instance_nearest will return either noone or the nearest found instance. Basically, any time that you need to check for an instance, you can expect to get either noone or an instance returned.

+

This can also be useful in combination with a with statement: 

+

with (instance_nearest(x, y, obj_enemy))
+ {
+     //do something as there is an enemy instance near
+ }

+

If the function returns an instance, the code between the curly braces { } will run once. If the function returns noone, the code won't be executed.

+

You can also assign noone as a value to a variable to store the result of such a function: 

+

Create Event

+

ins_last_collided_with = noone;

+

Collision Event

+

ins_last_collided_with = other.id;

+

 

+

 

+ + + + + \ No newline at end of file diff --git a/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/other.htm b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/other.htm new file mode 100644 index 000000000..d632b2b7b --- /dev/null +++ b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/other.htm @@ -0,0 +1,96 @@ + + + + + + other + + + + + + + + + + +

other

+

other has two definitions:

+ +

other has multiple ways that it can be used to reference a specific instance or struct: it can be used in a with statement, in a collision event, or in a function. This page is going to explain the last two use cases.

+

Collision Event

+

A collision event can only happen between two instances. You can have multiple collisions between multiple instances, but they are all resolved by GameMaker on a 1-on-1 basis, with the "self" instance that has the collision event and the "other" instance that is colliding with it.

+

Imagine you have a player instance, multiple enemy instances and multiple bullet instances that the enemy can fire at you. You can assign each enemy a single bullet instance but with a different damage variable randomly assigned to it when created, for example:

+

var bullet;
+ bullet = instance_create_layer(x, y, "Bullets", obj_Bullet);
+ bullet.damage = 5 + irandom(5);
+ bullet.speed = 8;
+ bullet.direction = point_direction(x, y, obj_Player.x, obj_Player.y);

+

You can see how we set its variables using the dot notation as outlined in the section on Addressing Variables In Other Instances. This will give each bullet instance a different damage value, but how will the player detect the damage that it has to take when it's hit by a bullet?

+

For this, the player will need to have a collision event with obj_Bullet, and within that event use other to read variables from the colliding bullet instance:

+

hp -= other.damage;
+ if (hp <= 0) instance_destroy();

+

The above code will deduct the amount stored in the other instance's damage variable from the player's hp variable, then it will check to see if the hp is lower than or equal to 0. If it is then it will destroy the player instance. Please note that the other instance must have the variable being checked or else an error will be thrown.

+

 The Collision event is the only event that has a special meaning for the other keyword. In all other events and scripts, the behaviour of other will be defined by the context it is being used in (such as a with() block, a function, struct declaration, etc.).

+

You can assign values to variables, or even create new ones, using other in the collision event, like this:

+

// add ten to the other instance's "mana" variable
+ other.mana += 10;
+ // set the other instance variable "hit" to true, creating the variable if it doesn't already exist
+ other.hit = true;

+

When 'other' changes

+

The page on self contains a section on When 'self' changes.

+

This section will describe those cases in relation to how other changes:

+ +

Struct Declaration

+

Scope doesn't change inside a struct declaration, so other refers to the same scope as self (the current scope), meaning the struct or instance that's initialising the struct:

+

var _struct =
+ {
+     parent_instance : other
+ }
+
+ show_debug_message(_struct.parent_instance == self);
+ // This prints '1' (true) meaning that both sides refer to the same instance +

+

However, you do not need to use other to read variables from the instance as any variables you reference directly will be read from that instance's scope, as described in this section of the manual. You would only need to use this if you wanted to store a reference to that instance's struct.

+

Instance Method

+

Using other within another instance's method refers to the instance that called that method.

+

For example, let's say Object2 has a method that references self and other. This method is then called in Object1. Since the method was created in Object2, it is bound to it and will always use the Object2 instance as the "self", no matter which instance calls it. In such a case, the calling instance becomes other.

+

// In Object2
+ my_method = function()
+ {
+     show_debug_message(object_get_name(self.object_index));
+     show_debug_message(object_get_name(other.object_index));
+ }
+
+ // In Object1
+ Object2.my_method(); +

+

This would cause the instance to first print its own object name ("Object2") and then the object name of the calling instance ("Object1").

+

The same will apply to a method that is bound to a struct.

+

 

+

 

+

 

+ + + + + \ No newline at end of file diff --git a/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/self.htm b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/self.htm new file mode 100644 index 000000000..fef8e006f --- /dev/null +++ b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/self.htm @@ -0,0 +1,85 @@ + + + + + + self + + + + + + + + + + +

self

+

self is the struct or instance that is the current scope of the code being executed. For object instances this will be a struct as well, containing the variables for that instance.

+

The current scope can be changed within an event or function using a with block, in which case self can be used to target the new struct or instance that is now in scope. For example:

+

var val = 100;
+ with (instance_create_layer(x, y, "Instances", obj_Fire))
+ {
+     self.val = val;
+ }

+

In this example you can see that we have a local variable called val and we want it to set the instance variable with the same name in the newly created object instance. To identify the instance variable correctly and tell GameMaker to set it in the instance calling the code block, we use the self keyword.

+

self is used in the same way with structs to reference member variables of the struct. It can also be used within constructor functions to reference the struct being generated from the constructor.

+

When 'self' changes

+

Within an event, the current self will change in the following situations:

+ +

In all of these cases, when self changes to a new scope, other will be set to be the previous scope. The only exception is when a bound constructor method is called. This is described more in When 'other' changes.

+

Notes

+

 You can also use the id built-in instance variable instead of self, but self offers certain benefits. To start with, it is faster for the compiler to identify the instance (or struct) using self rather than id, as the id value goes through the instance lookup table while self does not. Secondly, for those people making extensions, it is very useful to ensure the correct scoping of variables, since it is possible that a project which uses an extension may have a global scope variable or something with the same name as a variable in the extension.

+

 The self keyword is not a shortcut for the actual handle of an instance and should only be used in the context explained above. If you require the ID handle for an instance then you need to use id

+

 The self struct of an instance will be destroyed when its instance is destroyed (either manually or as a result of a room ending), however it will be kept alive if there are any references to the self struct itself or any resources within the self struct (e.g. arrays, methods, structs). This may cause unintended issues in addition to a possible memory leak. To avoid this in case of a struct reference, you can create a weak reference.

+

'self' as a value

+

You can also assign self as a value to a variable. What self references is only determined when you use it to look up a variable. For example: 

+

Create Event

+

my_val = 5;
+ the_thing = self;
+
+ the_struct = 
+ {
+     a: 4,
+     b: 5
+ }
+
+ with(the_struct)
+ {
+     a = other.the_thing.my_val;
+ }
+
+ show_debug_message(the_struct);  // { a : 5, b : 5 } +

+

This code is executed when an instance of an object is created. The instance receives a variable my_val that's assigned the value 5 and a variable the_thing that's assigned the value self. It also receives a variable the_struct, with variables a set to 4 and b set to 5. Next, the scope is changed to that of the struct using a with statement. Between the curly braces { },  the scope is that of the struct. The following line of code is then executed: 

+

a = other.the_thing.my_val;

+

The variable a is an existing variable of the_struct so it can be assigned to directly inside the with. What the expression on the right-hand side refers to can be found by checking the dot operators one by one. other refers to the scope that came before, i.e. before entering the with statement, so the instance scope. The instance's the_thing variable stores the value self, which refers to the current scope, which was just found to be that of the instance. Its my_val variable stores the value 5, which is finally assigned to the struct's variable a. The final value of the_struct is therefore {a : 5, b : 5}.

+

Note that doing: 

+

with(the_struct)
+ {
+     a = the_thing.my_val;
+ }

+

will throw an error, since here my_val is looked up on the_struct's "self". However, the_struct doesn't have a my_val variable!

+

 

+

 

+ + + + + \ No newline at end of file diff --git a/Manual/contents/GameMaker_Language/GML_Overview/Instance_Keywords.htm b/Manual/contents/GameMaker_Language/GML_Overview/Instance_Keywords.htm index 7e5024200..ffac72c23 100644 --- a/Manual/contents/GameMaker_Language/GML_Overview/Instance_Keywords.htm +++ b/Manual/contents/GameMaker_Language/GML_Overview/Instance_Keywords.htm @@ -15,195 +15,14 @@

Instance Keywords

-

To make certain things easier in GameMaker, you can use one of several instance keywords in your code (whether GML Code or GML Visual). These keywords are used to identify instances and structs. Each one is explained in the text below.

+

To make certain things easier in GameMaker, you can use one of several instance keywords in your code (whether GML Code or GML Visual). These keywords are used to identify instances and structs.

+

 The given keywords are represented by negative integer values internally, so care must be taken when assigning or checking variable values against or with these keywords, as you may get unexpected results later as GameMaker interprets the value you have used as something else. You should also note that using the integer values directly instead of the keywords in your code is not recommended at all and could cause issues later on.

-

self

-
-

self is the struct or instance that is the current scope of the code being executed. For object instances this will be a struct as well, containing the variables for that instance.

-

The current scope can be changed within an event or function using a with block, in which case self can be used to target the struct or instance that is currently in scope. For example:

-

var val = 100;
- with (instance_create_layer(x, y, "Instances", obj_Fire))
- {
-     self.val = val;
- }

-

In this example you can see that we have a local variable called val and we want it to set the instance variable with the same name in the newly created object instance. To identify the instance variable correctly and tell GameMaker to set it in the instance calling the code block, we use the self keyword.

-

You can also use the id built-in instance variable instead of self, but self offers certain benefits. To start with, it is faster for the compiler to identify the instance (or struct) using self rather than id, as the id value goes through the instance lookup table while self does not. Secondly, for those people making extensions, it is very useful to ensure the correct scoping of variables, since it is possible that a project which uses an extension may have a global scope variable or something with the same name as a variable in the extension.

-

 The self keyword is not a shortcut for the actual handle of an instance and should only be used in the context explained above. If you require the ID handle for an instance then you need to use id

-

 The self struct of an instance will be destroyed when its instance is destroyed (either manually or as a result of a room ending), however it will be kept alive if there are any references to the self struct itself or any resources within the self struct (e.g. arrays, methods, structs). This may cause unintended issues in addition to a possible memory leak. To avoid this in case of a struct reference, you can create a weak reference.

-

self is used in the same way with structs to reference member variables of the struct. It can also be used within constructor functions to reference the struct being generated from the constructor.

-

You can also assign self as a value to a variable. What self references is only determined when you use it to look up a variable. For example: 

-

Create Event

-

my_val = 5;
- the_thing = self;
-
- the_struct = 
- {
-     a: 4,
-     b: 5
- }
-
- with(the_struct)
- {
-     a = other.the_thing.my_val;
- }
-
- show_debug_message(the_struct);  // { a : 5, b : 5 } -

-

This code is executed when an instance of an object is created. The instance receives a variable my_val that's assigned the value 5 and a variable the_thing that's assigned the value self. It also receives a variable the_struct, with variables a set to 4 and b set to 5. Next, the scope is changed to that of the struct using a with statement. Between the curly braces { },  the scope is that of the struct. The following line of code is then executed: 

-

a = other.the_thing.my_val;

-

The variable a is an existing variable of the_struct so it can be assigned to directly inside the with. What the expression on the right-hand side refers to can be found by checking the dot operators one by one. other refers to the scope that came before, i.e. before entering the with statement, so the instance scope. The instance's the_thing variable stores the value self, which refers to the current scope, which was just found to be that of the instance. Its my_val variable stores the value 5, which is finally assigned to the struct's variable a. The final value of the_struct is therefore {a : 5, b : 5}.

-

Note that doing: 

-

with(the_struct)
- {
-     a = the_thing.my_val;
- }

-

will throw an error, since here my_val is looked up on the_struct's "self". However, the_struct doesn't have a my_val variable!

-

 

-

 

-
-

other

-
- - - - - - - - - - - - - - - -
KeywordDescription
otherThis keyword refers to the "other" instance involved in a collision event, or to the instance or struct that's executing a with statement or calls a function.
- More generally, other always refers to the scope through which the current scope was accessed or, put differently, the scope you were previously in or the scope where you came from.
-

The special keyword other has multiple ways that it can be used to reference a specific instance or struct: it can be used in a with statement, in a collision event, or in a function. This section is going to explain the last two use cases.

-

 If you're not in a collision event and don't change scope using the dot notation . or a with statement, other simply refers to the current scope, i.e. it refers to the same thing as self.

-

Collision Event

-

A collision event can only happen between two instances. You can have multiple collisions between multiple instances, but they are all resolved by GameMaker on a 1-on-1 basis, with the "self" instance that has the collision event and the "other" instance that is colliding with it.

-

Imagine you have a player instance, multiple enemy instances and multiple bullet instances that the enemy can fire at you. You can assign each enemy a single bullet instance but with a different damage variable randomly assigned to it when created, for example:

-

var bullet;
- bullet = instance_create_layer(x, y, "Bullets", obj_Bullet);
- bullet.damage = 5 + irandom(5);
- bullet.speed = 8;
- bullet.direction = point_direction(x, y, obj_Player.x, obj_Player.y);

-

You can see how we set its variables using the dot notation as outlined in the section on Addressing Variables In Other Instances. This will give each bullet instance a different damage value, but how will the player detect the damage that it has to take when it's hit by a bullet?

-

For this, the player will need to have a collision event with obj_Bullet, and within that event use other to read variables from the colliding bullet instance:

-

hp -= other.damage;
- if (hp <= 0) instance_destroy();

-

The above code will deduct the amount stored in the other instance's damage variable from the player's hp variable, then it will check to see if the hp is lower than or equal to 0. If it is then it will destroy the player instance. Please note that the other instance must have the variable being checked or else an error will be thrown.

-

 The Collision event is the only event that has a special meaning for the other keyword. In all other events and scripts, the behaviour of other will be defined by the context it is being used in (such as a with() block, a function, struct declaration, etc.).

-

You can assign values to variables, or even create new ones, using other in the collision event, like this:

-

// add ten to the other instance's "mana" variable
- other.mana += 10;
- // set the other instance variable "hit" to true, creating the variable if it doesn't already exist
- other.hit = true;

-

Struct Declaration

-

Scope doesn't change inside a struct declaration, so other refers to the same scope as self (the current scope), meaning the struct or instance that's initialising the struct:

-

var _struct =
- {
-     parent_instance : other
- }
-
- show_debug_message(_struct.parent_instance == self);
- // This prints '1' (true) meaning that both sides refer to the same instance -

-

However, you do not need to use other to read variables from the instance as any variables you reference directly will be read from that instance's scope, as described in this section of the manual. You would only need to use this if you wanted to store a reference to that instance's struct.

-

Instance Method

-

Using other within another instance's method refers to the instance that called that method.

-

For example, let's say Object2 has a method that references self and other. This method is then called in Object1. Since the method was created in Object2, it is bound to it and will always use the Object2 instance as the "self", no matter which instance calls it. In such a case, the calling instance becomes other.

-

// In Object2
- my_method = function()
- {
-     show_debug_message(object_get_name(self.object_index));
-     show_debug_message(object_get_name(other.object_index));
- }
-
- // In Object1
- Object2.my_method(); -

-

This would cause the instance to first print its own object name ("Object2") and then the object name of the calling instance ("Object1").

-

The same will apply to a method that is bound to a struct.

-

Constructor Function

-

When used within a constructor function, other will reference the instance or struct that is calling that function, however this is not recommended for general use as any external data that a constructor needs to use should be passed in as arguments.

-

 

-
-

all

-
- - - - - - - - - - - - - - - -
KeywordDescription
allAll instances currently active in the room.
-

This keyword is used to tell GameMaker that a function is to be applied, or to check, all active instances within a room (deactivated instances will not be checked or accessed). You cannot use all to access or set variables in other instances using the point method (see here), but you can use it when using with, for example:

-

with (all)
- {
-     speed = 0;
- }

-

The above code will set the speed of all instances in the room to 0. You can also use all within functions to target or check all instances in the room for example:

-

// Check a point for any active instance in the room
- inst = instance_position(mouse_x, mouse_y, all);
-
- // Check all instances for a collision along a line
- if collision_line(x, y, mouse_x, mouse_y, all, false, true) {}
-
- // Add all instances in the room into a motion planning grid
- mp_grid_add_instances(grid, all, false); -

-

all is a very useful keyword and can be used in numerous situations within your code and actions, often cutting down on the amount of code you need to write to achieve a desired effect.

-

 

-
-

noone

-
- - - - - - - - - - - - - - - -
KeywordDescription
nooneNo instance at all.
-

It may seem odd, but many times while programming your games will you find the need to check if there are no instances found at a location, in a collision, etc. In those cases you would use this keyword to check for nothing, something like this:

-

if (instance_nearest(x, y, obj_enemy) != noone)
- {
-     //do something as there is an enemy instance near
- }

-

In this example, the function instance_nearest will return either noone or the nearest found instance. Basically, any time that you need to check for an instance, you can expect to get either noone or an instance returned.

-

This can also be useful in combination with a with statement: 

-

with (instance_nearest(x, y, obj_enemy))
- {
-     //do something as there is an enemy instance near
- }

-

If the function returns an instance, the code between the curly braces { } will run once. If the function returns noone, the code won't be executed.

-

You can also assign noone as a value to a variable to store the result of such a function: 

-

Create Event

-

ins_last_collided_with = noone;

-

Collision Event

-

ins_last_collided_with = other.id;

-

 

-

 

 

log2

-

This function basically asks "how many 2's do you need to multiply to get n?". A common example of use in programming would be to calculate the number of bits that are needed to represent a number. To do this we calculate the log2(x) of the number, round it down and add 1 - for example log2(100) returns 6.643856, which rounded down is 6, to which we add one and it gives us 7. So we need 7 bits to represent 100. It can also be used for describing exponential growth or - decay, and is often called a binary logarithm.

+

This function basically asks "how many 2's do you need to multiply to get n?". A common example of use in programming would be to calculate the number of bits that are needed to represent a number. To do this we calculate the log2(x) of the number, round it down and add 1 - for example log2(100) returns 6.643856, which rounded down is 6, to which we add one and it gives us 7. So we need 7 bits to represent 100. It can also be used for describing exponential growth or decay, and is often called a binary logarithm.

 

Syntax:

log2(n);

- + + - + - + + - +
ArgumentTypeArgumentType Description
nnReal The input value.

 

Returns:

-

+

Real

 

Example:

-

colourbits = floor(log2(colour)) - 1;

+

colourbits = floor(log2(colour)) + 1;

The above code stores the number of bits needed to represent the value stored in the variable "colour".

 

 

@@ -55,7 +51,7 @@

Example:

Next: log10
-
© Copyright YoYo Games Ltd. 2021 All Rights Reserved
+
© Copyright YoYo Games Ltd. 2024 All Rights Reserved
- - \ No newline at end of file + + \ No newline at end of file From b83ef67d176bfef5fdfd031315609bbff2441c01 Mon Sep 17 00:00:00 2001 From: gurpreetsinghmatharoo Date: Thu, 19 Sep 2024 16:03:18 +0530 Subject: [PATCH 09/12] docs(general): Document 'other' behaviour in a struct literal * Also changed references of a self/other 'value' to 'reference' https://github.com/YoYoGames/GameMaker-Bugs/issues/2044 --- .../GML_Overview/Instance Keywords/other.htm | 47 +++++++++++++++++++ .../GML_Overview/Instance Keywords/self.htm | 14 +++--- 2 files changed, 55 insertions(+), 6 deletions(-) diff --git a/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/other.htm b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/other.htm index d632b2b7b..fc8953f3e 100644 --- a/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/other.htm +++ b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/other.htm @@ -47,6 +47,7 @@

When 'other' changes

  • Inside a with block, other will be the instance or struct that called the with() function
  • When calling a method that is bound to an instance or a struct, other will be the instance or struct that called that method
  • When calling an unbound constructor function, other will be the instance or struct that called that function. If the constructor is bound as a method, then other will be the instance or struct to which the constructor method is bound.
  • +
  • When stored as a reference through a struct literal, covered below under "'other' as a reference".
  • Struct Declaration

    Scope doesn't change inside a struct declaration, so other refers to the same scope as self (the current scope), meaning the struct or instance that's initialising the struct:

    @@ -59,6 +60,52 @@

    Struct Declaration

    // This prints '1' (true) meaning that both sides refer to the same instance

    However, you do not need to use other to read variables from the instance as any variables you reference directly will be read from that instance's scope, as described in this section of the manual. You would only need to use this if you wanted to store a reference to that instance's struct.

    +

    'other' as a reference

    +

    The page on self contains a section on 'self' as a reference with an example, which you should read before this section. This will cover that same example and how it would affect the other reference.

    +

    Both rules covered on the aforementioned page regarding storing self as a reference also apply to storing other as a reference. However other would be the previous self as it would be if self was stored.

    +

    Let's take that same example and replace self with other:

    +

    name = "instance";
    +
    + struct = {
    +     name : "struct",
    +     other_ref : other,
    +     other_name : other.name
    + }
    +
    + show_debug_message( struct.other_ref.name );
    + show_debug_message( struct.other_name ); +

    +

    This prints:

    +

    instance
    + instance

    +

    The base scope in the code example is an instance, so with self changing in other_ref it stays as the instance scope (which was the "previous" scope) and for other_name it also remains the instance scope as the self there is unchanged and there is no previous scope before the instance (as it is the base scope).

    +

    However, what would happen in the second case if there were another scope before the instance scope?

    +

    We can answer that question by placing this code inside a with() block:

    +

    name = "other_instance";
    +
    + with (inst)
    + {
    +     name = "instance";
    +
    +     struct = {
    +         name : "struct",
    +         other_ref : other,
    +         other_name : other.name
    +     }
    +     
    +     show_debug_message( struct.other_ref.name );
    +     show_debug_message( struct.other_name );
    + } +

    +

    This prints:

    +

    instance
    + other_instance

    +

    In the first case, as self changes to be the struct, the instance that is inside the with() block becomes the previous scope and is stored in other.

    +

    However in the second case, as self remains the with() instance, other retains the scope before that, which is the base scope ("other_instance"). You can visualise the hierarchy of scopes as such:

    +

    other_instance
    +  > instance
    +    > struct

    +

     

    Instance Method

    Using other within another instance's method refers to the instance that called that method.

    For example, let's say Object2 has a method that references self and other. This method is then called in Object1. Since the method was created in Object2, it is bound to it and will always use the Object2 instance as the "self", no matter which instance calls it. In such a case, the calling instance becomes other.

    diff --git a/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/self.htm b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/self.htm index 48bf6861b..6e6c326d7 100644 --- a/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/self.htm +++ b/Manual/contents/GameMaker_Language/GML_Overview/Instance Keywords/self.htm @@ -30,16 +30,17 @@

    When 'self' changes

  • Inside a with block, as shown above
  • When calling a method that is bound to an instance or a struct, the self during the execution of that function will be the instance or struct to which the method is bound
  • When calling a constructor function, self will refer to the new struct that is being generated as a result of that function.
  • +
  • When stored as a reference through a struct literal, covered below under "'self' as a value".
  • In all of these cases, when self changes to a new scope, other will be set to be the previous scope. The only exception is when a bound constructor method is called. This is described more in When 'other' changes.

    Notes

     You can also use the id built-in instance variable instead of self, but self offers certain benefits. To start with, it is faster for the compiler to identify the instance (or struct) using self rather than id, as the id value goes through the instance lookup table while self does not. Secondly, for those people making extensions, it is very useful to ensure the correct scoping of variables, since it is possible that a project which uses an extension may have a global scope variable or something with the same name as a variable in the extension.

     The self keyword is not a shortcut for the actual handle of an instance and should only be used in the context explained above. If you require the ID handle for an instance then you need to use id

     The self struct of an instance will be destroyed when its instance is destroyed (either manually or as a result of a room ending), however it will be kept alive if there are any references to the self struct itself or any resources within the self struct (e.g. arrays, methods, structs). This may cause unintended issues in addition to a possible memory leak. To avoid this in case of a struct reference, you can create a weak reference.

    -

    'self' as a value

    +

    'self' as a reference

    When self is used in a struct literal, there are two rules that define its scope:

      -
    1. When used as a value itself (just self) to be read later, it stores the scope of the struct being created
    2. +
    3. When stored as a reference (just self) to be read later, it stores the scope of the struct being created
    4. When a value from it is accessed, it is read from the scope that is creating the struct, not the struct itself

    Consider the following code that is run in an instance:

    @@ -47,11 +48,11 @@

    'self' as a value


    struct = {
        name : "struct",
    -     self_value : self,
    +     self_ref : self,
        self_name : self.name
    }

    - show_debug_message( struct.self_value.name );
    + show_debug_message( struct.self_ref.name );
    show_debug_message( struct.self_name );

    This sets a name variable in the instance, then defines a struct with a name variable as well.

    @@ -60,9 +61,10 @@

    'self' as a value

    However when you execute this code, you get the following output:

    struct
    instance

    -

    The argument for the first call, struct.self_value.name, where self_value stores self, resolves to the scope of the struct, instead of the scope of the instance, which was the active scope when self was stored into the variable.

    -

    This happens as a result of self being stored as a value in the struct literal which follows rule 1 defined above.

    +

    The argument for the first call, struct.self_ref.name, where self_ref stores self, resolves to the scope of the struct, instead of the scope of the instance, which was the active scope when self was stored into the variable.

    +

    This happens as a result of self being stored as a reference in the struct literal which follows rule 1 defined above - with it pointing at the struct.

    The argument for the second call, struct.self_name, correctly refers to the name of the instance, as self was accessed at the time the instance was the current scope. This follows rule 2 defined above.

    +

     These rules also apply when storing other as a reference, see 'other' as a reference.