Autoloads vs Composition

Godot Version

4.3

Question

I’m working on a more bigger Godot project, that means that the code base needs to be scaleable, flexible, cohesive and loosely coupled.

Of course, I have implemented a solution to play sound effects, transition music, with an SoundManager autoload.

However, now looking into the composition design pattern, I think following would be a better approach:

image

-Add the SoundPlayer3D to every scene you need a sound to be played.
-Then in order to play a sound, I would use signals, passing in the .wav file that needs to be played

Which approach is better? I find the 2. more scaleable for larger projects. I am so confused by all of the people saying to not use singletons. Need some advice here.

How about you create a flexible Sound Entity that you spawn into the object when needed? Once the sound was played, it will clean itself up and remove itself.

Imaging an AudioManager.gd autoload that has a library of sounds. Any object can access the AudioManager and requests a sound and give an audio channel (Master, BGM, SFX, Ambience, etc) as input. The AudioManager then spawns the corresponding AudioPlayer and returns it to the object. You can create a custom Audioplayer that is capable of queue_free() once the sound is played.

You can also do as you described and create an Audio Component that you add to every object that needs it. In their _ready() method, they can then initialize the audio component by adding the appropriate audioPlayer + soundfile + sound channel via code.

Singletons / Autoloads are supposed to load at the start of the game and stay forever in your SceneTree. As long as they don’t actively process things via _process() method, they don’t impact performance at all. Autoloads are great and convenient.

1 Like

If I understand the question correctly, the SoundManager will be able to manage the number and position of SoundPlayer3D, as well as its interaction with music.

People often say “You’re optimizing prematurely” and “Don’t solve that problem yet,” but I tend to disagree almost every time I hear it. Designing systems like this late in the project ranges from difficult to impossible because of the structural changes. But designing it at the beginning is easy enough.

I would very much lean into the Autoload approach. These two methods have big difference in how scalable they are, depending on how they are implemented.

1 Like

Just do what you think is best, some people want to push out quick prototypes and vertical slices that is build around functionality without regard to future expansion and flexibility. There are many ways to implement a feature and it should fit to the kind of project you aspire for it to become.

The curse of amateur gamedev is trying to overoptimize on the first try and spending too much time thinking about the implementation instead of the feature itself. Some people also fall victim to only watch guides and then parroting opinions of others instead of just trying out and see by experience.

I like Autoloads and I am biased towards its use but just do what you think is right. If the decision didn’t feel right, it’s also possible to refactor.

2 Likes

I agree entirely. @marshmallow_dev indicated that they aspire to create a “bigger project,” and I do think that setting up a good design pattern at the start is worth it for a longer term thing such as this.

1 Like

I’m not sure how I should feel about autoloads being a standard option in Godot. I see scaleability problems here. It seems to be like Godot is designed to be a “prototype engine”. As a beginner you might think “autoloads are so convenient and easy!”. But I think it kinda contradicts itself, because Godot is built around the composition pattern, but then it also encourages the use of singletons? I don’t understand it.

If you ask me, Godot provides a lot of flexibility that other engines also provide. The statement about Godot being built around composition patterns can also be said about class inheritance and ease of creation of custom classes and custom resources.

In my two years of Godot experience, I haven’t heard of or used Composition yet and I engineered my code around code inheritance like I’ve been taught to in school. Therefore I cannot give my opinion on that topic but I’ve regarded Singletons, Composition, Inheritance, Database Injections, etc as mere tools that Godot provides without being built or being dependent around it.

Maybe someone with more experience with the coding practices can provide a more qualified opinion.

1 Like

I don’t see a problem at all with singletons, specifically as they are implemented in Godot. That’s because that an Autoload is just an engine feature to attach a Node to the root. Don’t forget that you, yourself, can attach one to the root yourself, and detach them again freely. Therefore, if you need a globally-available manager of some sort, you can always do that, and detach it when the scene changes. Need a different kind of sound manager? Swap GameSoundManager with HeadlessSoundManager or SaveToFileSoundManager, or…

This is the point I’d like to make clear: I understand that you imagine a “bigger game project” but at a certain point, you have to accept that you can’t plan for all eventualities. You just can’t. If your question hasn’t yet been answered by the discussion in this thread, your best choice is to cannonball into the path of least likely trouble, and fix it later, if that point arises.

Your whole game is expected to have sound, correct? What are the alternatives? It adds a name to the global scope. Just creating a class adds a name to the global scope. GDScript has no namespaces that I’m aware of.

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.