GMS 2.3+ How to prevent performance crash in room editior with an insane big room (sized 960000x960000 with 100000+ instances)

jobjorgos

Member
I have an insane big open world in my roleplaying game. I have all zones in rooms similar of 2000x2000 that are linked to each other to emulate 1 big world. But connecting all these zones to each other takes alot of time, and also when editing zones in the editior, you dont see the surrounding zones so you dont have a clear overview of the total world.

I am consindering now placing the whole world in just 1 insane big room (e.g. 960000x960000 size with 100000+ instances), and disabling all instances outside the players view. In-game this will work fine without performance issues, but in the room editior of game maker it will freeze since all instances get loaded. Is there a way to prevent this so I can acctually use the room editor? otherwise I may have to build my own in-game room editior
 
Last edited:

Simon Gust

Member
First of all, you're lucky you're not using older iterations of game maker where rooms lag at just 1000 instances.
But in general, like inside the game; so many instances cause the editor to do a lot of work.

What I did for one of my projects was just to make my own editor that introduces the same optimisation strategies than in the game itself.
It's a long and difficult task to make a room editor but if your game is big, it's worth it.
 

TsukaYuriko

🌠
Forum Staff
Moderator
I found myself in a similar situation before and was stumped with the same choice. I initially attempted to just go with a massive room, but this turned out to be a bad decision due to the inevitable lag and massive room files (and commits) it would generate (this was back in the days of Studio 1 where the file format was all over the place).

In the end, I went for having multiple smaller rooms as having a massive room would end up being a maintenance nightmare, both to work with in the editor and from a repository perspective. Those rooms were then puzzled back together at run time and loaded and unloaded in chunks. For ease of visualization, I also ended up writing an external room viewer (but not editor) that parsed the room files and let me arrange and tack them together in a virtual space.
 

zendraw

Member
doesnt the current editor in game maker preview only the instances that are actually in view? in gms1 it loaded all of them becouse of that preview of the whole room, but since there is no such preview currently id assume it doesnt load all of the instances.
if it loads all of them your better off making your editor, if building a 1 massive world is a must for you.
one thing i can advice is that you dont nececerly need to have all objects actually in the world. you can have a set number of objects that change theyr position, sprites, and settings depending on where are you and the data they load can be from file.
 

jobjorgos

Member
I'd go the final route, with the in-game editor. I personally would have one room and just build the zones as you approach them.
Sounds as a good idea. I'm just worried if I make and use an in-game editior, and then for some reason I have to change anything in the 960000x960000 room file sometime, I simply cant since opening it cause a performance crash.
If I can never open the room anymore in game maker, I will become independed to the in-game editior tool and the game makers editior will become never useable again. I wonder if that is a problem or not. And also if game maker studio 3 launches sometime, I might have to change anything in the room editior which cant be done in code.

Those rooms were then puzzled back together at run time and loaded and unloaded in chunks. For ease of visualization, I also ended up writing an external room viewer (but not editor) that parsed the room f
This sounds not as my preffered method, but if I dont find any better ways, Ill probly also consider it similar to how you did it!

doesnt the current editor in game maker preview only the instances that are actually in view?
Maybe, but when opening a room, it will be already all zoomed out by default in game maker 2.3, which will result in an instant performance crash. There is also no option in game preferences to not be fully zoomed out when opening a room. Maybe this can be a nice feature in any future updates of game maker.

one thing i can advice is that you dont nececerly need to have all objects actually in the world. you can have a set number of objects that change theyr position, sprites, and settings depending on where are you and the data they load can be from file.
That is acctually a very good idea that I didnot think of yet! Since instances cause the performance drop, I think a room of 960000x9600000 with only tilesets will work fine in the room editior. I gonna test/consider this idea
 

GMWolf

aka fel666
I would use rooms as sort of stamps.
The trouble with splitting a large room into smaller, square regular rooms is if a feature lands in a border its a pain to edit.
Also large features are hard to mkve around, especially if they land on a border.


Instead, I would make each feature a room. For example a house with its NPC's can be one room. That large castle can be one room. The forest can be one room.
Then create a large room and place stand-in objects for the rooms.
On room start, they would instanciate the room into the large room where they are.
That way you have a nice, efficient, high level view of your map (here is a house here is a castle...) And then the details of each of those elements are in their own rooms.

The room functions are a pain to use, so get ready for some painful code.
 

jobjorgos

