What's the difference: Objects and Instances GM Version: N/A Target Platform: All Download: N/A Links: N/A Introduction At least a dozen times a week, I see questions on the Q&A section that have to do with people not distinguishing objects from instances. This topic aims to explain the difference between them and the do's/dont's for handling them. Difference between objects and instances In other words: Objects are templates that exist on the resource tree. Objects are types. Instances are products that exist in rooms. Instances are things. Using a physical analogy, "Human" and "Dog" are objects, but "Alice", "Bob", "Fido" and "Lassie" are instances. What you can and can't do The difference between instances and objects means certain operations are forbidden on one or the other. You must keep these in mind at all times. Instances do not have parents. If you need to get an instance's object identity, use object_index. object_get_parent() and object_is_ancestor() can then be used with the object ID to determine the object identity's relationship to other objects. Also remember that it is STRICTLY FORBIDDEN to change an object's property while an instance of it is active, especially its parent. Corollary: NEVER set or reference instance properties using object_*() functions. For example, to change an instance's sprite, you must set sprite_index instead of using object_set_sprite(). Also, NEVER attempt to use object_add() to create an instance. Objects do not have variables. As a result, there is no static scope in GML. If you need static-scope constants or variables, use macros (constants), enums (constants) or global variables (variables). NEVER access a single instance by object ID if multiple instances of the object exist. This includes attempts to reference or set object.variable (which is inconsistent across exports) and using with (object) to apply actions to it (this encompasses all instances of the object instead of just the one you want). Verbally, "Dog's colour" makes sense with one dog, but not with multiple dogs. Corollary: NEVER set or use an instance's own variables with object.variable. An instance's own variables can be referenced as-is without dot prefixes. DO NOT use self. If multiple instances of the object exists, you might end up setting the value for all instances or for some other instance (depending on the export). Finding the right instance As long as multiple instances of an object exists, referencing with an object ID alone will cease to work, so you must learn to find the one instance ID you want to work with. Here are some common situations. An instance's own variables: Type out the variable name as-is, without any dot-prefixes. DO NOT use self. DO NOT use the object ID. Collision events (the ones from the event selector, NOT collision checks in the Step event): other refers to the colliding instance in this event only. IMPORTANT NOTE: other is always equal to -2 and will lose context outside the event. If you need the actual instance ID later, you need to use other.id instead. Collision-checking functions: instance_place() and instance_position() are the instance-ID-oriented analogues of place_meeting() and position_meeting(). Functions that start with collision_ all return instance IDs. Save that instance ID into a variable (e.g. var inst_enemy = instance_place(x, y, obj_enemy);), then use that as the subject to work with (e.g. inst_enemy.hp -= 10;). Note that these functions return noone upon not finding a collision. Always account for this special case whenever you handle collisions this way. Created or copied instance. instance_create() (GMS 1.x and legacy) / instance_create_layer() and instance_create_depth() (GMS 2.x) and instance_copy() return the ID of the created or copied instance. NEVER use instance_nearest() to establish this relationship --- something else could be closer by. Subsidiary instance(s). Same as created or copied instance. If the subsidiary instance needs to reference its creator, the creator should assign its instance ID to an instance variable in the subsidiary instance. Conversely, if the creator needs to reference its subsidiary (or subsidiaries), it must store the return value of instance_create() (GMS 1.x and legacy) / instance_create_layer() or instance_create_depth() (GMS 2.x) immediately. NEVER use instance_nearest() to establish or maintain this relationship --- being the closest does NOT imply being the most relevant, especially in close quarters. If in doubt about whether a function will help you find the right instance, use the Index tab in the Manual to look for its entry. It will tell you whether it returns an instance ID or something else. Looping through instances The with block is GML's main tool for looping instances of the same object or of objects in the same lineage. To learn more about it, see the following articles: Manual entry on with blocks (pay attention to its coverage of other and behaviour of local variables) Variable scope inside a with block with block recipe cards Another common approach is to store instance IDs in arrays, lists or grids, then iterate through them using for loops. This is the most efficient when the same set of instances is repeatedly queried. Here are some important notes on instance looping: Avoid loops based on instance_find(). There is a hidden linear-time lookup in instance_find(), compounding this with a loop makes it quadratic-time. A with block or pre-computed array can do this in genuine linear time. See this post for evidence. Avoid using instance placements as your data model in non-action games. Repeated collision checks are much slower than array lookups, and instance placements cannot be readily cloned for saving or use with AI simulations. A with block in the Draw event does NOT change the drawing depth. If you need to draw at a different depth, change the depth ahead of time. If you need drawing subroutines to happen at a different depth, create instances of worker objects at those depths to do the drawing for you.