In this tutorial we are going to look at the GameMaker Studio 2 Object Editor. The Object Editor is where you define the different objects that will be used to create the behaviours needed for your game project to function.
You can also watch the following video on the Object Editor:
Essentially, an object is a "blueprint" for instances, and as such are they never actually placed in a room, but rather are used to generate independent instances which can then be changed and manipulated at run time. For example, you could create a single "enemy" object, but have a hundred instances of them in a game room.
In this tutorial we will explore all the features of the object editor, from those that you will use all the time like the Event Editor to those that are only used for very specific types of project like the Physics Editor, and hopefully prepare you to make the most of the options available to you.
Before getting into any detail on the different things that the object editor offers, we are going to give an overview of the main editor window itself and the different options that it contains. Below you can see an image of the object editor as it will appear when you create a new object for the first time (done by right clicking on the "Objects" entry in the resource tree and selecting Create):
When you create a new object you'll see that the Events window will open along with it, but for now we're going to concentrate on the main object properties window and we'll discuss events later in this tutorial. At the top of the object properties you get to name the object. Now, every resource in GameMaker Studio 2 has a name property, and every resource requires a unique name so that the program "knows" what each thing is. You can name resources just about anything you wish (as long as you use standard characters and no spaces) but it is recommended that you use some kind of system to naming so that when you see the resource in other contexts (like in code) it is easily identifiable. For example, many people prefix object resources with "o_" or "obj_", like "obj_Player", or "o_bullet".
You can also assign a sprite to the object. Assigning a sprite is not essential and you can still place instances of an object with no sprite into a game room. This is commonly done when the object is going to control things, like score or cutscenes etc... and an object with no sprite assigned can still draw things if you explicitly tell it to in the Draw Event. However, assigning a sprite to an object means that it will respond to collisions and has a number of other benefits like being able to use built in variables to define how it animates or how it rotates. By clicking on the sprite selector you can assign a sprite from the resource tree to the object:
With a sprite assigned to the object you can click the Edit Sprite button to change the sprite properties, or if you do not have a sprite for the object but wish to create one you can click the Add Sprite button to create a new sprite resource and assign that. You can also edit the sprite resource image that has been assigned by clicking the Edit Image button to open the Image Editor.
Beneath the sprite assignment area you have a button for choosing a specific Collision Mask:
By default an object will use the collision properties of the sprite assigned, but there are cases whereby you may want collisions to be based off of a different mask shape. For example, you may have a top down game where the main sprite has a rectangular collision mask, but to make collisions smoother a circular mask may be better. In these cases you can click the Collision Mask button and select another sprite resource. So now instances of the object will draw the assigned sprite, but base collisions off of the mask sprite.
The last things we'll talk about in this overview are the different object property flags that you can choose to activate:
Checking these flags will do the following:
- Visible - When this is checked, any instance of the object is visible, meaning that it will draw whatever is assigned as its sprite (if no sprite is assigned then it will still draw nothing even if flagged as visible). It is worth noting that switching visible off actually means that not only does it not draw its sprite, but it will also not run any code or DnD™ actions in the draw event if it has any (more on events later).
- Solid - When you flag an instance as being solid, you are telling GameMaker Studio 2 that it should try to resolve any collisions before triggering a collision event. This is a very basic functionality to help make dealing with collisions easier, and in reality all it does is move the instance back to the position it was in the moment before a collision was detected, although you may want to consider creating your own GML code or Drag and Drop™ to deal with this.
- Persistent - A persistent object is one where an instance of it will "persist" across game rooms. This can be useful for controlling aspects of your game across various levels, for example, but should be used with great care, as it's easy to forget it is in a room if it wasn't actually created there.
- Uses Physics - When this property is flagged, you are telling GameMaker Studio 2 that the object is a physics enabled object, which changes dramatically how an instance of it will behave when placed in a room. You should not flag this property unless you have set up a physics room. We'll discuss physics a bit more later in this tutorial.
By default when you create any new object the Object Editor opens along with the Event Editor (you can also open it by clicking on the Events button for the object). Everything in GameMaker Studio 2 is based on Events and the order in which they are run. This is important to note, as essentially the logic behind your game project is a single long chain of events and actions that happen one after the other in a more or less defined order every single game tick (game loop). A game tick is defined by the number of frames per second (fps) that you set your game to run at, so a fps of 60 means that the game loop will run 60 times per second, although it's important to add here that this may not always be the case and if your game is poorly optimised or has too much going on at one time you can get slowdown meaning that the frame rate will drop below this value.
So, your game runs a game loop a set number of times every second, and a game loop is comprised of Events. Some events will happen every single step (tick) of the game loop, and others will happen only when certain conditions are met. We won't go into all the different events here (for that you should press to open the manual and see the section on Objects), but we will cover a few of the most important ones.
The Create Event
Every single object in your project has a Create Event, and every single instance that is placed in a room or added through code or Drag and Drop™ will trigger its Create Event before anything else happens. This means that if you need to add any variables to an instance, for example a variable "hp" for controlling its health value, then it should be done in this event so that it is initialised for all other events. You can also use this event to create particles for a special effect on create, or play a sound, or anything else that only needs to happen once when the instance is created.
The Step Event
The Step Event is an event that happens every game step (tick) while the instance is active within a room. Because of this, it is recommended that you only put essential code here, since too many instances doing too much every game tick is a sure way to get frame rate issues later. So, keep this event for those things that need to be checked all the time, like custom collision checks, or specific user input, or maybe AI. This event is split into three parts, the Begin, the Step and the End events, so you can organise your game logic to perform calculations or actions before or after the main bulk of instances in the room perform them, and they will always run in the same order - Begin > Step > End.
The Draw Event
Like the Step event above, the Draw Event will run every single game tick, but in this event you place all the code or actions that you require for an instance of the object to draw something to the screen. Also like the step event, this event is split into multiple sub events that will run in a set order and do different things. The manual (press ) covers all these events, so here we'll just explain the standard Draw event, as that's the one you'll most likely use the most to start with. Now, when you assign a sprite to an object and then place an instance of this object in the room, it will draw the sprite when you run your game even though you have not added a draw event. This is because GameMaker Studio 2 will default draw automatically the sprite for the instance if no draw event is given. If you add code or Drag and Drop™ to this event then it will no longer default draw, as you are essentially telling GameMaker that you want to take over and tell it explicitly what to draw.
If you take over the draw event by adding actions or code, then you can draw whatever you want regardless of the sprite assigned to the instance - although collisions will still be based of this sprite regardless of what you draw - so you can have a single object that draws all your menu items or multiple elements of the player HUD for example. It should be noted however, that you should try to limit the code or actions added into this event to be only for drawing, as adding extraneous code here could cause issues and isn't recommended unless absolutely necessary.
Other Important Events
As mentioned above, you should really open the manual and revise all the events available to you and see what they do, but just to give you an idea we'll quickly cover some of the ones that you'll use most regularly:
- Alarms - An Alarm is a variable that you can set which will then count down one every game tick until it reaches 0. At 0 it will run the associated Alarm Event, so setting alarm to 30 will count down 30 game ticks and then trigger the Alarm0 event once before setting the alarm value to -1 (this is handy as you can check to see if any given alarm is greater than -1 to see if it is running or not).
- Keyboard And Mouse - These events are split into various sub-events and can be used to capture input from the keyboard or the mouse. Keyboard Events are global scope, meaning that when a key is pressed, a key event will be triggered for all instances and if you have any code in the event it will be run. Mouse Events can be global or local scope, with local events being triggered only if the mouse is actually over the collision mask of the instance (if the instance has no sprite or no mask then they won't be detected, regardless of whether you are drawing anything in the Draw Event or not).
- Collision - The Collision Event will only be triggered when the collision mask of the instance overlaps (collides) with that of another instance of the object you choose. For example you could have an object "objPlayer" and another "objBullet" and in objPlayer you have a Collision Event to detect when a bullet instance has hit them, and in the event you have some code to take 1 off off the "hp" variable you initialised in the Create Event. Note that if you have flagged the object as solid, then when a collision occurs the instance will be moved to the position it occupied in the previous step before resolving the Collision Event.
Once you have added an event, you will be prompted to add either Code or Drag and Drop™ Actions (depending on the project type you have created) to give the event something to perform. Explaining how the GameMaker Language (GML) or Drag and Drop works is outside of the scope of this tutorial, but there are two sections in the manual which explain in great detail how code is structured, one for GML and another for DnD™, so refer to them for more information.
When working with objects in the GameMaker Studio 2 IDE, you can set up Parent / Child hierarchies. This is done by clicking the "Parent" button in the object editor and then choosing another object from the asset explorer to be the "parent" of the one being edited:
Alternatively, you can open the object you want to be the parent and then simply click and drag on objects from the resource tree and drop them into the appropriate space in the parent window (the IDE will show you where to drop them, as shown in the image below):
So, every object in your game project can have a parent object, but what does this mean? Well, when an object has a parent assigned it can share code, actions and events with that parent. This sharing is called "inheritance" and an object that has a parent is called a "child" object. Not only can a child share code with its parent, but you can do checks and run code on parent objects and it will automatically include the child objects too, which saves a lot of time and energy.
If that sounds complicated, then another way to look at a parent object is as a way to "group" objects together under the same umbrella and have them share certain things without loosing their own unique identity. Maybe that still doesn't clarify things too much, so let's give some examples...
Say you have a "player" object and four different "enemy" objects. Now, you want the player to die if he touches any of these four objects and this would normally entail four different collision events with four different sets of actions or code, one for each of the enemy objects. BUT if we make a parent object for all the enemies, then we can create one collision event with the parent object only and it will trigger no matter which one of the four "child" enemy objects touch the player. Handy stuff! In the actual GameMaker Studio 2 object you would see something like this:
In the top image we have four separate collision events and in the bottom image we have a single collision event, as we have created a "parent" object and assigned all the enemy objects to it. Note, though, that a parent object doesn't have to have any events or code in it...
Another example of parenting would be if you have a game where you want to create 10 different looking objects and have them all behave in the same way. For that you would create one parent object and in that have all your behaviour actions or code in the required events, and then you would create your ten objects with no actions or code, but different sprites, and assign them your parent object. Now, when you place these instances in a room they will all behave the same, but look different, since they will "inherit" the events of the parent.
Finally you can use parenting to "mix and match" events and behaviours. We'll illustrate this with one final example... Say you want two monsters: one that moves up and down, while another that moves left and right, but you also want the two of them to have the same health, shoot at the player and hurt the player if they collide with them. In this case you can see that almost all events should have the same actions except for one or two that govern movement and image that's drawn. So, again, we can make one object the parent of the other, but in this case we also define certain events for the child object. These events "override" the parent events, meaning that whenever an event for the child object contains actions, these are executed instead of the actions contained in the event of the parent. If you also want to execute the parent event you can call the so-called "inherited" event using the appropriate action or code.
In the top image is the "parent" object with various events in it, and in the image below it you can see the "child" object. This child only has 3 events defined that override the parent, and it will inherit the rest of the events of the parent. As you can see, inherited events are still shown in child objects, only they have been greyed out to show that they are from a parent object and not part of the child. You can double click on them to open the parent event and see what code is there (note that they can't be edited this way) or you can right-click on them to open up the following menu:
A useful trait of using parents in your game is that wherever you target a parent object, this also applies to the descendants (or "children"). This happens when, in a DnD™ action, you indicate that the action must be applied to instances of a certain object. It also happens when you use the with() statement in code (see the manual for further details), and it works when you call code functions like instance_position, instance_number, etc... where if you supply a parent object then it and all child instances will be included in the checks. Here are some GML examples:
// Destroy all instances of a parent object AND its children
// Get the number of all parent instances and its children
var _total = instance_number(obj_Parent);
It is generally considered good practice in most cases to create one base parent object and have this base object contain all the default behaviour but never use an instance of it in the game. Rather, use all the children objects in the game rooms and only use the parent in situations like those outlined above - for collision, for referencing variables, etc... You should also realise that parents can have parents too! Obviously you can't create a cycle of "parent 1 is child of parent 2 is child of parent 1" but you can create what is called "object hierarchy" where "parent1 is child of parent2 is child of parent3". This is extremely useful to keep your game structured and you are strongly advised to learn to use this mechanism.
The next part of the object editor that we are going to touch on in this tutorial is the button marked "Physics". You will only require this if your object already has the Uses Physics checkbox flagged, and if you are placing instances of the object in a physics enabled room (see the section on the Room Editor in the manual). When you click the physics button, the following windows will be opened:
Now, physics is considered an advanced functionality of the object properties, since it requires multiple steps to be completed for the physics engine to be initialised and work correctly. This is outside the scope of the tutorial, so we'll just go over quickly the concept behind the physics button and outline what it does. For an in depth explanation, please press to open the manual and see the section on Physics in the Object Editor.
When you flag the object as using physics, you need to set up the physics properties as all physics enabled instances must have some type of physical property values set based on real-world values. These initial physical properties define how you want instances of the object to simulate when placed in a physics enabled room. Things like its density, restitution (bounciness) or friction can all be set here, and small changes to these values can have big effects. You also have a number of property flags for changing how the object is treated within the physics simulation (Sensor, Kinematic and Start Awake).
At the bottom of the properties window, there is a button with Modify Collision Shape. Clicking this will open up the physics Collision Shape Editor where you can define the outline of the physical body that the object is to represent. You may be wondering why this is necessary, since if the instance has a sprite, then it also has a collision mask... well, when you activate physics, you are activating a whole different system for collisions and for movement, and none of the "regular" functions will work, and sprite-based collision masks will not be detected either. That is why you have to define a different collision shape for the object, although once defined, instances will still detect collisions with each other and trigger a collision event as you would expect.
The final section of the Object Editor is related to creating Variable Definitions. This is a very powerful tool, especially when used with parenting as it gives you a visual interface for tweaking and adding variables to objects without actually having to create or edit any of the Events that it contains. When you first click theis button you'll get the following window:
This window permits you to define variables for the object and when an instance is created these variables will be initialised before the create event. To add a varaible simply click the Add button. You can then name the variable as well as set the type of variable it has to use and adjust its properties:
The variable name must start with a letter and can contain only letters, numbers, and the underscore symbol '_' with a maximum length of 64 symbols. So, valid variables are things like fish, foo_bar, num1, and invalid variables would be 6fish, foo bar, or *num. Once you have given the name of the variable you need to set its type, which can be any of the following:
It is worth noting that these variables will also be inherited from any parent object, just like events. This means that you can then choose to override or change any or all of them if you wish. When you create a child object of another object resource that has Variables defined for it, these will show up in the Object Variables window like this:
You can see in the top image that the Parent object has four Object Variables and in the bottom image these are also shown, only "greyed out" and have the Inherited From Parent icon to indicate that they have been inherited. These inherited variables can then be edited if you click the Override Variable button, so you can then adjust the range slider or values, or select different items from lists, etc... Note that when you edit a parent variable you can only change the defined value but not the name, nor can you change the variable options like min and max value. Also note that you can add in new Object Variables to child objects as well (and in the example image above you can see that "Character Type" is new Object Variable only for the child object).
If you have edited an inherited Object Variable, then you can click the Delete button to remove the edit, but not the variable. The variable will still be inherited from the parent, but will use the parent default value again. If you need to completely remove the variable, then you must do this from the parent object.
Objects are the fundamental "building blocks" of all games made with GameMaker Studio 2 and understanding them is paramount to getting the most out of the product. So let's quickly just go over the most important things to remember about them:
- Objects are never placed in a game, only instances of objects are used (the object is the "blueprint" for the instance). If you modify an object all instances of that object will be affected, but if you modify an instance, only that instance is changed and further instances created from the same object will revert to the original behaviour or values.
- If an object has a sprite, then it will detect collisions. Collisions are based off of the collision mask for the sprite, unless physics is enabled.
- Objects do not have to have a sprite assigned to be placed in a room and can be used as "controller" objects without any sprites.
- You add Events to objects so that things happen at specific moments within the game loop, and events can contain code (GML) or actions (Drag and Drop™).
- You can create object hierarchies using Parenting to better control how and when things happen.
- Objects can be flagged as having Physics Properties in which case they will require special coding and a distinct setup within the room editor.
- You can create Variable Definitions that will be initialised in each instance before the Create event and that can be inherited and modified by child objects.
If you require further information about any of the specifics relating to objects or instances, don't forget to open the manual (press ).