1
\$\begingroup\$

I'm migrating my game pet-project to ECS. I use C# (custom-made engine, not Unity). It goes pretty well, but one big thing is making me worry.

This is how and where to store pointers to system resources or third party libraries' objects?

For example, I have object with Transform and RenderModel component. Transform contains data like matrices, quaternions etc (like described in any ECS paper :) RenderModel contains path to FBX scene and some data how to render this model (materials, overrides, flags, scaling, etc).

For model rendering I use existing rendering library. To render the model I need to create object, add it to this library, update its transform if necessary and destroy it when I don't need to draw this model any more.

The question is where to store pointer to such rendering objects?

I see three approaches:

  1. Any component that holds such resources implements methods OnAdd and OnRemove which are called when component added or removed respectively. On addition the component create lib's object and destroys it on removal. I've focused on this approach because it's pretty straightforward and simple to implement. Main drawback of such approach that I need to implement some kind of workaround to feed transformation to this models.

  2. Systems are stateful and keep tracking of component addition and removal. When given combination of components is added (i.e. RenderModel and Transform) system that handle object drawing creates internal representation of the model and destroys when components are removed. Main drawback that I have no idea how efficiently track multiple component addition and removal.

  3. Some kind of "imperative" approach. For each entity with RenderModel and Transform components system calls method like DrawModel(...). At the end of the frame the internal representation is destroyed and created again on next frame. Such approach looks like most convenient approach from game logic view, but suffer from obvious performance issues, because rendering library might build internal structures, cache visibility data, use interleaved shadow maps etc. Furthermore, updating this systems in parallel threads obviously will become nightmare.

Same issues I've also encountered with physics library and FMOD sound, because such libs also offer some long-living objects (non-POD) and build internal data structures.

Could you suggest better approach to solve such issue?

P.S. I use custom (made from scratch) engine (not Unity)

\$\endgroup\$
1
  • \$\begingroup\$ This is an excellent question and it touches on a problem that I have been wondering about for a while: How to insulate system-private runtime data (e.g. loaded models) from the rest of the game code, to the point where different implementations of a system could be exchanged transparently without affecting the "public" component structures. \$\endgroup\$ – minexew Dec 12 '20 at 21:22
1
\$\begingroup\$

About option 1 (that's the one I suggest because I used a similar approach):

Main drawback of such approach that I need to implement some kind of workaround to feed transformation to this models.

I don't think it's a "workaround". You need a function in a system that will propagate the physics simulation results to your Transform (for those objects simulated by the physics), a system that will propagate the other types of "animations" to the Transforms of those entities that are not moved my physics, and you'll need a function in a system that will propagate those Transforms to your RenderModel component.

Depending on how you do things, you can have your component just hold the pointer to your external libraries, while systems or other classes create them, at your convenience.

Keep in mind that an architecture pattern (ECS) is there to help you make your life easier, not to force you to do things in a certain way if they don't make sense to you, your project or your team, and there is no ECS police. Go with the approach that makes the most sense to you, and try to not get caught in analysis paralysis.

\$\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.