Improving component system

Started by
12 comments, last by Norman Barrows 9 years, 4 months ago

Sean, I saw your videos on game spaces and data-driven design not too long ago. You're correct in that you can find a happy medium between intuitive OO code cache-friendly performance. Personally I've only seen it really count in my programs when it comes to managing graphics-related resources, so I do a ton of pooling of textures and meshes, and instance transforms to reduce state changes.

The blog you linked to looks like a pretty good implementation of data-oriented ECS. Shows that the author has prior real-world experience in game coding for performance. On the other hand, it doesn't sound like something you'd recommend if you already made your own kind of ECS framework which still does the job pretty well after testing it with many more components than you would actually use. Refactoring your code at that point of development seems almost useless if it's for that particular case use, while it's better off attempting it for a brand new game.

One thing I still don't fully understand about this type of ECS design, though. With entities as ID's, where should the component pools reside if a single system needs to work on two or more different types of components? Or should it only be one component type-per-system in this case?

New game in progress: Project SeedWorld

My development blog: Electronic Meteor

Advertisement

Another solution for dealing with related bone transforms is to consider them as higher-level things of their own rather than an explicit parent-child relationship. Think about how a weld joint works in a physics engine. This may not always be the best way to do it but it provides an elegant solution to situations such as the presented case of the cup on the table, where neither entity should be dependent on the other.

And when it comes to using packed, unordered component pools with systems that operate on multiple component types, you should have an array acting as a layer of indirection that maps IDs to offsets within the pool. This structure can also deal with handle invalidation through "magic numbers". Again, BitSquid has a good article on this concept. If you're worried about cache coherency when it comes to these indirected accesses, my advice would be to deal with different object archetypes in heterogeneous ways. For example, if not every entity has a velocity while every entity has a position, separate your entities into "static" and "dynamic" pools. That way, your "dynamic" entities can keep their position and velocity components packed and correlated.

"So there you have it, ladies and gentlemen: the only API I’ve ever used that requires both elevated privileges and a dedicated user thread just to copy a block of structures from the kernel to the user." - Casey Muratori

boreal.aggydaggy.com

And when it comes to using packed, unordered component pools with systems that operate on multiple component types, you should have an array acting as a layer of indirection that maps IDs to offsets within the pool. This structure can also deal with handle invalidation through "magic numbers". Again, BitSquid has a good article on this concept. If you're worried about cache coherency when it comes to these indirected accesses, my advice would be to deal with different object archetypes in heterogeneous ways. For example, if not every entity has a velocity while every entity has a position, separate your entities into "static" and "dynamic" pools. That way, your "dynamic" entities can keep their position and velocity components packed and correlated.

So the array to map IDs to different places in the pool is like a database table that stores relationships between entries in other tables? That's what I get from it being a "layer of indirection". Also, then it sounds like the component pools would not be inside of the system (but to me, it doesn't make sense for a system object to store components anyways, just needs to manipulate them). Looking through my code nearly all my Systems work on more than one type.

Splitting up the pools when the entities have slightly different behavior sounds like a good idea too, and easy to understand. Looks like I'll distinguish the "static" from "dynamic" entities for those that have a position component.

My idea is to have all the Position components in one array and those that belong to "dynamic" entities would be ordered from the beginning of the array, with the Positions of "static" ones afterwards. In practice most of my entities with a Position would not have a Velocity and therefore be static.

New game in progress: Project SeedWorld

My development blog: Electronic Meteor

in its most generalized form, an ECS usually looks something like this:

first you have a list of entities.

each entity has some sort of pointers or IDs referencing their components

then you have lists for each type of component.

and you have methods that operate on components.and / or component lists.

the list of entities just tells you where an entity's data is. the component lists hold the actual data, divvied up by component type. note that a render or update method could also be considered a component type.

Norm Barrows

Rockland Software Productions

"Building PC games since 1989"

rocklandsoftware.net

PLAY CAVEMAN NOW!

http://rocklandsoftware.net/beta.php

This topic is closed to new replies.

Advertisement