Member
Instead, I would make each feature a room. For example a house with its NPC's can be one room. That large castle can be one room. The forest can be one room.
Then create a large room and place stand-in objects for the rooms.
On room start, they would instanciate the room into the large room where they are.
This is another great idea! Is there actual a way to load rooms into other rooms?? Or do you just intigrate all the instances/tiles located in the smaller room into the main big room?
 

GMWolf

aka fel666
This is another great idea! Is there actual a way to load rooms into other rooms?? Or do you just intigrate all the instances/tiles located in the smaller room into the main big room?
No built in way as far as I'm aware. I'm sure it would be a good suggestion though as it would most definitely shift how games are developed in a very positive way IMO.

You would need to use the room functions to inspect the room contents and instanciate it yourself.

What I'd recommend is to create a new layer for each room layer (rather than merging them) that way you can disable entire rooms at a time when they go out of view.

(I'm on fire today 🔥. I need to write an extension or something)
 

jobjorgos

Member
No built in way as far as I'm aware. I'm sure it would be a good suggestion though as it would most definitely shift how games are developed in a very positive way IMO.

You would need to use the room functions to inspect the room contents and instanciate it yourself.
Aha I get it! Ill really consider this idea, thanks for this smart trick

What I'd recommend is to create a new layer for each room layer (rather than merging them) that way you can disable entire rooms at a time when they go out of view.
Okay... but how does that prevent an insane big room to crash in game makers room editior? In the room editior you can only turn on/off the visibility of an layer, does that acctually disable their CPU/GPU cost?
Or if you talk about disable layers in-game, then that is honestly not really such special idea I think, because it is also possible to simply just disable objects out of the players view anyway.
 
Last edited:

GMWolf

aka fel666
Okay... but how does that prevent an insane big room to crash in game makers room editior? In the room editior yo
In editor you would have one object to represent the entire other room. No disabling here. Just proxys.


Or if you talk about disable layers in-game, then that is honestly not really such special idea I think, because it is also possible to simply just disable objects out of the players view anyway.
Because, as I'm sure you will find out, disabling individual instances is slow. And tricky to get right.
One method of speeding up the process is grouping them up spatially.
If you are already designing them in these rooms, then they are already grouped spatially. So you don't need to individually figure out what is / isn't in view. You can do it for each room instead, saving a lot of processing.
Alternatively you could group them spatially when building the world. But why do more work than you have to?
Also grouping them by these features (houses, etc) will avoid breaking any interactions NPCs have (say you activated one NPC but not the anvil it's supposed to walk towards for instance)
 
Last edited:

Suttebun

Member
What you're looking for is chunking of a world. Questions with world chunking are how to travel amongst, and load chunks - and what to keep persistent between areas.

Matt Thorson used multiple rooms to create his large worlds, saving a mapX and mapY coordinate with rooms named according to their position in the grid. You would then change the room when you touch the edge of the room.
GameMaker has an option to set rooms as persistent, meaning that objects will retain their changes after being entered the first time.

Keep it up.
 

jobjorgos

Member
one thing i can advice is that you dont nececerly need to have all objects actually in the world. you can have a set number of objects that change theyr position, sprites, and settings depending on where are you and the data they load can be from file.
After consider all methods, I believe this will be the best way for me to do it.

Make the complete world in 1 room with room editior just in tiles, and add all the instances such as buildings, trees, NPCs, items, etc. with code or an own in-game instance placer/editior.

It is right that tiles does not cost much performance right? even if the room is insane big like 960000x960000, I can still open the room editior without that it lags extremely of even cause a crash, since it are mostly instances that cause lag?
 

Yal

🍋 *lemon noises*
GMC Elder
Tiles are stored in a way that makes them O(1) to reach now, the lag could be because instances are just a list with no correspondence to room placement (so there's a lot of looping through the entire list to figure out what to draw).

Some ideas:
  • To make it easier to glue small rooms together, have a special "connection mask" (screen-sized grid in a foreground layer that's automatically disabled - using its name - when the room loads) for every room, which indicates the valid connection region. Only that part of the screen is allowed to have empty tiles for connecting to neighboring rooms (and you need to leave the entire mask empty), forcing you to make rooms that match up in the end. The drawback is that rooms need to be an integer multiple of the chunk size and connections will be uniform (which can look unnatural) but if you make the stuff IN the rooms interesting enough, hopefully players won't notice.
  • YellowAfterLife made an extension that lets you store rooms as JSON data and load later, it could let you have rooms in rooms recursively.
  • Rather than having room connections make sense, have them teleport players to the general area they lead to (and make them be narrow valleys, doors etc that make sense to be very limited to a single spot, rather than "the entire left side of this field leads to the other field"). So try to design areas shaped more like a ¤ than a }, if that makes sense - the entire "body" of the area is self-contained in one room, and the connections are narrow passages.
 

zendraw

Member
tiles wont make it any easyer or performance optimal. the scope of your world is too big. what i was sayng it, make your editor, store the world instances in a file, grid wise. then pre create set number of instances in your game, those instances will be phantom instances and you will set theyr position and sprite and whatever when you load the stuff from the file. the data in the file will be stored like a grid ini_write_real("ASD", string(element)+string(i)+string(j), block);
where i and j will be x/grid_size, y/grid_size. so your just picking up only data your gona use, from the file. if your x/y are not on a grid then you can separate the instances in zones, which will be again in a grid.

imagine your screen to be the area to load. your x/y of the camera will be the starting horizontal and vertical grid slot to load. now how youll deal with load times you have to figure out as you make your game.

if you dont want to write on the drive, you can make an array that holds arrays of the separate zones that your gona load.
 

jobjorgos

Member
the data in the file will be stored like a grid ini_write_real("ASD", string(element)+string(i)+string(j), block);
where i and j will be x/grid_size, y/grid_size. so your just picking up only data your gona use, from the file. if your x/y are not on a grid then you can separate the instances in zones, which will be again in a grid.
Ah really nice to know, with this ini write I have the most important needed to build my own in-game world editior! It is a very good method
 

GMWolf

aka fel666
Some more ideas:
Rather than write your own editor, you can use an editor like tiled. It can export JSON that is easily read into GM.

Avoid ini like the plague: it won't scale.

Use procedural generation for details. You can scatter grass and flowers (for example) procedurally so you don't have to place them by hand, and they won't big down your editor either. It also means they don't need to be stored in your level files.
 

zendraw

Member
honestly you can just use an array that stores the zones, and arrays for the zones themselvs, and these arrays wuld be looked at bitwise. in the sense that 1 number answers for a whole roll. so
slot[x, 0]=grass;
slot[x, 1]=dirt;
slot[x, 2]=water;

i think this is how spelunky was made.

16 for instance is 00010000. so your zone is lets say 8x8 grid. and your checking for dirt. at slot[0, 3] you will set dirt.
 

Japster

Member
Just to add to the mix, and just a couple of ideas... :)

Background: I'm currently storing 1,000's of instances in my first level, but knowing I'd hit some performance issues in the Room Editor, decided early on to create a grid, and have each instance populate the grid with its own properties (Object Type, x, y, orientation, etc) - (The editor is already quite laggy (huge long 'room', many instances), so I'm getting close to activating it...)

Whilst it's nice to be able to see on the room editor where everything is, once I've placed a lot of my stuff, I'm happy that that's where it will stay, design-wise....

So.... ....going forwards, I'll load up (or create if no file found while dev'ing) a ds_grid containing existing placed instances on my map. During runtime, the game will load up this ds_grid, and add to it if any new instances are found on relevant layers. Once loaded and updated, it's saved again. So the room editor only needs to have instances in the room that are being designed / worked on at that point, greatly eliminating lag due to having 10's or 100's of thousands of instances in it... :)

