Game Development Without "Manager" Classes

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
Accy
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 29
Joined: Tue Jan 28, 2014 11:10 am
Programming Language of Choice: C++
Location: USA

Game Development Without "Manager" Classes

Post by Accy »

I thought about titling this "Game Development Without Singletons" but these manager classes are not always singletons.

Basically, in any game source I've found, and even in game dev books, all code is written with tons of these manager classes: ResourceManager, DisplayManager, KeyboardManager, EnemyManager, ManagerManager, etc. I feel like this MUST be bad design; it just goes against every principle you learn as you're learning programming. Hell, most of the time these classes are just wrappers around global variables; the only difference being you need to add the overhead of function calls to use them. And if you look into it, people always tell you, in what I imagine as a snooty rich person's voice, "There's no need that I can think of for singletons~" but never give a fuckin' alternative.

Take ResourceManager for example. This one is probably the best example of this pattern working. Pseudocode would look like

Code: Select all

class ResourceManager
{
public:
    Texture* LoadTexture( std::string path );
private:
    Texture* PlayerTexture;
};
I'm not sure there is a good alternative for this type of thing, because it serves one very important purpose: it makes sure resources are only loaded once. If I were to give every renderable object it's own texture member, say for bullets in a bullet hell game, I could be loading the same resource thousands of times.

Keeping on the bullet hell example, in order to continually redraw bullets, I believe I would need some kind of BulletManager. Example:

Code: Select all

class BulletManager
{
public:
    BulletManager( ResourceManager& rm );
    void RenderAllBullets();
private:
    ResourceManager Resources;
};
Basically, I would need to iterate through every bullet on the screen and render it every frame. I can't think of an alternative, but I can at least take away the global access by giving each "shootable" class it's own BulletManager member, that only keeps track of bullets created by that class.
Also note that I passed in the resource manager via reference, which is basically how people recommend getting rid of global access. I can't imagine tossing these pointers around all over the place is very cache safe.

My question is basically: does anyone else have a different solution to keeping track of your entities or do you use manager classes?
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Game Development Without "Manager" Classes

Post by dandymcgee »

Disclaimer: I am not an expert. Strong opinions follow.

Fuck the "global variables are bad" bullshit. One of the main reasons I switched to C for my current project is to avoid wasting 90% of my time worrying about useless layer-upon-layer abstracts and encapsulation for the sake of encapsulation. Object-oriented design has its place, but don't overdo it. Not *everything* needs a wrapper class. Not *everything* needs to be perfectly encapsulated.

One of the main goals in doing these things is to centralize specific tasks (e.g. bulk load all textures into VRAM at the same time, allocate memory in large chunks, etc.) In certain cases streaming is better (infinite, procedural worlds), but most of the time you want to manage each type of resource in one place.

Another goal is to keep inter-dependencies to an absolute minimum. When things start having strong, direction relationships you end up with impossible to maintain spaghetti code, cyclic dependency graphs, impossible refactors, etc. Managers keep things centralized, and distinct. They should define a logical interface through which other systems can makes requests, but don't worry about strictly enforcing these interfaces in your code. Unless you're working with a team of complete idiots, a logical interface and some reasonable coding guidelines will solve all of the *real* problems. Let the theorists solve the imaginary problems like perfect encapsulation.

As far as passing pointers around all over the place, rather than passing a pointer to the "TextureManager" to the "Starship" class's "Render" function, and having the Starship render itself, it's way more logical to have the StarShip store the GUID of the texture(s) belonging to it, and let the TextureManager do the rest. When the game loops gets to texture rendering, it will update / render *all* of the textures at the same time in a bulk update. It can do the z-sorting, occlusion, etc. without having a care in the world about who the texture belongs to, and the Starship can worry about the "business logic" of being a Starship rather than the internal details of texture rendering system.

As a final note, I'll just leave this here: "Game Engine Architecture" by Jason Gregory, who was the Lead Programmer on Naughty Dog's "The Last Of Us". I own it, I've read almost all of it, and it's a *fantastic* reference guide with just enough information to get you think and give you the keywords and concepts you need to do further research on whichever topics suit your fancy. https://www.amazon.com/Game-Engine-Arch ... 1568814135

