Skip to main content
gamedev.net
🔒 Locked

How to structure the 'engine' of the game.

Started by JoshuaWaring 7 replies 1.9k views
Original Post
JoshuaWaring
JoshuaWaring

I've been thinking about methods of maintaining objects in a game. Currently I'm thinking of using a Manager for each system, Physics, AI and Graphics. Each are independent of each other and cutting out the Physic's part won't break the game, just cause things not to fall by gravity. How would someone recommend going about doing things like this? I've been thinking about it for a while, but can't come up with a feasible method.

Below are the reasons why how I'm thinking of having it work will not work.

This is my problem though, because I'm trying to have the data stored in RAM sequentially, so instead of storing a structure containing the position and velocity next to each other in ram. have all positions so be placed next to each other in ram and all velocities to be stored next to each other. Nice large chunks. This brings up my problem of What if you remove a entity? There's now a unused space inside the chunk of memory. I don't want to use any if statements to check if the ram is used or unused and skip over that block, because this would cause a stall in the CPU, one stall on every entity adds up.

Another issue would be what if an entity isn't affected by Physics or doesn't have any Positions, would I just leave the memory blank? but this would cause the same issue as before. The only real solution I can fabricate is having a another chunk of Bitfeilds to tell each system about the entity and what it actually contains. I can see it working, but that will still use a if statement to check if each entity will run it's stuff.

Waterlimon
Waterlimon

I have each entity contain a handle to each component it needs. Thus the components of an entity are stored in different indices. Only store the components in the same index in the same place if they belong together (that is, only use an object of arrays if you can use an array of objects)

For example,

Entity

{

Position //Object of arrays, each has same index for given entity

Rotation

Velocity //Different object of arrays, each has same index for given entity but different from above

Force

RotVelocity

CollisionBody //Array, index different from others

Visuals //Same as above

}

So:

Entity

{

LocationHandle->{

Position

Rotation

}

PhysicsBodyHandle->

{

Velocity

Force

RotVelocity

}

CollisionBodyHandle

VisualsHandle

}

Basically if you expect a component to not exist together with another component, you should think wether to bundle it with other components (leave a blank space) or to separate it from a performance and memory point of view.

You could also have the ID of the entity be mapped to a component ID in each of your systems, but that would probably turn out to be very slow.

o3o
HappyCoder
HappyCoder
What has worked well for me in the past is to have each module separately coded like you have described above, then have a class that binds them all together. The binding class would depend on all of the sub modules but each sub module should have no knowledge of the binding class. If any information needs to be passed up to the binding class use delegates or have the binding class poll the sub module for information. So it would look something like this



class Entity
{
    // handles the collision detection and collision response
    private PhysicsObject physics;
    // handle drawing the entity
    private SceneNode sprite; 
    // handles playing sounds from this entity
    private SoundSource soundSource
    // ect...
}

Once you have this working be sure that the physics system doesn't depend on the graphics nor the graphics on the physics. Instead they are completely independent from each other.

An example of how I used this in a game I made recently. The sound my character made when he took a step changed depending on what surface he was walking on. To do this I had to involve the collision detection system, to determine what surface he was walking on, the animation system to determine when the play the sound, and the sound system to play the sound in 3D space coming from the character. I accomplished this by giving the animations named events. Whenever the event was crossed in the animation it would call a function signaling that the event had been passed. The binding class would receive this event and then check with the collision system to see what surface the player is standing on, once it has the type of material it would lookup what sound to play based on the type of event and the type of material. It would then signal the sound system to play the sound. In this way all of my subsystems had no knowledge of each other but could still work together to produce the expected results.
My current game project Platform RPG
metsfan
metsfan

It sounds like you're pretty concerned about your memory usage patterns. I wouldn't worry about that so much right now. You're still in your development phase. Having custom allocators once you understand your usage patterns is very important, but you aren't even close to there yet. Right now I'd just focus on getting something working. The real memory eaters in applications aren't gonna be 50 unused bytes in an entity object. It's going to be your disk assets (textures, models, maps, ect). An extra 50 bytes per entity isn't going to break the bank (unless of course you have millions of entities, but that's not really a typical use case).

JoshuaWaring
JoshuaWaring

Well I was thinking about having things like that, and I had this class called a Message Manager and everything could check it to see if it had any messages for it.
I looked around in the Gish engine and right now I think things are nicely concealed. although I've had to remove my idea of any control to how the objects are stored in memory.

I should focus more on a prototype then final code designs.

deftware
deftware

I was playing with a similar concept - utilizing more of a databasing model as opposed to an object-oriented approach, but... I came to believe that grouping variables according to the conceptual entity they are associated with (in memory) allows for the CPU to more effectively make use of caching mechanisms when executing a chunk of code designed to handle said entity concept..

When you're performing physics, for example, it's more cache-coherent to have position/velocity/angles/etc. for each object stored within close proximity, so that when the CPU fetches that data from memory, most of the data that an executing piece of code would be operating on would be right there in the cache, instead of the cache constantly missing each time your code references a different variable for a given entity, and having to load the cache again with data from a far-away block of origins, or velocities, angles, etc..

It seems to make more sense, from a programming standpoint, but in practice it's just plain miserable for the CPU...

At least, this is my understanding, and somebody please correct me if I am wrong.

[ deftware.org ]
JoshuaWaring
JoshuaWaring

There's also the ram bank (http://en.wikipedia.org/wiki/Memory_bank#In_caching) which will benefit from having it being sequential.

Maybe the implementation is difficult, but very possible :D?

This idea is going to remain in my head, but I'll probably try and implement it on something small and simple, nothing like a game at first.

My biggest problem in programming comes from include loops... I've managed to get them back into my program -.-

Krohm
Krohm

According to my experience, high-level engine operations don't really weight much once put in a profiler.

As a side note, your efforts on entities are wasted effort: at a certain point you'll just want to move them all to scripts.

Be specific of your problems. You won't get anywhere by thinking of things "in general". If your entities are lights, that's a thing. If they are rigid bodies, that's another.

Previously "Krohm"
markr
markr

Don't worry too much about it.

I certainly wouldn't want to make "physics" or "object management" pluggable, they are usually very tightly integrated with the implementation of other parts. Look at the interface for any physics engine, and you'll see that in our own objects we are maintaining a lot of references to physics objects and vice versa.

Rendering is a bit different, because you might want to have pluggable renderers (likewise, sound, if that's a separate thing).

Pluggable AI is possibly useful (at least, because it lets you run several different/ competing AIs at once). It depends what level the AI is operating at.

So my answer:

* Physics, object-management - No. Don't even *think* about making them pluggable, it's a massive waste of effort.

* Rendering - yes, have it pluggable, at least to the extent that you can create a "null renderer" which won't draw anything (think network servers, test programs etc)

* AI - possibly - depending on how it's used in the game.

---

Regarding "storing things next to each other in memory" - this sounds like a micro-optimisation, you're probably better leaving those until later.

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.