2
\$\begingroup\$

I'm working on a small, data-driven game engine with some friends.

We use GameObjects (a.k.a. Entities, Actors, or whatever it is called in your favorite engine) to represent every entity in the game. These GameObjects owns Components, who communicates via message passing. This is a very well-known pattern, and although implementations differ greatly, it seems to be what every commercial, modern game engine is doing.

Now we have one problem: managing state. Let's say we are creating some kind of platform game. The hero of this game should be able to stand still, jump, attack...

We created some Finite State Machines to hold the player's state. Now the state should, in turn, be consumed by the other components. Running should trigger an animation and modify the player's velocity, attacking should stop the player and spawn a bullet...

But this creates a lot of dependencies. The Sprite component now has to be aware of the State component, and listen to state changes. The Movable component should listen to state changes too, to be able to change the player's speed. Nearly every component depends on the State component. This sounds like a dependency hell.

I think it's a very common problem, but I can't find a good solution for it. Are there some design patterns for situations like this?

\$\endgroup\$
  • \$\begingroup\$ Components hold data (state is data). Systems process components (which contain data/state). You are already implementing the pattern that handles this "problem". \$\endgroup\$ – Cypher Jul 6 '15 at 18:43
4
\$\begingroup\$

It's OK to have component dependencies. And the more explicit the dependency the better. There's nothing worse than dependencies hidden behind useless layers of indirections.

Your case doesn't look like a dependency hell to me. No circular dependency or unclear ownership of data: consider yourself lucky!

Now I still believe that you need to reverse your thinking a bit. Instead of having your Movable, Sprite, VFX etc. components reading the player's State, you should probably have the State request changes on the others. E.g. by posting messages (I want a speed of Xm/s, I want a running animation, and also some dust smoke, kthxbye), or via direct functions calls. The player controller is often the client of various subsystems, not the other way around.

\$\endgroup\$
  • \$\begingroup\$ +1 for the "reverse your thinking". I also think the better approach is the State object orchestrate its stuff. In my game each State has a Initialize, Update and Finalize methods and it is in them where I play sound, spawn objects, set physics etc. \$\endgroup\$ – Emir Lima Jul 7 '15 at 12:19
  • \$\begingroup\$ While I am no master in these things, that's the approach I'd take. Basically multiple basic components (collision, sound, rendering, whatever) tied together by a "parent" object. The parent object then tells the child components what to do. \$\endgroup\$ – Tara Jul 7 '15 at 17:25
3
\$\begingroup\$

In my experiences there aren't too many ways around the fact that, you're right, all your different game entities and their components need to be aware of the state of the game and their own state. It's a mess unless you design with state machines in mind.

The best way I've found to deal with it is to make sure that components are all doing small pieces of work and working together. Don't let components get out of control and handling all sorts of things that could be handled by separate components. Let the Sprite component just load images, check the Player's state and update with the right image. If you need Animation scrap the Sprite managing anything other than loading and Drawing and let the Animation query the Player's state and tell the sprite to play back certain images at a certain speed. This is a rough example but I think it highlights how to deal with components working together in one object.

Another practice that helps is having a GameManager entity that has a series of scripts for managing the game state of the scene. You don't necessarily want the GameManager to control much game logic as that should mostly be up to the components but it should act as a wingman for all of the components to let them know about the state of the game as a whole. Don't be afraid to have static data either. It's not awful to call something like Enemy.GetEnemies() or GameManager.GetState()

It's a good idea to check out some projects written in Unity or another engine to see how they're organized. I know you're dealing with the Engine not just the Game but I can link you to some projects of mine that I think are fairly well organized.

A game written in my engine: https://github.com/FlannelViolin/Checkers

A game written in Unity (links directly to scripts): https://github.com/Honeybunch/Ebolinator2014/tree/master/Assets/EbolinatorScripts

Polymorphism and Dependencies are your friends; very powerful friends. Design with them, not against them.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.