Here are the best code architectures for indie games. I made a bunch of indie games, so I'm a professional idiot and feel qualified to talk about this. What you have to realize is that most games under the hood are pure spaghetti. Spaghetti means bad, horrible, horrible code. In case you're not aware, most games, um, especially most indie games are just horrible, horrible spaghetti code under the hood. Pure chaos. And it's actually okay. If it works, it works. This is very important to realize. Most games don't have good code architecture and it's fine. If it works, it works. But uh I have some suggestions. I have some things that I've learned and that I will try to do in my future projects and that I think will also save you a lot of time if you incorporate them. First of all, have reusable code modules. So, for example, if you have an object spawner, make it reusable to the point where you'll never have to write another object spawner for your project. you'll just keep reusing that one. And if you do this well, you'll end up with a bunch of isol
isolated systems. So you'll have a player movement system, a health system, enemy wave spawner, enemy movement system. And each of these systems is completely independent from all the other ones. It can be replaced, it can be reused, and it has low complexity because it is isolated isolated from the other systems. And then you just essentially use some glue to tie it all together. What What is this glue though? Do I mean, for example, if you have a health system and a movement system, um, the movement system just gets the health component and the health component just gets the movement component. So, they they both have references to each other and now they're glued together, right? No, no, no, no, no. This this is not what I mean. This is this is the bad way to do it. Cuz now they're no longer independent. Now you've tied them together. They can't be separated from one another. This is this is not good. You can connect uh them with no code in engines or you can use for example Unity events uh exposed fields etc. Or you can connect them with dedicated glue codes.
You you'll essentially write some script that you already know you're not going to reuse. It's just designed essentially to tie your various components together. So these could be game managers or system connectors or just dedicated scripts that connect your systems. For example, in our game Thronefall, we have this wonderful auto attack script. And this is reused everywhere in the project. Every object that can attack has this script, which is very nice and keeps it keeps it very clean, keeps it tidy. Um, like enemies have this script, your own units have this script, your buildings have the script, melee units have the script, range units have the script, everything that attacks just has the script. And then it makes it easy to make adjustments and changes. And we also have a bunch of glue. Like for example, here the local game state. This one is not meant to be reused or or whatever. It it's just there to tie various systems together. And we have a bunch of these. So the basically the way you can imagine this is you have a bunch of reusable
components. These are not just meant to be reused within your project, but they can also be reused in other projects. That's was like really cool about this is that you can sort of build a library of cool cool Lego bricks that you can reuse for other projects as well. And then you use a little bit of glue code or in engine connections to tie all of your systems together. Then you probably also need some game managers like some some bigger glue objects essentially that trigger all of your various systems. So 70% of your systems can be reusable bricks and 30% can be glue systems. If I had to guess, this is probably, if you do a good job, this is roughly uh the percentages you can end up with. And you can collect a bunch of cool Lego bricks and reuse them for future projects. Every time you make a new game, it should be faster because you already have more Lego bricks ready to go that you can just drop in and make your next game a lot faster. And also the nice thing about keeping your system systems
isolated and independent from each other without them referencing each other or anything like that is that you keep the complexity low. So this avoids spaghetti code. This makes your systems easier to manage to debug and so on. You always want to limit the spaghetti length like sticking to the spaghetti code reference. You do not want the spaghetti to go out of the plate. That is that is a mess. You want the spaghetti to stay in the plate. No, no, no, no, no, no spaghetti outside of the plate. Cuz if you do that, then your project will look like this. And uh like if all of the modules reference each other, it's just get turning into a complicated mess that's impossible to make sense of. What you want is you want the spaghetti of each module to stay in the module. You want the spaghetti to stay on the plates and then you can connect it uh with other means. But what if there are some systems that should be connected? For example, the health system and the attack system. And you're like, I don't know how to separate the
two. What the hell? They they need to reference each other. Yeah. So what? Just just make it one system. So some systems should just be one system. That is indeed correct. Um for example, health and attack system is a very good example. These should usually just go together. They should be one system. They're difficult to separate. Rule of thumb, write systems with the intent to reuse them in future projects, even if you don't. Cuz even if you don't reuse them in future projects, there's still a lot of advantage to writing them as if you would. You'll keep them more tidy. You'll keep them more modular. You'll keep them more independent. And even if you just use them for one project and then never use them again, it'll just make for cleaner modules. And then similar thing is true for your glue scripts. You don't want one very large monolith game manager that glues everything together. You don't want to use universal glue for everything. You never want to have too much spaghetti in one place. So, it makes more sense to break the game
manager up in a couple of smaller glue modules like maybe you have an enemy manager, building manager, day night manager. I also know some people are not a big fan of like game manager zingons in general. I personally kind of like them. Um, so how exactly you glue things together is up to you, but I I think usually you will need something something like like these game manager manager objects, like centralized data hubs that um glue all of your various systems together. I would recommend you break them up into small systems wherever possible. Makes it cleaner so that way all of the spaghetti is once again tidied up in one place. For example, in Thronefall, we have 30 game managers like this. And the reason for that is that they often times have very very small and specialized tasks. So, some of them are quite tiny. This is how you structure your code. You have reusable modules, you have a little bit of glue, but there's another aspect to
games, and that is all of the data, all of the gameplay data. And what I mean with data is mostly the immutable data. So like all of your balancing data, translations and so on and so forth. The mutable data like the positions of the objects, the speed of the objects um that lives somewhere over here in code. Sometimes it's not entirely possible to separate the two. But generally it's a very very good idea to keep them separate. You want to keep your code and your data as separate as possible. Here big wall. I I created a big wall. And then all of your code just basically reads from the database to run the game. An example for this that I think is easy to understand is uh translations. You never want to hardcode your text into the game like this because if you want to add translations later on, you'll have a big problem. Um it's a much better idea to put all of your text in a giant spreadsheet with all of the
different languages. And that way you can uh much more easily access all of the various translation data later on. Make sense? Exactly. So you should do this with all of your data. There's no reason to just do this with translations. You you do want to do this with pretty much all of your data. And just to be clear, it doesn't have to be spreadsheets. It can also be other data types. Like your database can also be made of scriptable objects. For example, there are equivalents to these in other game engines. Like I'm sure like I know God has its own version of these as well and so on. So you can essentially just create these very nice spreadsheet objects. They can also link to each other. You can create very very complex databases with these. These are absolutely fantastic for storing all of your games data. Prefabs are similar. They can also hold a lot of data. Um, just got to be careful that you don't do what we did with Thronfall cuz in Thronfall a lot of
the balancing data, for example, is spread out all over the place. We have some movement speed here. We have cooldown durations here. And this is actually quite annoying to work with. Like all of the data is sort of hidden in various random places. That's quite annoying. Not like this. You want to keep all the relevant data in one place. If it is game designed together, store it together. So this is uh much more about usability. Happy game designer is when all of the data is tidy and sorted and in one place. This game designer is very very happy. He's like, "Yay, I get to play with all of these cool numbers. I can make changes and additions quickly. Awesome." And there's an angry game designer. The angry game designer has to deal with all of your games data and balancing parameters and so on spread out all across your project. and whenever he wants to change something, he has to spend hours looking for it. This is very annoying. This is frustrating to work with. It slows you
down a lot. So, you want your data to be easy to work with. Duh. You want it to be easy to update. You want it to be easy to expand. You want it to e be easy to mod. This is also a big advantage of keeping your data organized and in one place is that uh modders have a much easier time adding new content to your game because the only thing they essentially have to do is to add new data often times and all makes your data easier to search. It's just more more pleasant to work with. Keep it all in one place. And this is so important to the point where I sometimes just design the database first. So I'm like I don't even have a game yet, but let's let's design the database. Let's design the data structure, everything I will need for my game and then I build the game systems on top. I really like this approach because it ensures that uh I will end up with a very very clean database that looks exactly the way I want it to look like and like nothing is left to chance here. This is very carefully designed with this workflow.
So if you design your code, you can almost look at it like this. You maybe design your data structures first. Then you build your little code modules on top. Like every little independent code module probably has its own data objects and data types that it requires. And then you build a bunch of glue on top. And that is more or less your game. There's one very long spaghetti that unfortunately you cannot avoid. And that spaghetti is time. Every system in your game needs to connect to this time spaghetti somehow. So every script is executed at a certain point in time. There's usually no way around this. And this can very quickly create a mess again. Um, what a mess. And that's why I recently became to appreciate just controlling the execution order of scripts very tightly. So, for example, I have one script that just individually calls all of the update events in exactly the order I want to call them. I know there are other ways you can control the execution order. Uh, I don't know. You just have
to find a way that works for you. doesn't really matter for small projects, but for complex projects, this is getting more and more important. I also don't really like events for that reason. For visuals, they're kind of fine, but for gameplay relevant stuff, I don't like my code being executed in random orders that I can't control easily. This is the default execution order of most game engines. Ugly, ugly, ugly. Um, you want to find a way to carefully thread the time spaghetti through your project. this. I don't know why it doesn't go through the glue um scripts here. Probably should. Uh I I drew that incorrectly, but you get the idea. You You want to control the time spaghetti for bigger projects. It's very very important. Separate gameplay and art. This is uh one of the more advanced techniques, but it's super powerful. It it cleans your project so so much. So, it's almost like you're designing two games in a way. You have the simulation and you have the few. The simulation is
just the bounding boxes that just the raw data of the game like just the raw game state that the game is currently in. You have like the objects uh and what's happening and so on. And then the few component is just rendering what's happening in the simulation. So the few is observing the simulation and showing it on screen. From the perspective of the few components, your simulation is essentially a real-time database that it just reads from. It's like, okay, I'll pull the current position of this object. I pull the current position of this object, and I'll render it all out for you. And from the perspective of the simulation, it's just like the few doesn't even exist. It's just the simulation doesn't care about anything else. It just cares about itself. Doesn't care about the view at all. So, you end up with almost these two separate projects within your projects. One is just the simulation, all of the gameplay logic, and one is rendering all of your game. Keeping track of time is usually very, very important for your simulation and not so
important for your view because this one is basically also only reading stuff from the simulation anyway. So time is typically not as important here for your simulation. You want to thread the time spaghetti carefully. And this architecture makes it so that you can easily replace one part or the other and also helps break down your modules into even smaller pieces. So there are no systems that do both game play and art. It's just like either a system is a gameplay system or it is an art visualization system. I think think keeping them separate is very very helpful and helps keep your stuff more tidy. And both of these have their own glue. They have their own data. for example, the data for visual systems are stuff like animations, meshes, and so on and so forth. And it's the same here. It makes a lot of sense to keep it tidy and to keep them in one place so that if you want to exchange the animation or the
mesh of something, you can just go into your database and quickly replace it. Tada. This is the best code architecture for indie games that I would recommend. Um, it's a I understand it's a bit of a more advanced architecture. So, if there's something else that works for you, don't worry about it. Remember, if it works, it works. Also, the main rule is just to stay organized, whatever that means for you. It also means a slightly different thing for every project. It really is really important to lean into what your project needs. It will take a few attempts to get right. you there there's nobody who can explain this to you in a way that will make you go ah now I get it. I can only kind of point you in the right direction and you will have to figure most of this out through your own experiments unfortunately. But I really hope this did point you in the right direction and if you want to watch another video then you should click here. YouTube really thinks you should watch this video right here. I I don't know why YouTube wants you to watch this. Um, but for some reason for for
some reason YouTube thinks you should watch this and we all know you should always always trust the YouTube algorithm. I hope you enjoyed and I'll see you in the next one.
Auto-generated captions from YouTube — names and numbers may be misheard.
Distilling the key insights…
Jonas Tyroller · 2025
Thomas Brush · 2026
Comments