Take the 2-minute tour ×
Game Development Stack Exchange is a question and answer site for professional and independent game developers. It's 100% free, no registration required.

Assuming the underlying low level audio logic is encapsulated in some outside class... what is the best way to add audio effects to a component-based entity framework?

I am taking the approach that entities are just IDs and a type of database is used to associate components with entity IDs. The I can create masks for the systems to query particular types from the database.

So for example for components I might have:

  • PositionComponent.
  • PhysicsComponent.
  • VisualComponent.

And the corresponding systems:

  • VisualSystem, which processes visual components, hands off to outside renderer.
  • PhysicsSystem, which processes physics, updates position vectors.

So the question is, how best to add audio to this system... or should I even bother? The problem I am having is mapping sounds to actions and when to play sounds.

Here are some approaches I've thought of::

  1. Force PhysicsComponents to have a some collision sound field and when a collision occurs, play the sound within the physics system.

  2. Same as 1 but instead when a collision is detected add a SoundComponent(sound) to the entity and lets the SoundSystem see that and consume it (so the sound plays once for example). This still means PhysicsComponent would have a sound field. So really this just shifts the playing of audio into a system.

I don't like either of those approaches. They are not very suitable to expanding the game either. Now I would need a field for every possible sound a unit could generate.

Really I think individual entities should dictate which sound to play based on some component attached to them I would assume. The question then becomes how to know when to play that sound.

Sorry if this is all very vague. Any tips appreciated.

share|improve this question

1 Answer 1

up vote 3 down vote accepted

You are teetering on the brink of the pit that is "putting everything in the entity system." Not everything needs to be a component, and indeed, many things should not be.

You should strive for separation of concerns where possible: a physics system should not know about the sound system at all. This includes avoiding a "sound to play on collision" field for objects.

Instead, build your physics system such that it exposes callbacks for collisions; a callback can be as simple as a function that has references to the two colliding rigid bodies to as complex as you need.

There is a system in your game that knows about both physics and sound: the "game" class itself, the thing that holds both the "sound system" and the "physics system." Have this game class wire up callbacks from the physics into the game logic, which can understand what sounds to play when two things collide, and play them. Since the game already knows about both systems out of necessity, you introduce no additional coupling. This works perfectly fine in an entity/component system because physics components typically correspond to rigid bodies.

If you need to put SoundComponents in your game, use them for things like controlling whether the entity plays a periodic sound or emits an audio effect (like local sound damping).

Most of the time, component-based entity systems work best when paired with some form of scripting language or other way to drive behavior without recompilation of code. If you have such a thing, I'd recommend giving your "script components" access to at least of subset of the audio API, so that they can request that sounds be played when they determine it's warranted (for example: a script component representing enemy AI that "detects" a player may want to issue a warning growl).

Generally, I find that sounds work best when they are just a service that appropriate components or other systems can access as needed. There's room for things like SoundComponent for limited, simple use cases (like periodic sounds, as mentioned). But if you try to shoehorn all sound activity into components I've found that you often end up with a complex mess of components that's hard to balance for good audio mixing.

Also remember: an entity system is a high level concept. It's higher level than sound or physics, so the components should usually be built on top of the underlaying system and not the other way around (by which I mean it should be theoretically possible to use your physics or audio system without components if you wanted to).

share|improve this answer
    
Excellent answer, thanks. I agree with everything you have mentioned. I'd like to mark this as an answer but it still leaves one question open. Going with the approach of a collision callback into game. How does this callback know which sound to play? The physics system doesn't care the type of game object it is processing, it is just concerned about collision shapes and adjusting vectors. So now in my callback I know two entities collided and their id but nothing more. Lets say each entity has a different collision sound to play, where do you introduce this field? –  Halsafar Mar 8 at 20:43
    
The typical approach is to correlate the physics objects from the callback with their entities, and from there you can get the components or any other data you need to figure out, for those two bodies, what the interaction/collision sound should be. –  Josh Petrie Mar 8 at 20:47

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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