r/gamemaker • u/refreshertowel • 6h ago
Tutorial Experiments with GM Plugins (or How I Learned to Stop Worrying and Love Reflection)
So I've been doing quite a lot of experimentation with GMs plugin system over the last couple of months, and I figured it'd be fun to share some of the stuff I've learned.
Plugins are still fairly new, and apart from the Prefab builder in the beta branch, there's not really a documented "path" to creating one. So you really gotta figure shit out for yourself by diving into GM. Keep that in mind as you read this, it's not a path "blessed by GM" itself, it's essentially condensing the notes I left myself while doing the experimentation, and figuring out how plugins work, into something others can read, before the GM devs have fully released the system publicly properly.
My own experiments have led directly to the creation of the Sundial Visual Editor (a day/night cycle editor that runs directly inside GameMaker, intended as an authoring tool for Sundial) and a few other things that I'm yet to release.
Please note, it might be easier to read this article on my actual site, as it has got better formatting and stuff than a simple reddit post (plus other cool stuff to explore lol): Experiments with GM Plugins (or How I Learned to Stop Worrying and Love Reflection)

Making the plugin has been an interesting experience, with a lot of ideas for future cool things, and much wailing and gnashing of teeth as things refused to work how I thought they should, or bizarre little quirks reared their ugly heads.
So plugins ey? How do they work?
When most people think about extending what GM can do, they think of extensions, which have been around for yonks, but plugins are a different beast altogether.
Rather than providing additional functionality to your game, plugins are intended to extend GM itself. They're written in C# using .NET.
A plugin generally consists of a compiled DLL, a .gmplugin manifest describing the plugin, and then any other stuff it might need, like an XML layout or images you might want to show (for instance, the little icons on the timeline scrubber for the Sundial Visual Editor are graphics that are stored in the plugin).
GM loads up the plugin, and then you can register commands, add menu items, create editor windows, mess around with project resources and all sorts of other stuff (like hook into various IDE events). In other words, you can kinda take control of GM itself.
To make it clear, you're not building a seperate system really, you're actually working with GMs own interface system, exactly like the Sprite editor, or the Object window or anything native to GM like that.
Building interfaces
GM uses XML layouts to describe its interfaces (things like windows, grids, buttons, etc) and uses C# to provide the behaviour. And you can do exactly this for your plugins, which is how Sundial gives you a fairly substantial editor that feels exactly like a normal part of the IDE.

