My Construct Cookbook (2025)

Development principles, practices, patterns and anti-patterns as seen by a random Construct 3 developer (me).

I've been using Construct 3 for about 5 years now. So far I've made over 30 jam games, countless experiments and prototypes as a hobbyist. Between 2023 and 2024 I built about a dozen smaller scope browser games for various clients, so I guess I can call myself a professional game developer, but I haven't done a "proper" game release on Steam or other big platforms. Although it will probably happen in the future, I have no short term plans to start working on one.

In this article I attempt to summarise the principles and practices I try to apply as a Construct developer. They seem to work well for me, your mileage may vary.

Processes

  • Prototype, clean up, repeat.
    I'm a big fan of iterative development, but if there's intention to grow the project into something sustainable, periodic clean-ups and refactors are key. Nobody nails everything for the first time, especially while experimenting with different things instead of following a well thought out "recipe". Even if you are, things might turn out to be duds that need to be removed or replaced and usually leave some spaghetti behind. Or hastily coded experiments turn out to be amazing and need to be kept around and built upon. Usually I do clean-ups every third or fourth session on most projects. This is also when I get rid of the sea of "todo" comments I made during development, to mark the bit that need to be refactored, fixed or optimised.
  • Get to know the tools built by the community.
    Like some of these for example.
  • Look for automation opportunities.
    I don't use a lot of automation, but I do have a script that pushes a fresh HTML5 build of a game to Itch.io (via butler) and to Vercel, and another one that converts my versioned .c3p files into git commits and pushes them to GitHub, which I use as an off-site backup.
  • Aid balancing and content creation workflows that take a long time.
    If you spend a lot of time balancing a game using variables, consider using "rule" files in an easy to edit format (eg. JSON – or JS, so you can have comments, trailing commas and includes). Rule files should contain the values that need to be balanced, ideally in a nice structure. With rule files, changes are easier to track and merge, and it can even act as a data source for generating change logs. A basic rule system can be extended to provide an in-game editor, URL parameter based overrides (eg. ?Player_Health=150), portability (saving/loading to local storage, the file system or an API), just to mention a few. I have a basic rules-and-overrides system in my "blank" project template, because I used it quite a few times lately.
  • Consider your dependencies.
    Relying on third party addons or services has advantages and disadvantages as well. In general I try to keep my dependencies as low as possible. Limitations fuel creativity anyway!
  • Write todo lists and change logs.
    If you're a solo developer (or just prototyping on your own), why not store todo lists and change logs inside the project as files? I've started doing that recently. When I finish something from the todo list, I move it to the change log (with added details if needed), bang. You can even add them to your in-game menu, so players can track what changed and when.

Setup

  • Set up the Construct editor as a PWA to maximise screen space and take full advantage of the extra features (eg. file associations, application shortcut).
  • Avoid unnecessary frustration: prevent data loss & keep "checkpoints" throughout development. I have an article on how I back up my projects in Construct; in short, it's one versioned c3p project file per build, stored in Dropbox, eventually converted to git commits and pushed to GitHub.
  • Learn hotkeys and keyboard navigation, which are especially useful in event sheets. It can be a very nice boost to productivity (and for me it's a lot less frustrating), especially if you're good touch typing. If not, practice :)
  • Get to know the features that help you get around in projects and organize your program structure so you can take full advantage of them (more on that later).
  • Use a template project that has all the boilerplate you need every time (or almost every time). You can download mine, but it's very opinionated and might not make sense to you. In general, if you find yourself re-implementing the same thing for multiple projects (eg. I have one for top-down player movement and camera), it's probably a good idea to turn it into a template, so you can hit the ground running faster when starting a new project.

Development patterns

  • Using "global names" and sheet organization are two topics I've covered in length, so let's see the other ones :)
  • Use naming conventions for:
    • Object types
      ...so they are easier to find when typing their name (eg. Player, PlayerCamera, PlayerHurtbox). Optionally you can apply prefixes that relate to their "type" (eg. 3D object textures, 2.5D billboards, etc: txGrass, txConcrete, bbPlayer, bbEnemy, etc).
    • Functions and custom actions
      Where it makes sense, and stick to it. Some random examples: an onInput custom action on the Player object that handles one-off button presses, an onClick custom action to handle mouse or touch interactions on a button, Enemy custom actions named spawn and spawnGroup, one spawns a single enemy instance, the other spawns a specified number of enemies in a formation.
  • Use folders to group elements of your project.
    Object types, event sheets, files, et cetera – especially if you have a lot of them, so they're easier to locate compared to the default alphabetised list.
  • Use a level and/or game manager object instead of global variables where appropriate.
    Resetting global variables can be a pain if some of them need to be kept. Destroying and recreating a global object is easier and it also helps to separate level or game state variables from miscellaneous stuff.
  • Use the keyboard as much as possible in event sheets.
    Switching between mouse and keyboards slows me down quite a bit and I prefer the keyboard for programming. Construct as excellent search and autocomplete coverage, you can create events, variables, functions, custom action, groups, code snippets without using your mouse.

Development anti-patterns

