Skip to main content
  1. Quick Notes & Explanations/

5. Choosing the Appropriate Architecture

·4 mins· loading · loading ·
Table of Contents

After the reminders about optimization in the first three sections, we can bring together the principles from the fourth section to develop an architecture that can be applied to our project. Considering that randomly chosen architectures can negatively impact their interactions with each other, we can select an architecture based on principles that are widely used and accepted in the gaming industry. We should focus on making our choices based on the constraints we mentioned initially, not on the complexity of the code or architecture.

Let’s review the topics discussed in our meetings, along with their advantages and disadvantages, in light of what we have learned so far.

Singleton

Singleton is not an architecture in itself; it is one of the principles that can be applied within software architecture. This means that along with Singleton, we can also use principles like Object Pool, Interface Segregation, etc., which we often do. It wouldn’t be correct or objective to classify principles as good or bad. Our only requirement is that it doesn’t violate the constraints that concern us or our project.

If we evaluate the approach within the architecture:

For projects with simple mechanics and small teams, including the Singleton principle in our architecture is a logical approach. It facilitates communication between our objects through static instances without needing any access-reference requirements. It can make our code simpler and cleaner compared to a structure without any architecture. Typically, we use Singletons for scripts like Manager or Controller because using them for each object would create a problem of uniqueness and occupy a significant and unnecessary amount of memory. However, there is a fundamental problem with Singletons: single and unique references.

For example, let’s assume we have a script called CharacterController. In a simple project, having a CharacterController Singleton in our scene would be advantageous in many ways. But let’s imagine a scenario where there are not just one but 10 different instances of CharacterController in the scene. This could be in a multiplayer setup (and if it is, creating Singletons at runtime would completely take away our control over memory). It is not possible to use multiple Singletons of the same object type.

For large and scalable projects, Singletons are not favorable in this regard. They create all sorts of dependencies. Additionally, they cause errors that are hard to diagnose because anything can enter your Singleton object (as a reference interaction).

Dependency Injection

💡 There is no principle called Dependency Injection, nor is it an architecture. Dependency Injection and Dependency Inversion are not the same things either. Injection is a method that facilitates the distribution of object references and allows us to apply the inversion principle based on IoC.

It allows us to distribute CharacterControllers with multiple instances across various classes without static allocations, which we discussed in the Singleton section. In other words, every Singleton is essentially a dependency injection; not every DI (Dependency Injection) is a Singleton.

One of the major advantages that DI provides for us and our constraint is that it frees us from the obligation to hold static references. This ensures that there won’t be scenarios where the Garbage Collector is disabled, our game won’t consume unnecessary memory, and we can easily distribute multiple similar instances within our project.

It’s worth reiterating: Singleton is not an architecture! Dependency Injection is neither of these; it’s merely a solution or an approach at best.

Now that I think I’ve cleared up this confusion, I’d like to return to our architectural choices.

Example Games and Their Architectures

First, I’d like to mention a studio that creates network-based games in the Casual genre: GDCompany. The studio has dozens of different types of games in this area, and in the Assemblies of a few games I reverse-engineered, I saw that they applied the SOLID principles. You can easily find the projects of their reverse-engineered games on Google.

You can see Zenject directly in the source codes of the above games. Since it’s a Russian-based company, I even think that the Zenject development team might be this company.

Another game that perhaps everyone knows, with over 500 million downloads, is Sniper 3D.

Here, Victor, a member of the game’s development team, wrote an article on his Medium account about how they developed this game based on SOLID principles:

In fact, I reviewed the source codes of dozens of games in a few hours; almost all major games used architectures similar to SOLID. Aside from SOLID, the GRASP architecture is also famous but not as popular as SOLID. I couldn’t find a project example for this architecture.

If we pay attention here, the richness of libraries and plugins that popular architectures offer us also stands out. Zenject is a framework that almost everyone has heard of as a system based on SOLID principles and allows us to develop projects in this direction.

From this point on, I will continue with an explanation based on the SOLID principles.

Reply by Email

Related

4. Design Pattern Examples
·10 mins· loading · loading
We can categorize Design Patterns under 3 main headings: Architectural Patterns Examples: MVC (Model-View-Controller), SOLID, MVVM… Design Patterns It is a specific Architectural Pattern, such as Singleton. Using it alone in a project is not sufficient, and optimization with several different patterns is necessary.
3. Why should we use architecture?
·3 mins· loading · loading
One of the fundamental advantages of working with principles and architectures in our projects is that it allows us to benefit from the advantages of libraries and plugins developed specifically for those principles.
2. GC Alloc ve GC Collect
·2 mins· loading · loading
In C# and some Object-Oriented Programming languages, there is the term Garbage Collector. However, in some mid-level programming languages, it is the programmer’s responsibility to remove objects that are no longer needed from memory.
1. Theory of Constraints & Games
·1 min· loading · loading
Theory of Constraints suggests that every production system has a single constraint that limits the producer from unlimited production, and the goal of the system is to continuously maximize the efficiency of that constraint.
Beat Them All
·1 min· loading · loading
The game offers a strategic experience where players merge houses to create powerful armies, sending them out to defeat their enemies in a visually engaging 3D environment. “Beat Them All 3D” challenges players to think strategically as they merge houses on the battlefield.
Vending Master
·1 min· loading · loading
In this game, you take on the role of a vending master, managing and operating a vending machine to serve customers. The game provides a fun twist on the everyday operation of vending machines by showing the little people working inside to keep things running smoothly.