There are two ways I can interpret your post, so I will try to touch on both by describing how I structure my code base and how I attempt to cleanly document its behavior.
The way I structure my project is by splitting pieces of logic into their own isolated (Local)Scripts and attaching BindableEvents and BindableFunctions to them which will be used to interact with those systems. I try to keep the responsibilities of each piece of logic to a minimum and to the point, so it becomes easier to learn what each piece does.
My first step when starting a project is always to ask myself which technical pieces of logic do I need? I then write those down and draw connections between them. For example, an ‘achievement system’ will need to access the player’s data, stored in the ‘player data system’. So, for example, when writing a team-based racing games with randomly generated maps, I would instantly write down the following pieces I need:
- Game state system
- Player data system
- Map generator system
- Achievement system
- Team system
I know that the game state system will need to tell the map generator system to generate a map, so for that I attach a new BindableEvent or BindableFunction to the map generator system. It will then act as a ‘method’ of the map generator system. I repeat this for all other interactions. I also add BindableEvents that act as ‘events’ that will broadcast important changes (such as: a map has been loaded, a game has ended, etc.)
The project structure I just described actually helps make documentation very straight forward for me.
When you expand a (Local)Script in the explorer you will see all of its BindableFunctions and BindableEvents. Their names tell you what they do, and their implementation can of course be found inside the script. This way the game explorer is essentially turned into a ‘global overview’ for documentation, assuming that logic is not spread across many different places. It helps give unfamiliar developers a vague idea of what everything does.
As for the documentation within scripts, I make sure to add a couple comments for each BindableFunction and BindableEvent explaining the details of what exactly is happening. The game hierarchy already tells a summarized story due to the different BindableFunctions and BindableEvents and their names, so the contents of each script turns into a ‘chapter’ of sorts, listing only the details.
If there are any systems that are very complex and/or hard to comprehend, I do end up writing external documentation for them. I usually do this in the form of a Google document or a Confluence page. I can then add a comment at the top of the script with a link to the document where I add diagrams and/or images as well.