[Simple Layers Framework] - Utilizing Layered Architecture in making Games

Simple Layers - Framework

Reference Guide/Documentation

About:

– [Why Simple Layers?] –

Simple Layers is a lightweight framework for organizing your game into layers of systems. Built on the principles of single-script and layered architecture, it keeps things minimal: one script on the client and one on the server start the entire game, loading modules that are neatly divided into layers.

Get it here!
VVV


– [Summary] –

Layered architecture is a way of organizing code into stacked layers, where each layer has its own responsibilities. A key rule of this is that a layer can only talk to the next layer directly beneath it (never skipping).

*A quick overview of Layered Architecture: https://www.youtube.com/watch?v=WiXp2p4obe4

I made it so that you can create any amount of layers as you wish. However usually you’ll never need more than four.

In this framework each layer has their own systems, which is just my fancy name for a module, but that is specifically made to work under some layer. You can add any amount of your own systems to your layers.

Systems can talk to other systems of the same layer, as well as that, systems can also talk to other systems of the next layer beneath it.


How to use:

– [Setup] –

Free Model: https://create.roblox.com/store/asset/74676753921417/SimpleLayersFramework
Insert the free model into workspace and you should see this:
image
Ungroup everything in the ‘Ungroup in’ folder to the correct place and you’re done!
This setup currently does not have any layers so lets start creating layers!

– [Creating more layers] –

From the Templates folder take the ‘LayerTemplate’ and insert it under the ’Layers’ folder of either ‘SimpleLayersClient’ or ‘SimpleLayersServer.’ (Doesn’t matter which they’re pretty much the same.) You can name it whatever you want.

A layer consists of the following:

  • The ‘Configuration’ is used to indicate the order of layers.
  • The ‘Systems’ folder is where you will put all your system modules.
  • The ‘Mediator’ module is what is used to allow systems to talk to each other

[Configuration]:

Configuration has a single attribute ‘LayerOrder’ which lets the framework know the order to load layers, where the lowest number is loaded first. This is because we want to load the layers from bottom to top. ‘LayerOrder’ must be a unique number different from what was set in other layers.

[Mediators]:

When adding multiple layers there is a bit of a setup required in order for certain functions of the ‘Mediator’ module to work properly. Let’s say we added two layer templates and named them Layer1 and Layer2. Where Layer1 is stacked on top of layer2. For now, since we currently have no systems in the layer, all we need to do is:

  1. Layer1 is above Layer2, this means that Layer1’s Mediator module needs to require Layer2’s Mediator module. Shown here:
    image

  2. Next Layer1’s Mediator Type module needs to require Layer2’s Mediator Type module. As well as that on the line ‘GetSystemFromNext’ replace ‘nil’ to ‘NextMediatorTypes.GetSystemFunction’ Shown here:

Because Layer2 is the last layer of the stack, there is no ‘NextMediator’ therefore you can just leave it as is.

– [Adding a system to a layer] –

As long as you don’t have any duplicate names you can pretty much add any module you want to a layer’s system folder.

For each system you can add the following optional functions: Init() and Start()

At runtime the Layer will go through each system and load them. It will first require each system, then call the Init() function for each system, and finally call the Start() function for each system. (If there is no Init() or Start() function in the system then it’ll skip it.)

– [Accessing other systems] –

As said before, Systems can talk to other systems of the same layer, and they can also talk to other systems of the next layer beneath it. This is done through the use of the Mediator.

The Mediator has two functions:

  • GetSystem(Name: string)
  • GetSystemFromNext(Name: string)

GetSystem() takes in a name and returns the system with the same name that is from the same layer the mediator originates from. The Mediator’s GetSystem() function should only be used after the Layer Module is done requiring each system, this is because during the ‘requiring’ stage we are indexing the references for each system. It is safe to use under the optional Init() and Start() functions.

GetSystemFromNext() is similar to GetSystem() except it will return the system from the next bottom layer and can only be run when the next bottom layer is finished completely loading.

If typed correctly these two functions will give the correct autofill options depending on the system returned. So let’s see how to set that up now.

[Setting up Types]:

Lets say Layer1 has systems named, Example1 and Example2.

Each of these systems should have a separate Types module different from the system module. In this case here I put them under the corresponding system module.

In each of the Type modules, write all the functions/properties you want the corresponding system to have exposed. In the case of Example1 and Example2 it both has a single Print() function.


image

Next in Layer1’s Mediators Type module, we require the Type Modules of Example1 and Example2. Then we can use those to overload the type ‘GetSystemFunction’ as shown:

This will then allow the typechecker to detect what system you want and display the correct autofill options.

Remember in a previous example we got Layer1’s Mediator Type module to require Layer2’s Mediator Type module? In that example we set the type ‘GetSystemFromNext’ function to be the same as Layer2’s GetSystemFunction type! That means if we do the same thing we did to Layer1’s Mediator Type Module to Layer2, then the GetSystemFromNext will also have the correct autofill options!


Example use Diagram:

The free model provides an example of how everything works together. The image below shows how it works:

6 Likes