The game, when ran, can simply parse the ds_grid, and re-create these instances either en-masse, or as needed / visible (and can also decide whether to disable any that are not near to the camera view / player, so the grid will also help with chunking... :) )... If creating en-masse, there's also no reason not to just delete the grid and free up memory if desired, once utilised... :)

Plus, Tiles indeed do not seem to affect room editor performance anywhere nearly as badly as instances, so it is possible, if you need some visual representation of where your instances are, to just have a tileset with icons / names of your placed objects, on a layer that you won't enable at runtime, and just select tiles to place onto that layer, for a visual representation of instance locations? - Beyond initially creating said tileset, not a lot of effort! - you could pop a tile on that layer at the location of your instance at design time, then after having all of the newly-added ones from your current design session added to your DS_GRID list of instances, remove the instances, and you're left with a 'flag' or marker of (roughly) where they were, dependent on 'marker' tile size, via the tileset markers...

Alternatively, you could perhaps maybe 'represent' where your instances are, simply by using an 'asset' layer, and dropping Sprites / assets on that layer, instead of instances. If you're not setting local instance variables at design time, then you can maybe even build the above list purely from the asset layer's contents! - if you store a list of sprites and accompanying objects, you could simply generate them from your asset layer contents, I think (not tried that!)...

Phew, long post as always, but hey! - it's something I've already thought about for my own game, and I hope it gives some food for thought! :)
 
Top