Level select movement inspired by 'Super Mario Bros.' - In Roblox

Game development has been one of my big interests while learning programming. Roblox, a massive online game platform, provides an environment for developing games easily called 'Roblox Studio'. It has its own game engine and uses the programming language 'Luau', Roblox's version of Lua that implements extra features for better integration with the game engine and to allow creators on the platform to have more control over their creations.

A small system that I decided to try and create is the movement for a level select inspired by the 'Super Mario Bros.' series. 

Level select movement example from 'New Super Mario Bros. Wii'

To be able to create such a system, I first needed to figure out how I would be able to distinguish levels from each other. The simple solution was to assign 'Level IDs' to the parts that would act as the gateway to each level. When you select an object in Roblox Studio, you get access to all of its properties and you are able to add your own attributes. The attributes I added to each part were an 'Id' attribute to uniquely identify each level gateway, and directional attributes that would indicate which level gateway (ID) would be in any direction from the current level gateway. 
Level gateways organised in the hierarchy and the attributes attached to a gateway.

Another idea I had considered was if a set path was to be taken, like going up a hill or making turns to get to the next destination (refer to the 'New Super Mario Bros. Wii' example from above). To implement this idea, I created a folder in each gateway with the naming conventions of: (Level ID to go to) + 'Paths'. With this naming convention, I can automate checks for if a path exists inside a gateway and make the system easily handle large numbers of level gateways as well as multiple paths that may stem from a single gateway. Inside the path folder will be invisible parts that act as the various points the player will need to move to progress and finish the movement to the next level gateway. These parts will be numbered from one to how many paths there may be, making it essential for them to be placed in the proper order for the player to move smoothly to the next pathing point. To visualise this pathing I used beams that would be attached to each level gateway and the paths between them by using attachments on each part.

Path folder in the hierarchy and how they look in the 3D space.

Now that the level gateways are set up with a coherent ID and naming system, these can be used in script to get the level select movement system working. In a local script, a script only the local player can interact with, some variables will need to be set up. One of these variables will hold all of the level gateways by using the 'WaitForChild' function and a for loop to go through every child in the folder that was created to hold them. Another variable will be to store the ID of the level gateway the player is currently on, which will be used for comparisons and validation checks later on. With these essential variables, an input detection system can be set up by using Roblox Studio's service 'UserInputService', more specifically the 'InputBegan' event that can be fired when a key is pressed by the player. With this input detection, I can check for movement keys such as the arrow keys or 'WASD' and also check if any level gateways exist in the directions assigned to these keys and the attributes in the current level gateway, which a function to move the player to the next gateway can be called.

In this movement function, a check will be made for a paths folder. If this folder exists, we can loop through it and make the player's humanoid, the controller for the player, move to each point in the path. To check whether we need to loop through this in reverse order or not, a simple comparison between the current location ID and the next location ID is made. The table, that was created when retrieving all the children in the paths folder, is then sorted based on whether this order is in reverse or not. The paths are then looped through and waits for each movement from the humanoid to be complete before starting the next movement.

Pathing code, where 'LOCATIONS' is a table containing all the locations in the world and 'locationId' is the target location ID.

After the movement along the path is complete, the next step is very simple: move to the level gateway and set the player's position to it after completion.
Final movement code, where 'part' is the target location instance.

Something that is built into the humanoid's 'MoveTo' function is that it timeout and set its state to complete if it has been more than 8 seconds since it had started. This makes it very simple to add redundancy in case it ever breaks or if the gaps between two points are too big since the player's position will be set to the next level gateway after the movement has been completed.

Demo of this system being used.

With this system complete, it can be easily integrated into many project I may want to work on in Roblox. Some features that can be easily implemented into this system include a working level select, where the level can be loaded when you interact with a level gateway (can be seen in the demo video), or allow for multiple worlds to exist, where the level index starts for one again but only works in a different area of the game world. This can be expanded to fit so many different visions, and I will be expanding it myself to try and develop my own small game.