P.S. Great question. Hit me up on Discord if you ever wanna chat about this stuff. I'm sure I could learn just as much from you.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
lelandbdean
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 18
Joined: Thu Mar 28, 2013 10:37 pm
Favorite Gaming Platforms: PC, Gameboy, PSP, SNES, NES
Programming Language of Choice: C/++ usually

Re: Game Development Without "Manager" Classes

Post by lelandbdean »

Fuck the "global variables are bad" bullshit.
This.

Video games are real-time applications. Performance matters.
Simplicity is King.

No matter what kind of design paradigm you espouse, your game will run procedurally, because that's how the hardware works.
A lot of "recommended practices" in object-oriented languages boil down to "theoretically blahblah and this code is elegant".

I would recommend learning about cache-coherency and data-oriented-design. It is less important that your code is "elegant" and more
important that your game runs at a smooth framerate. That said, design does matter. You don't want singleton-encrusted spaghetti.
The easiest way to keep your global state clean is to keep it global. "static" is better than wrapping everything under
the sun in some God-awful piece of shit wrapper class in some needlessly complex hierarchy with a vtable and a pile of getters/setters
(another shit habit). Programming is not that complex.

Regardless of what language(s) you like best, I would recommend writing a lot of C code. It forces you to understand how things work
and it forces you to get better at programming by discovering which paradigms and patterns work for you and your problems
(because they are almost completely optional, not something you're forced to work beneath).

Recommended reading/listening:
http://www.agner.org/optimize/blog/read.php?i=417
https://www.youtube.com/watch?v=rX0ItVEVjHc
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Game Development Without "Manager" Classes

Post by dandymcgee »

lelandbdean wrote:I would recommend learning about cache-coherency and data-oriented-design.
.. and this.
I feel like I've read that article before a while ago, but it is still great. As far as the video, I absolutely love Mike Acton. He is an incredibly intelligent man and a fantastic speaker.

Edit: At 30:00 in Mike Acton's talk, he brings up a reference image on memory caching which was taken from Jason Gregory's book I recommended in my post. It's a small world. ;)
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
Accy
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 29
Joined: Tue Jan 28, 2014 11:10 am
Programming Language of Choice: C++
Location: USA

Re: Game Development Without "Manager" Classes

Post by Accy »

dandymcgee wrote:P.S. Great question. Hit me up on Discord if you ever wanna chat about this stuff. I'm sure I could learn just as much from you.
Sorry about the wait, my computer had a bit of a problem when Windows ate my hard drive. Guess I gave it too much credit to think I could dualboot with it. My Discord tag is AcceleratingUniverse.
I wouldn't give me too much credit though, I'm not too good :lol:
lelandbdean wrote:I would recommend learning about cache-coherency and data-oriented-design.
I actually spent most of my last semester researching dod, and I came to the conclusion that it's too fucking hard. :mrgreen:
To write and design an actual program with everything contiguous in memory and accessible to the cache is really quite a task. I think a lot of people believe that dod means "use vectors instead of classes" when in all honesty it seems to mean "use one big ass vector and nothing else"

I also have this somewhat irrational fear that I'll post my super-optimized game code on my github and potential employers eternally stuck in 1993 will look at and think "look at this fucking retard! he's not even using multiple inheritance to derive car from wheeled-vehicle!!"
User avatar
dandymcgee
ES Beta Backer
ES Beta Backer
Posts: 4709
Joined: Tue Apr 29, 2008 3:24 pm
Current Project: https://github.com/dbechrd/RicoTech
Favorite Gaming Platforms: NES, Sega Genesis, PS2, PC
Programming Language of Choice: C
Location: San Francisco
Contact:

Re: Game Development Without "Manager" Classes

Post by dandymcgee »

Accy wrote:
lelandbdean wrote:I would recommend learning about cache-coherency and data-oriented-design.
I actually spent most of my last semester researching dod, and I came to the conclusion that it's too fucking hard. :mrgreen:
To write and design an actual program with everything contiguous in memory and accessible to the cache is really quite a task. I think a lot of people believe that dod means "use vectors instead of classes" when in all honesty it seems to mean "use one big ass vector and nothing else"
Not at all. It's not about perfect caching, it's about weighing the trade-offs. Achieving local cache coherency in the context of a particular subsystem is much better than throwing it out the window because making your entire memory block one contiguous chunk is "too fucking hard". Everything in programming is a trade-off. Only with experience will you be able to perfectly balance them all to achieve the best results.
Accy wrote: I also have this somewhat irrational fear that I'll post my super-optimized game code on my github and potential employers eternally stuck in 1993 will look at and think "look at this fucking retard! he's not even using multiple inheritance to derive car from wheeled-vehicle!!"
Irrational indeed. Maybe this will help: any potential employer who thinks code which focuses on cache-coherency or data-oriented design is "stuck in 1993" is no potential employer of mine. Nor should they be a potential employer of yours. Always remember that the employee is the valuable asset, not the employer. The employer should be convincing *you* why you should come to work for *him*, not vice versa. The more experienced you are, the more this is true (everyone is a "I'll take what I can get" employee in the beginning, you have to start somewhere). Taking a job to pay the bills is one thing, but don't stay there for 10 years just because it pays the bills. You have to be constantly challenging yourself if you ever want to grow as a programmer, and as a person.
Falco Girgis wrote:It is imperative that I can broadcast my narcissistic commit strings to the Twitter! Tweet Tweet, bitches! :twisted:
User avatar
Arce
Jealous Self-Righteous Prick
Jealous Self-Righteous Prick
Posts: 2153
Joined: Mon Jul 10, 2006 9:29 pm

Re: Game Development Without "Manager" Classes

Post by Arce »

<qpHalcy0n> decided to paint the office, now i'm high and my hands hurt
User avatar
Falco Girgis
Elysian Shadows Team
Elysian Shadows Team
Posts: 10294
Joined: Thu May 20, 2004 2:04 pm
Current Project: Elysian Shadows
Favorite Gaming Platforms: Dreamcast, SNES, NES
Programming Language of Choice: C/++
Location: Studio Vorbis, AL
Contact:

Re: Game Development Without "Manager" Classes

Post by Falco Girgis »

Eeeeeeh... I actually am going to have to agree to globals being bad in C++, but not for the reasons most people do. Honestly, you have a MILLION different alternatives to handling them within the language and yet you are choosing the most ugly, primitive solution possible? Jesus, at very least make them a public static member of a class.

In C, obviously they are a way of life, although I do tend to use them sparingly. Within C, it's usually only TRANSLATION UNIT scoping that you are really looking for. You want all functions within the file to have access to the data, but not random functions fuck-knows-where in other translation units. Always declare those variables "static" globals.

As for manager classes, yes, absolutely game development does use a shitload of them, and for a pretty good reason. I have all kinds of "Manager" classes within our engine, and most engines and even software in general tends to have something similar to maintain objects.
Accy wrote:I actually spent most of my last semester researching dod, and I came to the conclusion that it's too fucking hard. :mrgreen:
To write and design an actual program with everything contiguous in memory and accessible to the cache is really quite a task. I think a lot of people believe that dod means "use vectors instead of classes" when in all honesty it seems to mean "use one big ass vector and nothing else"
Actually, it's not that hard. I'm doing it in ES, and that's how I'm getting rid of a shitload of different "manager" classes.

It's a technique I like to call "data centrality" where rather than the data within software being dispersed fuck-knows-where within different subsystems such as CollisionManager, WarpManager, TileManager, AIManager, etc, they are all stored within a single structure:

Code: Select all

class Area {
    elysian::Pool<Entity> entities;
    elysian::Pool<Renderable> renderables;
    elysian::Pool<RigidBody> rigidBodies;
    elysian::Pool<Warp> warps;
    //etc;
};
Then there is a single pointer "Area* curArea" that everything is accessing to manipulate the data it needs. There are actually quite a few strengths in this design:
  • Cache Coherency - as you can see, everything is stored contiguously and nearby
  • Easy Loading/Saving - all data for loading and saving is located within a single structure
  • Easy swapping - With the manager paradigm, to "swap" areas, you essentially have to call some kind of "unload" function for each manager to clear the old area then call a "load" to load the new data. With this paradigm, you literally set "curArea" to point to another area, and BOOM, you just changed fucking areas.
  • Supporting multiple loaded Areas/Assets - With the manager system, you're going to have a hell of a time storing in RAM the separate contents of multiple areas at once. With this paradigm, you simply have multiple Area objects allocated at once and can simply change the pointer between them... So in ES we can cache nearby/previous areas (on non-Dreamcast platforms), and in ESTk this paradigm really paid off, because you can have a SHITLOAD of different areas/levels open at once, and can simply swap between them when editing.
Post Reply