Sundial uses GMs existing controls wherever it's reasonable, but then I had to write custom-rendered components for the slightly crazier things like the timeline and image preview.
One thing that tripped me up a few times is that GM has several different kinds of windows, and they're not interchangeable, lol.
Like, an ordinary floating tool window is different from an editor window attached to a workspace, which is different from a child editor linked to another window by GMs weird little green workspace lines.
It sounds obvious, but you can actually create a perfectly valid window that doesn't behave anything like the kind of editor you wanted. It's not gonna tell you "Hey mate, you're using the wrong window now, use this type of window instead". It'll just...not draw, or whatever it decides to do.
To wit, during some of my early tests, I managed to create a window that the plugin could totally successfully find and interact with...but it would never actually appear on screen...Which took a frustratingly long time to fix.
It turned out that the problem was the structure of the XML layout. I'd created something that GM thought of as an embedded component, rather than a standalone window...
So if you're attempting to make a plugin yourself, something to keep in mind.
Working with the IDE
Another interesting thing is that you're working inside an application with its own resource management and state and shit. It has its own lifecycle. GM does GM things, and you need to be ready for when it does them.
For example, Sundial stores its settings separately for each project, and it hooks into GMs normal project-saving behaviour to save.
I keep track of changes while the user is editing, if they change some setting in Sundial, I mark the project as modified, and then I actually save the changed data only when the user saves the project.
This sounds kinda simple and obvious. Of course stuff gets saved when you save your project. But there's a bit to consider here. What happens when someone closes the editor without saving? What happens when they switch projects? What happens when they uninstall the plugin?
You need to think about these things because the plugin isn't just responsible for displaying itself to the user. It's properly participating in the normal operations of GM, which includes cleaning up after itself.
A few development tips
Probably the biggest thing I've learned is that it's worth finding out how GameMaker itself does something before attempting to recreate it.
Having a good knowledge of GM itself was pretty crucial, as when I decided "I want a dropdown menu" or whatever, I'd be able to think "What native GM window is doing something similar to what I want here?" And then copy that implementation, lol. Every time I got cocky and decided to just implement something without checking first, it'd inevitably bite me in the arse because of some quirk in how GM checks something, or the lifecycle of the component, or whatever.
The same rule applies when an interface isn't behaving as expected. Rather than trying to guess about what I had access to and how I should use it, a little probe experiment would usually reveal what I was missing.
The probes are just using reflection in C# to grab things like types, methods, and fields and stuff that are exposed by what I was looking at. These were invaluable because of the lack of documentation about plugins right now. I could grab a big list of everything that I could use for a particular component while GM was running, and then examine that and start trying to figure out what things seemed like reasonable attempts to do what I was wanting to do.
This saved an enormous amount of trial and error during the earlier editor experiments, lol.
Another thing to keep in mind is that the IDE and the game runtime are obviously separate environments.
Just because your plugin can manipulate a resource in the IDE does NOT mean you've automatically extended GameMaker's compiler or runtime to understand something new. I was doing experiments with custom assets, and could create a custom asset in the GM IDE, but getting that asset into a game where the game could actually use it while it was running, proved extremely hard, as there are hardcoded parts of GM that restrict this during compilation.
The only method I could find to make it work meant that the project itself was considered corrupted by GM if the plugin wasn't loaded. This ain't great, hahaha, so I'm hoping they add some flexibility to the assets and stuff at some point to allow this kind of behaviour without you having to mutate everything to the point of breaking. However I have since found some other hacky ways of sneaking custom assets into the compilation process without breaking the project, which is kinda cool. But they aren't true custom assets like my original experimentation was.
For Sundial, the editor handles the visual authoring side in the IDE, while the actual day/night grading is performed by a separate completely normal GML code library.
So when the user saves, I actually run a check through the project with project.FindResourceByName(name, type); to see if the correct assets for the code library are present, and if they are, I jam the preset data into the variable definitions of one of the objects that the code library has.
Then the code library can read from that variable in-game, which is essentially the bridge between what is happening in the IDE, and how that gets translated into something actionable in the game itself, while still allowing both the visual editor and the code library to function without the other being present.
Distributing plugins
GameMaker's Package Manager is pretty standard for package managers. It supports npm-compatible package registries and you can setup custom sources, which is actually very useful as I'll explore in a bit.
There are a few steps involved in packaging and signing everything correctly, which you have to handle as the plugin builder. But people installing the plugin for their GM don't need to install .NET, npm or any other development tools themselves, all that's required is for them to point at the appropriate registry and download it to GM (I mean, this is all bog-standard stuff that you can figure out from the beta Prefab builder stuff, without any of this custom plugin work).
For development, I've found it useful to run a local package registry so I could quickly and easily test the actual installation and update process rather than just manually copying files around. I just installed verdaccio and ran the local server whenever I was working on the plugin.
Another thing is that if you're hosting your plugin on the standard npm registry, it doesn't provide the correct metadata for GM, lol. This doesn't mean that it won't work, but it does mean that you can't provide certain details, like an icon image, for example (or at least, I could not work out a way to have that displayed), and it can look kinda ugly or generic when shown in the Plugin Manager.
Instead, I had to build a little "middle man" webpage of my own (just hosted on free cloudflare), and then users point their Plugin Manager at that page. The page requests the package data from the npm registry, and then serves it alongside the extra metadata that GM needs to display everything properly. This was a very annoying workaround to have to implement, lol, but I'm a professional man who does professional things in a professional way because I'm a professional, and stubborn, I guess, so I couldn't just leave my plugin without a cool native icon and stuff in the package manager.
One last thing to consider is version compatibility. Right now, because plugins are essentially undocumented, and they depend on GMs own IDE interfaces, it means that there's always the potential for an update to break something.
Until the GM devs actually come out with a sanctioned list of behaviours and ways that plugins should interact with GM, then you should consider them to be somewhat of a hack, in the same way that doing math on asset ids prior to the big reference update was a hack, and we all know how the reference update broke many people's workflows.
So you'll have to stay on top of updates and test any plugins you might try to build on each new update as it comes out, to make sure it ain't broke.
Anyway!
Plugins are sick. They let you extend GM in some incredible ways, and I'm still finding new stuff all the time as I work with them.
So far I've experimented with extending existing editors, creating new workspace windows, working with project resources, and building more specialised interfaces (Sundial is an example of that, with its custom drawing that is intended to match the in-game visuals), and I really feel like I'm just scratching the sruface. There's a lot you can do, if you have the time and patience. Hopefully it won't take quite so much time and patience after they finally release a sanctioned way to create plugins like the Sundial visual editor, lol.
If you've read this far, here are some other tutorials I've written that you might enjoy perusing:
- Let's build a basic state machine
- How to use Signals in game dev
- How to (comfortably) deal with modifiable stats in RPGS (and other genres)
- A beginners series on procedural generation
A brief plug
You've already seen some examples of the Sundial Visual Editor in action throughout this post. It's free to download and play with, just install it by following this guide:
So you can see exactly how plugins can extend GM by trying it out.
Also, all my libraries are 50% off for the itch Halloween Sale, so check them out. I rarely discount them, so this is a huge saving if you're interested in any of them.
My site: RefresherTowel Games libraries
I've only just released Sundial, which is a sweet day/night cycle system for your game, letting you craft specific and visually arresting moods for each period of the day, alongside having a bunch of cool features like callbacks for the changing day periods, a masking system so you can separate indoor from outdoor areas and light them separately, plus a bunch of other stuff that is useful for day/night cycles.

Best of all, you can edit the entire look of the thing in GM with the Sundial Visual Editor plugin, without having to boot your whole game up to see how it looks in action, and on top of that, it just takes one single measly line of code to get Sundial running in your project:
SundialStart();
When you want it to stop:
SundialStop();
There's plenty more code you can use in Sundial if that's your thing, but if you're a beginner or an artist who hates code, well, there you go! Simple, easy, rustic!
Get Sundial
Read more about Sundial here: Sundial Docs