Updating an entity component system asynchronously

Started by
2 comments, last by AxeGuywithanAxe 8 years, 12 months ago

Hello gamedev.net. In the past two weeks I have taken time to research data oriented programming and entity component systems. As these two features are seeming to become the norm in engines, I thought that I should learn as much as possible about these two patterns. After reading the GDC 15 article that Bungie released pertaining to their component/data oriented renderer, http://advances.realtimerendering.com/destiny/gdc_2015/Tatarchuk_GDC_2015__Destiny_Renderer_web.pdf,

I seem to have somewhat of a grasp over the rendering side. My problem now relates to updating game objects in a multithreaded environment. I have read that one of the greatest advantages of data oriented/component based engines is cache coherency, in that you can update all, or most, of a certain component at the same time linearly, but I don't understand how that would work in an object system with dependencies such as attachments.

i.e if Object1 is attached to Object2, then Object2 must have all of it's components capable of updating it's internal state (like position/animation possibly physics?) updated prior to Object 1. This would mean that multiple systems would have to be traversed. Would this not make the effort for cache coherency moot?

And in a scenario where Object 2 must be updated prior to Object 1, would Object2 call some type of virtual update function on it's own components based on the update phase that it is in? i.e If Object2 is in a pre physics update phase, would it call all of it's components that are interested in being updated during this phase?

These seem like issues that would make updating a simple entity component, data oriented, and cache coherent system more complex than a basic inheritance based approach in a single threaded environment, let alone a multithreaded one.

To save myself from rambling anymore , I would like to ask for opinions on possible approaches, either proven or theoretical, for updating entities, and their components in a multithreaded environment that tries to sustain cache coherency. I would also like to know if any developers have subscribed to this method and have had success, or if I should go to a simplistic component system and find other ways to optimize my code. Thank you.

Advertisement

In an entity component system, there really are no 'objects' or 'entities', so it would be wrong to say that one entity must be updated before another. Components might have update order constraints WRT to other components or systems.

I think the point is more that with ECS systems, objects tend to naturally be organized in a cache friendly way, and if they dont, its very easy to make it happen.

If there are no dependencies between components of the same type, you can update components of that type in any order (perhaps using worker threads to divide the workload) so its not an issue there, and I would say most components are like that. Instead, dependencies tend to be between types of components, where its easy to just update the different systems in the correct order.

In the cases where components might depend on others of the same type, you still can design the system such that its cache friendly:

  1. You could see if its possible to make the components accept data from previous update instead of current one (so update order doesnt matter within a single frame)
  2. You could store the components sorted in an array such that 'parent' components come before 'child' components (flattened tree), cache friendly and update order is correct, downside is that there will probably be some indirection cost and sorting cost since components cant stay in the same position forever.
  3. If your dependency tree has finite depth, you could split the components of that system into multiple levels where each level is a 'normal' cache friendly component storage thingy (similar to how you might have pre-update, update, post-update etc.)
  4. Use whatever data structure you have to use. Its not like you need to do this for every type of component and its not like you would have better options without ECS.

o3o

This is a good article about how it was done in Uncharted 2: http://www.gameenginebook.com/resources/gfg2010-final.pdf

Thank you both for your response. I actually have both of his books. I was thinking of doing the bucketed approach that he presented. My only reservation was with the use of predetermined buckets. But this would be a much simpler solution than the one's I've seen prior. I guess my approach would replace a "Character" bucket, with possibly a "Level1" bucket or something of that nature? As in entities/components without a parent would be in the Level 0 bucket, and then if they are attached to a vehicle, they're bucket index is incremented? That would require updating a lot of buckets depending on the components that the entity owns. hmm.

This topic is closed to new replies.

Advertisement