Need Tips for "Open World" 2D game

Hello dear unity users, I am currently working on a personnal project. I’m an amateur and have been playing with unity and C# for 2 years and a half now, and decided i could try to go on a somehow “decent” project. I apologize for my poor english and my lack of programming vocabulary.

The project is a 2D Exploration/Shooting/Platformer, it looks like a lot as “Super Metroid” on Super NES.
(youtube is filled with Super metroid videos if you need a visual explanation)

I nailed at modding the standard 2D Character movement scripts and using 2D colliders (So i could play the game a bit when developping it becomes annoying).

The actual issue :

My problem is that there are plenty of rooms with platforms and puzzles. Those rooms are linked by doors, when you pass through a door, the game loads the next room and pauses your character for a few seconds. I want to get rid of that and just pass a door running through it and arrive to the new room just like if the entire game was made in only one room.

I knew this wouldn’t work, but i made rooms using game objects linked together in one big composite collider, and made a prefab of each room. When you arrive in a room, the game instantiates all the rooms that are linked to it, and destroys all the rooms that aren’t. Actually, right now, every time you pass by a door, the game freezes for half a second and ruins all the fun.
If i load the actual 10 sprites that are in my assets, and make my “90” gameobjects use those, i guess it will load faster than loading “90” prefabs directly, is it true?
If it is true, can i do the same about their colliders, just load one box collider, and one of each polygon colliders that i need, and copy those onto every game object?
I thought maybe i could run some kind of loop, loading like only “10” game objects per frame to build the next rooms while the player is playing, and block the door if the player tries to open it while the room isn’t built yet.
Actually, one room can link up to maybe 6 other rooms (more if it is a really big room), and advanced players could pass through two doors in less than 4 seconds. This is why, even if my game is somehow just a project for fun, i need a room generation that works well.

The real issue, i don’t have enough experience to know if what i say are good things to do or not, and i don’t know the actual vocabulary to use properly the search function. I guess open world games use something that looks like a more complexe thing than what i’m looking for, but searching for open world in the search function just spams me with memes about poeple asking for an how to do it, and searching for runtime level generation i find procedural dungeons generation but they include loading screens.

I hope I am not asking for too much in this post, and i will be very happy if you could give me a solution, tips, th vocabulary i need to search properly what i need, or maybe a link to a tutorial.(I understand oral and written english easily even i don’t speak it well).

Thank you a lot for taking the time to read me.

That sounds like exactly how you should be doing it (if your world is so big you can’t just load the entire map at the start).

Since my world is huge, but not bigger than the floating point limitations, I actually load my entire maps at the start of the game and then disable them. I then enable only what is around the player, but the entire world is already fully & permanently loaded.

However since I have multiplayer, I do something similar to that but keep all the world enabled on the server - I just disable specific components like rendering or scripts that aren’t required unless the player is around the area. For a singleplayer game, you could just disable the entire gameobject though unless you need it.

Some more tips.

I have my game entities in a specific hierarchy like a folder/file system. So I can just disable one gameobject called “Graphics” which already holds references to all the spriterenderers I need to disable. Precaching references to objects is way better than GameObject.Find() or GetComponent<>. I also separate my game simulation (C# code / Data) from the game engine (Unity/Rendering/Input) so even if I deleted all gameobjects, turned off the monitor, and disabled input, the game would still exist (I could just press one button to reinstantiate gameobjects & rendering the data at anytime.

This was required in multiplayer so the server could send the entire world & all data across the network when a client player connects). Headless servers disable very specific components, like all graphics, sound, & animation but enable the entire world (collision, maybe NPC’s, harvestable objects like trees, items on the ground, etc.). Host (server is also a player) has all the world enabled & disables those same components (rendering) outside the player’s area, but renables them if the player is around - like they’re a client. Clients who connect to a server don’t have to load the entire world - just what is around them, but I go ahead & load the whole world & sync it for them too since my game is only 4 player COOP & the world is huge but not too huge.

