How do I organize objects, events, external events, external layouts and global objects for a longer platformer game

We are working on our first Indie game which is going to be a mobile friendly classic platformer. We plan on having 4 worlds, with 9 playable levels for each world. So its going to have a ton of potential scenes if I did one scene per level. After creating a bunch of objects (enemies, platforms, coins ect) and a prototype level Iā€™m working to figure out the boring stuff, how to organize everything for mass level design. Iā€™ve not seen this all laid out in one place but here is what I have figured out.

I should use scenes to represent each major set of unique objects, so one scene per world. Each world will have a bunch of new objects to keep the player interested. Trying to follow the advice in the documents of keeping only very few objects global (the player, controls and UI displays).

Then Iā€™ll create External Layouts for each unique level the world. So Iā€™ll have a set of external layouts which will be the playable levels within each world/scene.

On the event side I split the logic between a few external events which will be linked by each scene (world). Iā€™ve got one for Player, enemies, objects, and platform events.

Ok to the questionsā€¦

Am I using scenes correctly here? Organizing them around sets of objects that will need to be re-used, so that I donā€™t make tons of objects global objects?

Currently I am using a new object for everything in the game. I have multiple platforms that behave the same, but each is its own object. However, in the platformer template, I see where multiple platforms are inside one object as unique animations, this seems more efficient. But I havenā€™t figured out how to place one specific platform from the list of animations when doing the level building. So, is it best to group similar things into a single object? How do you place a specific animation from an object on the scene?

What other things do I need to consider to make sure the game can scale in size (levels) without causing other issues?

When you place an object in the editor, click on it and check the properties panel on the left side of the editor. Just above the words ā€œInstance Variablesā€ is a box to enter the animation number.

Your splitting up of events and external layouts is a good approach, and using a scene per world is a good idea. Putting objects with the same mechanic but different appearance as animations in one object will help reduce the events youā€™d otherwise need. Which in turn means a reduced chance of bugs.

1 Like

I think I can be a great resource for you :sweat_smile:

My Game TripleJump that I just released has a very similar design:

I went with the following main scenes related to gameplay:
Level - This is essentially just the layers and some gui layout, but it has ALL of the game objects defined here AND all of the background assets for every world theme.
Overworld - This is essentially one huge map with different mechanics than the levels, so it only acts as a bridge between levels.

The ā€œLevelā€ scene has a lot of objects in it that are not used in every level, but I didnā€™t find that to be a problem. Each External Layout is named in a world-level style like ā€œ1-1ā€, ā€œ1-2ā€, etc. I use a global variable called ā€œCurrentLevelā€ that is set via the ā€œOverworldā€ and the Level scene logic loads the appropriate External Layout based on that variable.

I considered many times creating a unique Level scene for each world, mostly because it was annoying to sift through nine layers of background images for nine themesā€¦ but eventually I convinced myself that it wasnā€™t worth it because of the maintenance cost: If you want to update an object thatā€™s shared across multiple worlds (like the player sprite) then you would have to do that for every level sceneā€¦ which is prone to manual errorā€¦ itā€™s so easy to just miss one, or to forget to change the collision box in just one of those copiesā€¦ and debugging that would be a nightmare.

Next, you are right on about using External Events for related objects, and for specific functionality. I had Enemies, Objects, GUI, JumpEngine (for all the jump mechanics), TextButtons (my generic button library used in every scene), LevelEngine, BackgroundEngine, TileMapEngine, and JukeBox (to manage background music for each scene).

I also used different objects for each of my platforms, just be sure to create a group called Platforms and add all those objects to the Platforms group. There is no current way in Gdevelop to select objects by behavior. Youā€™ll also want to get in the habit of using object groups for everything thatā€™s relatedā€¦ it will make your logic much more generic and simple. However, maintaining groups is a manual process so itā€™s worth designing some debug code to find any objects that donā€™t have groups assigned, and when you run into a bug check that firstā€¦ it will happen I almost promise.

Just hit me up if you have questions.

2 Likes

I forgot some really important advice that I wish I knew when I started:

Use ā€œLogic Groupsā€ for EVERYTHINGā€¦ there should be no code that is not a part of a group.

  1. It really helps from a UI perspective once your code grows large
  2. The performance debugger (that I never really used :sweat_smile:) bases all of itā€™s timings on code groups
  3. Itā€™s like a super comment, so use code groups instead of comments and youā€™ll thank me later.

After you load your External Layout, add a bunch of conditionals to see which objects are in the scene and set a flag for those object types
Compare two numbers Ghosts.Count() > 0 => Variable LogicFlags.Ghosts = true
Then in your ExternalEvents put a conditional around all the Ghost logic and only process that if (LogicFlags.Ghosts is true)ā€¦ make it ā€œtrigger onceā€ too. This will really help with performance because youā€™ll only execute the logic that pertains to the current objects in the layout.

2 Likes

Thanks for all of the great insights, it was exactly the kind of details I needed. Iā€™ll surely be back with more questions once I absorb this.