Some of these are heavily influenced by the fact that I prefer keyboard navigation in event sheets and I use "find all references" a lot to get around a project.

  • Using string literals as identifiers.
    See my article on "global names" for details.
  • Using "On created" for objects that are dynamically spawned.
    On created is useful for initialising objects that are on a layout at start. For dynamically spawned objects, I usually have a spawn custom action on a, essentially a wrapper for a "Create object" system action which also handles or calls any initialisation.
  • Using "On destroyed".
    I can imagine some rare cases where this could make sense, but using a custom action for handling destruction of objects has better readability, and you can search for references to the custom action too.
  • Using groups solely for organisation, using long event sheets and nested groups.
    At the time of writing there's no keyboard shortcut to expand or collapse things (including groups) in the event sheet. I prefer splitting events into multiple event sheets that you can have open side by side.
  • Using global constants / variables anywhere else but one of the "value" sheets.
    Having them grouped together by type in separate event sheets makes them easier to locate. These sheets act like a "table of contents", you can use "find all references" as a jump-off point to locate where they are used.
  • Using extraneous object types for UI when grouping them together makes more sense.
    I use an instance variable named role instead. A random example: if I have a screen with 10 buttons that can each trigger a special skill of the player, I create a single object type (eg. UI_Button_Skill), and set the role instance variable on each with a different unique value. If a UI_Button_Skill object is clicked, a custom action (eg. onClick) is called with the role instance variable passed to it as a parameter. This custom action takes care of the validation (eg. if the skill is not on cooldown) and activates the skill if possible.
  • Using the Audio object's "play" actions directly.
    Instead, I usually have a single PlaySFX custom action on the Audio object, which implements debouncing, sound effect variant randomization, an optional volume multiplier (for balancing the volume of sound effects). It can be extended to add positional audio or anything else you might need. Similarly, I usually have a PlayBGM custom action too, which handles changing the background music.
  • Keeping "template" object instances for dynamically spawned objects anywhere else but a designated "object templates" layout (aka. "object repository", "repo", etc).
    Anything else can lead to ambiguity and thus is more error prone. If the instances are on a separate layout, they are easier to find and change. If the game has "static" level designs (made with the layout editor, as opposed to eg. procedurally generated ones), I use statically placed "spawner objects" on layouts that will dynamically spawn the real objects based on instances placed on the "object templates" layout. These spawners all "activate" at the start of the layout and spawn the required object type (optionally with a specified template), with hierarchy if needed.
  • Using functions that are (mostly) doing something related to a single object type or family (unless a return value is needed, which is not possible with custom actions at the moment).
    I usually have custom actions that initialize or spawn, update ("tick") and destroys a certain object type (or family), named init / spawn (depending on whether they are statically or dynamically spawned), tick (that sometimes calls several "sub custom actions", like tick_input, tick_movement, tick_attack, etc), remove/kill (which discards the object instance and takes care of anything else related to it, eg. adding a score).
  • Using "every X seconds" for anything other then prototyping.
    In the long run Timers almost always work better. Just don't forget to add a "for each" condition for "on timer" actions if there's a chance multiple instances will finish their timers in the same tick.
  • Using "Wait for previous actions".
    Although sometimes it can help make the code more concise, I almost always refactor it so it's no longer needed.
  • Multiple events with the same top condition / trigger.
    I prefer a single event with sub events instead. I group my event sheets by the "type" of events contained within the, (eg. eCollisions for collision checks, eSystem for anything from the System category, et cetera - see my "blank" template for more examples). I find it easier to locate events this way.
  • Using layer IDs.
    They are indices, so they can change when layers are added, removed or sorted. Instead, I use global constants with a string value matching the layer's name. It helps finding references, and provides an easy way to rename a layer (just change the layer name and the value of the constant).
  • Using the boolean type.
    Since Construct doesn't allow passing a dynamic boolean value to functions or custom actions, I just use the numbers instead. I use two global constants (aka. "primitives") called NO and YES with the numeric values 0 and 1 respectively to keep things readable.
  • Passing UIDs in function or custom action parameters instead of copying existing picks.
    If instances are already picked, why pick them again, right?
  • Using the "trigger once" condition.
    For some reason it just screams spaghetti for me. I've never felt the need to use it.

Things I haven't (really) used in Construct

These are features in Construct, that I have zero or almost zero experience with at the moment. There's a good chance I'll use some of them at one point, but I haven't had the need for them yet.

  • Timelines
    If I ever have to do advanced animation in-engine, I'm sure I'll check it out, but I haven't even tried this one.
  • Flowcharts
     I'm pretty sure I'll explore this one in the future, it seems really useful for implementing certain types of mechanics.
  • Signals
    I'm happy with custom actions and functions so far.
  • Pure JavaScript or TypeScript projects
    I'm a web developer by trade (my JS is... okay), but I do almost everything with events. In some cases I sprinkle in some JS code or glue in external libraries. I landed at Construct because I much prefer the event-based system compared to writing actual code. This hasn't changed a bit.
  • Steam integration
    I have no intention to release a game on Steam anytime soon.
  • Networked multiplayer
    I made a few one-screen local multiplayer games though.

 

Hey, thanks for reading! Or scrolling all the way down :) I'll try my best to make an updated version of this next year. If you have any feedback, feel free to find and message me in the Construct Community Discord!

This article was updated on

Related posts

Links
Illustration showing an "under construction" barrier and links of a chain

Links for Construct developers

If you're a Construct developer, check out these neat resources made by the community. Tutorials, tips, optimisation techniques, 3rd party tools, et cetera.