I make my singleplayer games like this too though. Not just in case I want to add multiplayer later, but to make it easy to save/load, change engines if needed, etc.

**

[quote]**
Actually, right now, every time you pass by a door, the game freezes for half a second and ruins all the fun.
**[/quote]
**
Do you know how to use the Profiler? It can help you pinpoint the exact cause of why the game has awful performance.

You also might want to look into Object Pooling.

**

[quote]**
If i load the actual 10 sprites that are in my assets, and make my “90” gameobjects use those, i guess it will load faster than loading “90” prefabs directly, is it true?
**[/quote]
**
Answer this yourself! Do it both ways (if quick enough) and check if there is a performance difference using the profiler.

**

[quote]**
I thought maybe i could run some kind of loop, loading like only “10” game objects per frame to build the next rooms while the player is playing
**[/quote]
**
This works. Using a coroutine to slowly load everything, one bit at a time, helps to prevent unity from locking up.

**

[quote]**
and block the door if the player tries to open it while the room isn’t built yet.
**[/quote]
**
Really the rooms shouldn’t be loading so slow as to make it possible for the player to move so fast that they approach a room before it is finished loading. How complex are these rooms? If huge open world games can stream in their world faster than the player can run into them, a simpler 2D game shouldn’t have any issue.

**

[quote]**
Actually, one room can link up to maybe 6 other rooms (more if it is a really big room), and advanced players could pass through two doors in less than 4 seconds. This is why, even if my game is somehow just a project for fun, i need a room generation that works well.
**[/quote]
**
If your player is moving too fast, then you should expand how many rooms are loaded at each time. Load in a larger area.

They sound like solid methods. In fact, this is the same method suggested by professionals (See my huge open world resource thread in my signature).

That is why I created the Huge Open World Game Resources thread. I know it is lacking though. If any of this helps or you help youself - feel free to post in that thread, linking back to here or explaining your problem/answer. For future reference it helps to have everything in one thread.

Gamedev is hard. Especially when you’ve never done something like this before. It is brain-crushingly difficult, until you learn how to do it. Which is extremely hard unless someone helps.

It sounds like you’re just facing some performance issues that slow down your game too much when loading new rooms. Fix that, and this should all work out from what I understand.

Actually, i don’t know why i didn’t think before i could just load the entire map at the start of the game and just set them inactive. I made some tests and activating / desactivating 5 rooms at the same time don’t even hit the performances in a noticeable way.

Rooms are composed of a few polygons colliders and a composite colliders, about a hundred gameobjects for an huge sized room to compose the floor / platforms / walls, a few more gameobjects will hold some fancy graphics , monsters and power-ups.

I didn’t know how to use the profiler, but i took a look at it and figured out it was really easy to understand and figured out why i should avoid destroying gameobjects.

I looked at your post about huge open worlds, and the floating point problem, what i understood is if my map is too big, its position can’t be stored with precision in a vector3, I don’t think my map will be that big, but it’s really good to know.

I guess i will just make room gameobjects holding a List of Vector3 and load them all at start. Set them active when the player gets near to them, and use an object pooler holding all the game objects needed to populate active levels using the vector3 lists to set their position/eulerangle/scale in a coroutine.

But it can make a list containing from 200 to 1000 rooms(well, 1000 rooms if i spend 10 years creating the game), each room containing up to 200 packs of three Vector3. I’m not a pro, but it sounds like a lot to me,is it too big? Should i find another solution?

1 Like

Great news that you figured it all out. Cheers!

As for performance issues later on when you may get 1000+ rooms? I would only worry about that problem when & if it ever comes to it. As long as your performance is good, no need to pre-optimize for later. You can always fix it later, when the problem actually occurs. If it ever does. And when it does? Just loading huge chunks of rooms, but not all, would still work plenty great. I just wouldn’t worry about streaming the rooms until you actually need to (the world gets big enough that your performance tells you “You shouldn’t load EVERYTHING at once.”) It often turns out that you never need to optimize in the first place, since modern hardware is so fast.