1. Hey! Guest! The 34th GMC Jam will take place between August 22nd, 12:00 UTC (Thursday noon) and August 26th, 12:00 UTC (Monday noon). Why not join in! Click here to find out more!
    Dismiss Notice

What's the Difference: Objects and Instances

Discussion in 'Tutorials' started by FrostyCat, Jun 21, 2017.

  1. FrostyCat

    FrostyCat Member

    Joined:
    Jun 26, 2016
    Posts:
    4,320
    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() (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() 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:

    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.
     
    Last edited: Mar 30, 2019
    Blaize, Japster, KPJ and 16 others like this.
  2. Snayff

    Snayff Member

    Joined:
    Jul 18, 2017
    Posts:
    213
    Thank you for taking the time to put all of this together.
     
    K3llyll likes this.
  3. rjenman

    rjenman Member

    Joined:
    Jul 17, 2018
    Posts:
    67
    thanks, I was aware of the difference but there is clearly a whole lot of more detailed implications to coding due to the difference and just due to the way code works that I didn't know
     
  4. immortalx

    immortalx Member

    Joined:
    Sep 6, 2018
    Posts:
    296
    Thanks @FrostyCat
    I wish I've studied the basics more before actually making a game (but it's never too late) and your post seems like the cornerstone of the basics.
    I just discovered this post and I'm glad I did, for it certainly cleared things up about objects and instances.
     
    Japster likes this.

Share This Page

  1. This site uses cookies to help personalise content, tailor your experience and to keep you logged in if you register.
    By continuing to use this site, you are consenting to our use of cookies.
    Dismiss Notice