Jump to content
  • Advertisement
Sign in to follow this  
BiiXteR

Problems With Game Engine Architecture

This topic is 613 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

As the title says I'm having a lot of problems with the architecture of my game engine.

Every time I write a game engine all different components (Graphics, Audio, Input) get really messy.

Input needs to have access to Graphics in case for example the player shoots, and the Graphics might need access to Audio because clicking a button should play a audio file, and so on.

 

I can't find a good way to do this without everything looking like spaghetti.

 

I've considered these things, but I don't know if any of them are actually good ways to do it : 

 

  • Making every single component of the engine global, and putting them in a globals.h.
  • Event/Messeging system (this one seems pretty good but I can't wrap my head around on how to implement it)
  • Declaring pointers to components in each class that needs it.
  • Passing the components to each function that uses it (I dislike this one since if a function needs several of the components it looks really messy)

 

Basically I want my engine parts (Graphics, Audio, Input, GUI, MapManagers, Debugging Classes and so on) to be able to access eachother without having to create a sphagetti mess everywhere.

Share this post


Link to post
Share on other sites
Advertisement

Maybe a bit to obvious, but there's good book on this calles exactly "Game engine architecture". It's a good guideline for exactly what you're doing (currently I'm at chapter 4 :))

Edited by cozzie

Share this post


Link to post
Share on other sites

 

Input needs to have access to Graphics in case for example the player shoots, and the Graphics might need access to Audio because clicking a button should play a audio file, and so on.


My suggestion to handle this is to extract the "game logic" into its own systems and have it communicate with the other systems. "Platform-level" components like input, graphics, and audio should never need to know about one another. Instead, try this:
- when the player shoots, input notifies the game system that the player has shot
- the game system takes care of telling the graphics system to spawn particles (the graphics system shouldn't know what "bullets" are - only things related to rendering)
- UI should not be in the graphics layer - UI should be in its own system that takes input and tells the graphics and audio layers what to do
 
As much as possible, you want dependencies to flow in one direction. Either platform components should not need to know about gameplay components at all, or gameplay components should not need to know about platform components at all. Platform components definitely shouldn't need to know about each other.

Passing the components to each function that uses it (I dislike this one since if a function needs several of the components it looks really messy)


This is my preferred option, most of the time. It may look messy, but it also lets you see exactly which function of each component depends on which other component. That's something that can come in handy when refactoring. If your dependencies are explicit, and they look messy, that's probably because they are messy. If your dependencies are implicit, they might look less messy, but that doesn't take the mess away.

 

 

I checked out the source on CryEngine, they seem to use static objects for all their managers, considering they're using it I assume it's not that bad?

I really, really dislike the looks of sending them in to every function though. I'll probably only do that if I have no other options tbh.

 

 

Maybe a bit to obvious, but there's good book on this calles exactly "Game engine architecture". It's a good guideline for exactly what you're doing (currently I'm at chapter 4 :))

 

I'll check that out. :)

Share this post


Link to post
Share on other sites

Input should never have access to graphics. This doesn't make much sense to be honest.

This is where you come to abstraction layers. Abstraction layers will prevent things from spiraling down into insanity as long as you keep abstractions going in one direction.

 

For example

Input -> Logic -> World -> Representation.

Your input should only influence the logic. Where the logic influences the world. And the world influences the representation. To make things simple.

Your world consists of models and sounds. And your representation consists of how things needs to be rendered.

Between those, you'll have data that is goes back and forth between one another. Or goes in just one single direction.

Share this post


Link to post
Share on other sites

A few things I do:

 

- I use globals for all my managers.  There are a few, but I also cluster some of the sub managers into a manager for that area. EG - Special effects manager, has explosions, particles, etc...all the fluff.  I do have a static and dynamic entity manager which should be managed together also. BUT 

- General rules you make for yourself.  Mine, don't call a manager from an entity in another manager.  That's my rule, so it means that the entity has to have strong status controls in it.  For example, if my bullet hits something, I set a status on what it hit (material).  My manager orchestrates call from the top level.  it means I dont have to follow into entities all the extra game logic.

- If you think something is complicated in your mind, then comment it in your code.  You come back 2 weeks later and go WTF.

- Don't be afraid to start with creating too many managers (yes, its bad practice though), you will soon realise patterns in your code and refactor.  Experience will play a part.

 

As mentioned before, major game engines have some pretty bad code in them.  Read Unreal has some epic classes in its engine, making it hard to pick up and learn.

 

And reading books is good also, its old fashioned, but works 

Share this post


Link to post
Share on other sites

Input needs to have access to Graphics in case for example the player shoots, and the Graphics might need access to Audio because clicking a button should play a audio file, and so on.

 

What if I want to make an ASCII-based game that has no audio?  What if I want to create a networked game where an input also needs to be sent across the internet?

 

Write the engine as engine, keeping the components completely separate from each other.  Then write another layer, your game, on top of those that connect things together.

Share this post


Link to post
Share on other sites

- I use globals for all my managers.  

 

Heheh. I remember when I made that exact statement about my game project almost 5 years ago. I also remember 6 months ago when I suddenly realised why it was a bad idea and spent a few months refactoring everything to remove all globals.

 

Globals are seductive because they are easy to use and let you share information between different objects very easily. But you eventually end up in dependency hell, where to test a small system you need to recreate the entire game state, since object A references systems B and C, and they rely on D and E and F.. etc

 

The best thing about the mindset of passing dependencies instead of referencing them through globals, is that poor design stands out like a sore thumb.

Share this post


Link to post
Share on other sites

 

- I use globals for all my managers.  

 

Heheh. I remember when I made that exact statement about my game project almost 5 years ago. I also remember 6 months ago when I suddenly realised why it was a bad idea and spent a few months refactoring everything to remove all globals.

 

Globals are seductive because they are easy to use and let you share information between different objects very easily. But you eventually end up in dependency hell, where to test a small system you need to recreate the entire game state, since object A references systems B and C, and they rely on D and E and F.. etc

 

The best thing about the mindset of passing dependencies instead of referencing them through globals, is that poor design stands out like a sore thumb.

 

I do have globals, but I dont sprinkle them much throughout my code.  The point is to use the conservatively.  At the end of the day, my managers only accessed through say a core render functions.  I enforce that game entities themselves don't jump in and out of Globals.  Creates spaghetti code.  Its just down to discipline.

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!