Reputation: 379
I am having some issues designing the memory management for an Entity-Component system and am having some issues coming up with the detail of the design. Here is what I am trying to do (note that all of these classes except Entity
are actually virtual, so will have many different specific implementations):
The Program
class will have a container of Entity
's. The Program
will loop through the Entity
's and call update on each of them. It will also have a few SubSystem
's, which it will also update on each loop through.
Each Entity
will contain two types of Component
's. All of them will be owned by a unique_ptr
inside the Entity
since their lifetime is directly tied to the entity. One type, UpdateableComponent
, will be updated when the Entity.update()
method is called. The second type SubSystemComponent
will be updated from within their respective SubSystem
.
Now here are my two problems. The first is that some of the Component
's will control the lifetime of their parent Entity
. My current idea for this is that Component
will be able to call a function parent.die()
which would change an internal flag inside Entity
. Then after Program
finishes looping through its updates, it loops through a second time and removes each Entity
which was marked for deletion during the last update. I don't know if this is an efficient or smart way to go about it, although it should avoid the problem of an Entity
dieing while its Component
's are still updating.
The second issue is that I am not sure how to reference SubSystemComponent
's from within SubSystem
. Since they are refered to by a unique_ptr
from inside Entity
, I can't use a shared_ptr
or a weak_ptr
, and a standard pointer would end up dangling when the Entity
owning a component dies. I could switch to a shared_ptr
inside the Entity
for these, then use a weak_ptr
in the SubSystem
's, however I would prefer to not do this because the whole point is that Entity
completely owns its Component
's.
So 2 things:
weak_ptr
sort of functionality with unique_ptr
, or should I just switch to shared_ptr
and just make sure to not create more than one shared_ptr
to the SubSystemComponent
'sUpvotes: 0
Views: 239
Reputation: 106096
Can my first idea be improved upon in a meaningful way?
Hard to say without knowing more about the nature of the work being undertaken. For example, you haven't said anything about your use of threads, but it seems your design gives equal priority to all the possible updates by cycling through things in a set sequence. For some things where low latency is important, or there's some useful prioritorisation that would ideally be done, a looping sequence like that isn't good, while other times it's ideal.
There are other ways to coordinate the Component-driven removal of Entities from the Program:
std::function
could allow the Program to specify cleanup behaviour.Is there an easy way to implement a weak_ptr sort of functionality with unique_ptr,
No.
or should I just switch to shared_ptr and just make sure to not create more than one shared_ptr to the SubSystemComponent's
It sounds like a reasonable fit. You could even wrap a shared_ptr
in a non-copyable class to avoid accidental mistakes.
Alternatively - as for Entity destruction above - you could coordinate the linkage between SubSystem
and SubSystemComponent
using events, so the SubSystemComponent
destructor calls back to the SubSystem
. An Observer pattern is one way to do this, a SubSystemComponent
-side std::function
fed a lambda is even more flexible. Either way, the Subsystem
removes the SubSystemComponent
from its records.
Upvotes: 1