librelist archives

« back to archive

entityx usage questions (network serialization as well)

entityx usage questions (network serialization as well)

From:
Shaun Reich
Date:
2014-10-02 @ 02:33
so, having tried artemis i'd like to try entityx...but i have a few
usage questions, as the api in question seems unclear

so, my issues...specifically i need a few use cases for network
serialization of components and i'd like to have this made more clear
so i don't do a horrible approach...

basically right now with artemis i grab an entities id on the server,
put it in the packet, get a list of components, for each one i add it
to a packet with an id that refers to the component type, and i
serialize the data that each component would want to have serialized
(somewhat manually, but only in one place..and then on deserialization
end).

so basically the problem is i need to tell the client "spawn this
entity of id x", so that i can trivially refer to it when sending
later commands. how can i create an entity with id of x? (assuming
they never collide. which they should not, assuming the client is
mostly in sync)

sidenote..why does entityx not return references at all it seems? e.g.
entities.create() returns simply an Entity?

also right now i have a bit of a hack which goes through each
component and finds which m_componentType they are of, and switches
based on that, appending a new component to the end of the message.
wasn't sure how to do this in artemis either, without doing something
pretty expensive...all i'd need is some identifier, and  then be able
to switch on said identifier.

additionally, how does one add a component exactly? the example only
seems to show constructor arguments, which doesn't scale past *maybe*
3 arguments.

the artemis equivalent was entity->addComponent(new PlayerComponent),
or obviously you could hoist that out. point being that components
sometimes have *many* values that may need to be set (and may need to
*not* be set on e.g. client!). is there an equivalent for this?
perhaps i missed it.



-- 
Shaun Reich,
KDE Software Developer (kde.org)

Re: [entityx] entityx usage questions (network serialization as well)

From:
Alec Thomas
Date:
2014-10-02 @ 04:39

On Thursday, 2 October 2014 at 12:33 pm, Shaun Reich wrote:

> so, having tried artemis i'd like to try entityx...but i have a few
> usage questions, as the api in question seems unclear
>  
> so, my issues...specifically i need a few use cases for network
> serialization of components and i'd like to have this made more clear
> so i don't do a horrible approach...
>  
> basically right now with artemis i grab an entities id on the server,
> put it in the packet, get a list of components, for each one i add it
> to a packet with an id that refers to the component type, and i
> serialize the data that each component would want to have serialized
> (somewhat manually, but only in one place..and then on deserialization
> end).
>  
> so basically the problem is i need to tell the client "spawn this
> entity of id x", so that i can trivially refer to it when sending
> later commands. how can i create an entity with id of x? (assuming
> they never collide. which they should not, assuming the client is
> mostly in sync)
>  
>  


The ID is actually two values, an index and a version number (which are 
also accessible). An ID is guaranteed to be unique for the lifetime of the
EntityManager, but the version of an index can change over the lifetime of
the EntityManager. This is a performance optimisation.

Unfortunately, if you’re using EntityX on both client and server, there’s 
no way to guarantee that an ID can be the same. This is because entities 
are actually implemented as indices into (essentially) an array, and 
destroyed entity indices are reused. The API prohibits the creation of 
Entity::Id’s deliberately.

Basically, the two goals are competing. The goal of EntityX is to provide 
extremely fast lookups and management of entities. The goal of a 
network-synchroinzable ID is to be unique across all peers.

This has been asked a few times, so I think I’ll add it to the README.
>  
> sidenote..why does entityx not return references at all it seems? e.g.
> entities.create() returns simply an Entity?
>  
>  


Entity objects are just handles containing a pointer to the EntityManager,
and an ID. An entity is purely an ID, so there’s nothing to reference. 
Components are allocated in arrays of the same type.
>  
> also right now i have a bit of a hack which goes through each
> component and finds which m_componentType they are of, and switches
> based on that, appending a new component to the end of the message.
> wasn't sure how to do this in artemis either, without doing something
> pretty expensive...all i'd need is some identifier, and then be able
> to switch on said identifier.
>  
>  


It sounds like you’re asking for a way to iterate over components for an entity?

Unfortunately there’s no good solution to this due to limitations of C++ 
and the approach taken by EntityX.

The two options as far as I’m aware are:
Iterate over all valid components of an entity as a base type 
(BaseComponent), then cast to the appropriate type based on the 
::family(). This is not type safe.
Iterate over all known components, checking if an entity has that 
component. This is type safe.

I chose option 2 because it’s type safe, and probably about as fast. It is
slightly more annoying for the user, but casting is annoying too.

>  
> additionally, how does one add a component exactly? the example only
> seems to show constructor arguments, which doesn't scale past *maybe*
> 3 arguments.
>  
>  


Components are allocated into slabs via placement new (for performance 
reasons). That is why components must be constructed through the provided 
interface.

That said, there are two options for more complex construction:
ComponentManager::assign<C>(…) returns a pointer-like object 
(<Component>::Handle) to the newly created component. You can use this to 
do further initialisation.
You can create your object manually, then ::assign<C>(copy) via copy construction.

I would use option 1 if possible, to avoid the overhead of copy construction.


>  
> the artemis equivalent was entity->addComponent(new PlayerComponent),
> or obviously you could hoist that out. point being that components
> sometimes have *many* values that may need to be set (and may need to
> *not* be set on e.g. client!). is there an equivalent for this?
> perhaps i missed it.
>  
>  
>  
> --  
> Shaun Reich,
> KDE Software Developer (kde.org (http://kde.org))
>  
>  

Re: [entityx] entityx usage questions (network serialization as well)

From:
Shaun Reich
Date:
2014-10-02 @ 12:56
On Thu, Oct 2, 2014 at 12:39 AM, Alec Thomas <alec@swapoff.org> wrote:
> Basically, the two goals are competing. The goal of EntityX is to provide
> extremely fast lookups and management of entities . The go al of a
> network-synchroinzable ID is to be unique across all peers.

okay, makes sense. what is the approach that network games should
take, then? or is entityx simply not well suited for network
synchronization?

>I chose option 2 because it's type safe, and probably about as fast. It 
is slig htly mor e annoying for the user, but casting is annoying too.

yeah, and extremely slow, is the main issue with them.



-- 
Shaun Reich,
KDE Software Developer (kde.org)

Re: [entityx] entityx usage questions (network serialization as well)

From:
Alec Thomas
Date:
2014-10-02 @ 13:49



> On Oct 2, 2014, at 10:56 PM, Shaun Reich <sreich@kde.org> wrote:
> 
>> On Thu, Oct 2, 2014 at 12:39 AM, Alec Thomas <alec@swapoff.org> wrote:
>> Basically, the two goals are competing. The goal of EntityX is to provide
>> extremely fast lookups and management of entities . The go al of a
>> network-synchroinzable ID is to be unique across all peers.
> 
> okay, makes sense. what is the approach that network games should
> take, then? or is entityx simply not well suited for network
> synchronization?

It is not in scope for EntityX to solve this problem. You'll need to find 
a solution.

> 
>> I chose option 2 because it's type safe, and probably about as fast. It
is slig htly mor e annoying for the user, but casting is annoying too.
> 
> yeah, and extremely slow, is the main issue with them.

I'd be surprised if it were. It's basically a bit mask per component. 
Unless you have a large number of components this should be pretty minor.

If you have a better approach I'm all ears.

> 
> 
> 
> -- 
> Shaun Reich,
> KDE Software Developer (kde.org)

Re: [entityx] entityx usage questions (network serialization as well)

From:
Shaun Reich
Date:
2014-10-02 @ 15:17
>>> I chose option 2 because it's type safe, and probably about as fast. 
It is slig htly mor e annoying for the user, but casting is annoying too.
>>
>> yeah, and extremely slow, is the main issue with them.
>
> I'd be surprised if it were. It's basically a bit mask per component. 
Unless you have a large number of components this should be pretty minor.

was referring to using dynamic_cast for another approach, though the
hierarchies would be shallow so it wouldn't be a *super* big deal.
your approach seems fine.

for component iteration..guess there's not a good way without a lot of
copy & paste :/

i was thinking, to tackle the network sync problem, would it be
reasonable you think, to add an idcomponent which would just have some
unique id across the net, and make some kinda idsystem which would
track adds, removals and hash them so when it needs looked up, it'll
be trivial to query it.

or do you have a better approach in mind? of course i could add that
functionality to entityx itself, at the cost of more maintenance,
possibly fucking with cache(depending on  how big uid's would be),
etc.


-- 
Shaun Reich,
KDE Software Developer (kde.org)

Re: [entityx] entityx usage questions (network serialization as well)

From:
Alec Thomas
Date:
2014-10-02 @ 23:07
On Oct 3, 2014, at 1:17 AM, Shaun Reich <sreich@kde.org> wrote:

>>>> I chose option 2 because it's type safe, and probably about as fast. 
It is slig htly mor e annoying for the user, but casting is annoying too.
>>>
>>> yeah, and extremely slow, is the main issue with them.
>>
>> I'd be surprised if it were. It's basically a bit mask per component. 
Unless you have a large number of components this should be pretty minor.
>
> was referring to using dynamic_cast for another approach, though the
> hierarchies would be shallow so it wouldn't be a *super* big deal.
> your approach seems fine.
>
> for component iteration..guess there's not a good way without a lot of
> copy & paste :/
>
> i was thinking, to tackle the network sync problem, would it be
> reasonable you think, to add an idcomponent which would just have some
> unique id across the net, and make some kinda idsystem which would
> track adds, removals and hash them so when it needs looked up, it'll
> be trivial to query it.
>
> or do you have a better approach in mind? of course i could add that
> functionality to entityx itself, at the cost of more maintenance,
> possibly fucking with cache(depending on  how big uid's would be),
> etc.
>

I've been thinking about this a bit overnight and I think your idea is
a reasonable approach.

Here's what I was thinking:

- A NetworkSystem on each node maintains a mapping from netid to entityid.
- Subscribe NetworkSystem to
ComponentAddedEvent<SynchronizedComponent> and
ComponentRemovedEvent<SynchronizedEvent> to maintain the mapping
automatically.
- Add a SynchronizedComponent to tell the NetworkSystem which entities
should be synchronized. It might just have a netid, but you might also
want to track any state that can tell you whether an entity should be
synced across the network. For example, previous position,
orientation, or a dirty flag.
- netid could be a 8+24 bit number composed of node+counter to
identify which node an object was created on. This allows clients to
predictively create entities before the server  is synchronized.
- Pick a tick rate for synchronization to occur.
- Every tick, NetworkServerSystem iterates over all entities with a
SynchronizedComponent, checking if it needs to be synchronized (eg.
dirty flag) and bundles all the changes up into network sync payload
for each client.

Obviously this is vastly simplifying, but it seems fairly reasonable.

>
> --
> Shaun Reich,
> KDE Software Developer (kde.org)

Re: [entityx] entityx usage questions (network serialization as well)

From:
Asmodehn Shade
Date:
2014-10-02 @ 15:29
Hello,

I have been thinking about this topic as i use entityx now in a game that
has some network elements ( async http however ) and that i have experience
in MMO kind of games...

Entities in entityx ( and as they are supposed to be in the way i
understand entity system design ) are just a set of components. These
components are the data that systems work on *every update call*.

That means this entities basically can a priori change, appear and
disappear every update loop of your game ( usually every ~15 ms for 60 fps
- a minimum )

That cycle is too fast for network games with distributed entity concept
where you might expect one entity to match one global abstract concept
object of the game world ( monster etc. ) but it is perfect to use for the
local representation of that object ( think the local ghost of an online
racer )

I think if you want an distributed entity concept for a network game, there
needs to be another level. Simulation standards like HLA have these
concept, which are just extension of corba distributed objects, but these
local concept of entity and objects might not be appropriate for slow
change rate over a network and there probably must be some adaptation.

On top of components and system, in entityx there are events ( signals ).
I usually dont use events when dealing with components and system ( because
i can just create and delete a component to send a message to another
system ) but i use events when i want to send a global message from my
"entityx world" ( the set of systems implementing a complex feature ) into
the rest of the application. So they serve as media to transfer message
outside my "entityx world" and that outside could be another process
somewhere...

So if i were you i would look into how to bind signals ( essentially fancy
callbacks ) from one process to another, via different mechanisms (
network, shared memory, ipc,  etc. )
Some projects probably exist with this feature... Then one process sending
events can have a globally unique ID and that would be your distributed
entity concept... i did a brief work on distributed ID synchronization
mechanism for process sending events, i can give you pointers if you re
interested.

Then you can realize it doesnt have to be a whole process, it can probably
be slimmed down to a thread, or some other fancy design pattern to include
in a server design architecture ( proactor / reactor ), or you could build
it around this architecture. container or contained not sure which one
would be best...

Then finally there need to be a way to create a library from this code that
can be either server or client. And from then on you have a usable global
distributed concept that match the abstraction that we think about when
designing server and client together to incarnate some abstract concept in
a distributed way.

Something i wished i had more time to study in depth. Keep me posted if you
find a good solution, i m very interested.

Good luck.
On Oct 2, 2014 10:50 PM, "Alec Thomas" <alec@swapoff.org> wrote:

>
>
>
>
> > On Oct 2, 2014, at 10:56 PM, Shaun Reich <sreich@kde.org> wrote:
> >
> >> On Thu, Oct 2, 2014 at 12:39 AM, Alec Thomas <alec@swapoff.org> wrote:
> >> Basically, the two goals are competing. The goal of EntityX is to
> provide
> >> extremely fast lookups and management of entities . The go al of a
> >> network-synchroinzable ID is to be unique across all peers.
> >
> > okay, makes sense. what is the approach that network games should
> > take, then? or is entityx simply not well suited for network
> > synchronization?
>
> It is not in scope for EntityX to solve this problem. You'll need to find
> a solution.
>
> >
> >> I chose option 2 because it's type safe, and probably about as fast. It
> is slig htly mor e annoying for the user, but casting is annoying too.
> >
> > yeah, and extremely slow, is the main issue with them.
>
> I'd be surprised if it were. It's basically a bit mask per component.
> Unless you have a large number of components this should be pretty minor.
>
> If you have a better approach I'm all ears.
>
> >
> >
> >
> > --
> > Shaun Reich,
> > KDE Software Developer (kde.org)
>

Re: [entityx] entityx usage questions (network serialization as well)

From:
ryan alexander
Date:
2014-10-02 @ 05:35
A question related to component initialization: Say I go with option 1 and
assign a component, and then modify it after. On assign, a system will
receive a ComponentAddedEvent. This is where I find myself doing things
like adding a physics body to the world. But in this case the component
hasn't really been initialized yet, so I'd need to add the body somewhere
else.

Does EntityX provide a mechanism for notifying systems of changes
post-assignment? Maybe this is this something we'd use events for?

Thanks!

ryan

# Ryan Alexander
# http://onecm.com

On Wed, Oct 1, 2014 at 9:39 PM, Alec Thomas <alec@swapoff.org> wrote:

>
>  On Thursday, 2 October 2014 at 12:33 pm, Shaun Reich wrote:
>
> so, having tried artemis i'd like to try entityx...but i have a few
> usage questions, as the api in question seems unclear
>
> so, my issues...specifically i need a few use cases for network
> serialization of components and i'd like to have this made more clear
> so i don't do a horrible approach...
>
> basically right now with artemis i grab an entities id on the server,
> put it in the packet, get a list of components, for each one i add it
> to a packet with an id that refers to the component type, and i
> serialize the data that each component would want to have serialized
> (somewhat manually, but only in one place..and then on deserialization
> end).
>
> so basically the problem is i need to tell the client "spawn this
> entity of id x", so that i can trivially refer to it when sending
> later c ommands. how can i create an entity with id of x? (assuming
> they never collide. which they should not, assuming the client is
> mostly in sync)
>
>
> The ID is actually two values, an index and a version number (which are
> also accessible). An ID is guaranteed to be unique for the lifetime of the
> EntityManager, but the version of an index can change over the lifetime of
> the EntityManager. This is a performance optimisation.
>
> Unfortunately, if you’re using EntityX on both client and server, there’s
> no way to guarantee that an ID can be the same. This is because entities
> are actually implemented as indices into (essentially) an array, and
> destroyed entity indices are reused. The API prohibits the creation of
> Entity::Id’s deliberately.
>
> Basically, the two goals are competing. The goal of EntityX is to provide
> extremely fast lookups and management of entities. The go al of a
> network-synchroinzable ID is to be unique across all peers.
>
> This has been asked a few times, so I think I’ll add it to the README.
>
>
> sidenote..why does entityx not return references at all it seems? e.g.
> entities.create() returns simply an Entity?
>
>
> Entity objects are just handles containing a pointer to the EntityManager,
> and an ID. An entity is purely an ID, so there’s nothing to reference.
> Components are allocated in arrays of the same type.
>
>
> also right now i have a bit of a hack which goes through each
> component and finds which m_componentType they are of, and switches
> based on that, appending a new component to the end of the message.
> wasn't sure how to do this in artemis either, without doing something
> pretty expensive...all i'd need is some identifier, and then be able
> to switch on said identifier.
>
>
> It sounds like you’re asking for a way to iterate over components for an
> entity?
>
> Unfortunately there’s no good solution to this due to limitations of C++
> and the approach taken by EntityX.
>
> The two options as far as I’m aware are:
>
>    - Iterate over all valid components of an entity as a base type
>    (BaseComponent), then cast to the appropriate type based on the ::family().
>    This is not type safe.
>    - Iterate over all known components, checking if an entity has that
>    component. This is type safe.
>
> I chose option 2 because it’s type safe, and probably about as fast. It is
> slightly mor e annoying for the user, but casting is annoying too.
>
>
> additionally, how does one add a component exactly? the example only
> seems to show constructor arguments, which doesn't scale past *maybe*
> 3 arguments.
>
>
> Components are allocated into slabs via placement new (for performance
> reasons). That is why components must be constructed through the provided
> interface.
>
> That said, there are two options for more complex construction:
>
>    1. ComponentManager::assign<C>(…) returns a pointer-like object
>    (<Component>::Handle) to the newly created component. You can use this to
>    do further initialisation.
>    2. You can create your object manually, then ::assign<C>(copy) via
>    copy construction.
>
> I wo uld use option 1 if possible, to avoid the overhead of copy
> construction.
>
>
> the artemis equivalent was entity->addComponent(new PlayerComponent),
> or obviously you could hoist that out. point being that components
> sometimes have *many* values that may need to be set (and may need to
> *not* be set on e.g. client!). is there an equivalent for this?
> perhaps i missed it.
>
>
>
> --
> Shaun Reich,
> KDE Software Developer (kde.org)
>
>
>

Re: [entityx] entityx usage questions (network serialization as well)

From:
Alec Thomas
Date:
2014-10-02 @ 06:41

On Thursday, 2 October 2014 at 3:35 pm, ryan alexander wrote:

> A question related to component initialization: Say I go with option 1 
and assign a component, and then modify it after. On assign, a system will
receive a ComponentAddedEvent. This is where I find myself doing things 
like adding a physics body to the world. But in this case the component 
hasn't really been initialized yet, so I'd need to add the body somewhere 
else.

Yeah, in that situation you’d either need to fully initialise the 
component before assigning, or not use ComponentAddedEvent.

Another option is to make the component a thin container for a pointer to 
the “complex” data. Then you pre-initialise the complex structure and 
assign from that. eg.

struct MyComponentData {
// complex data here
};

struct MyComponent : public ex::Component<MyComponent> {
MyComponent(MyComponentData *d) : d(d) {}
~MyComponent() { delete d; }

MyComponentData *d;
};

In this case though, you lose cache coherency when iterating over the component.

The approach I usually take is to drive my components from external data 
stored in JSON. I just pass a pointer to the JSON structure in to the 
component constructor and let the component initialise itself. This allows
for arbitrarily complex components with zero overhead.
  
>  
> Does EntityX provide a mechanism for notifying systems of changes 
post-assignment? Maybe this is this something we'd use events for?

There is no built-in facility for this, but yes, you could definitely use 
an event for this.
  
>  
> Thanks!
>  
> ryan
>  
> # Ryan Alexander
> # http://onecm.com  
> On Wed, Oct 1, 2014 at 9:39 PM, Alec Thomas <alec@swapoff.org 
(mailto:alec@swapoff.org)> wrote:
> >  
> >  
> > On Thursday, 2 October 2014 at 12:33 pm, Shaun Reich wrote:
> >  
> > > so, having tried artemis i'd like to try entityx...but i have a few
> > > usage questions, as the api in question seems unclear
> > >  
> > > so, my issues...specifically i need a few use cases for network
> > > serialization of components and i'd like to have this made more clear
> > > so i don't do a horrible approach...
> > >  
> > > basically right now with artemis i grab an entities id on the server,
> > > put it in the packet, get a list of components, for each one i add it
> > > to a packet with an id that refers to the component type, and i
> > > serialize the data that each component would want to have serialized
> > > (somewhat manually, but only in one place..and then on deserialization
> > > end).
> > >  
> > > so basically the problem is i need to tell the client "spawn this
> > > entity of id x", so that i can trivially refer to it when sending
> > > later c ommands. how can i create an entity with id of x? (assuming
> > > they never collide. which they should not, assuming the client is
> > > mostly in sync)
> > >  
> > >  
> > >  
> >  
> >  
> > The ID is actually two values, an index and a version number (which 
are also accessible). An ID is guaranteed to be unique for the lifetime of
the EntityManager, but the version of an index can change over the 
lifetime of the EntityManager. This is a performance optimisation.
> >  
> > Unfortunately, if you’re using EntityX on both client and server, 
there’s no way to guarantee that an ID can be the same. This is because 
entities are actually implemented as indices into (essentially) an array, 
and destroyed entity indices are reused. The API prohibits the creation of
Entity::Id’s deliberately.
> >  
> > Basically, the two goals are competing. The goal of EntityX is to 
provide extremely fast lookups and manageme nt of entities. The go al of a
network-synchroinzable ID is to be unique across all peers.
> >  
> > This has been asked a few times, so I think I’ll add it to the README.
> > >  
> > > sidenote..why does entityx not return references at all it seems? e.g.
> > > entities.create() returns simply an Entity?
> > >  
> > >  
> > >  
> >  
> >  
> > Entity objects are just handles containing a pointer to the 
EntityManager, and an ID. An entity is purely an ID, so there’s nothing to
reference. Components are allocated in arrays of the same type.
> > >  
> > > also right now i have a bit of a hack which goes through each
> > > component and finds which m_componentType t hey are of, and switches
> > > based on that, appending a new component to the end of the message.
> > > wasn't sure how to do this in artemis either, without doing something
> > > pretty expensive...all i'd need is some identifier, and then be able
> > > to switch on said identifier.
> > >  
> > >  
> > >  
> >  
> >  
> > It sounds like you’re asking for a way to iterate over components for 
an entity?
> >  
> > Unfortunately there’s no good solution to this due to limitations of 
C++ and the approach taken by EntityX.
> >  
> > The two options as far as I’m aware are:
> > Iterate over all valid components of an entity as a base type 
(BaseComponent), then cast to the appropriate type based on the 
::family(). This is not type safe.
> > Iterate over all known components, checking if an entity has that 
component. This is type safe.
> >  
> > I chose option 2 because it’s type safe, and probably about as fast. 
It is slightly mor e annoying for the user, but casting is annoying too.
> >  
> > >  
> > > additionally, how does one add a component exactly? the example only
> > > seems to show constructor arguments, which doesn't scale past *maybe*
> > > 3 arguments.
> > >  
> > >  
> > >  
> >  
> >  
> > Components are allocated into slabs via placement new (for performance
reasons). That is why components must be constructed through the provided 
interface.
> >  
> > That said, there are two options for more complex construction:
> > ComponentManager::assign<C>(…) returns a pointer-like object 
(<Component>::Handle) to the newly created component. You can use this to 
do further initialisation.
> > You can create your object manually, then ::assign<C>(copy) via copy 
constru ction.
> >  
> > I wo uld use option 1 if possible, to avoid the overhead of copy construction.
> >  
> >  
> > >  
> > > the artemis equivalent was entity->addComponent(new PlayerComponent),
> > > or obviously you could hoist that out. point being that components
> > > sometimes have *many* values that may need to be set (and may need to
> > > *not* be set on e.g. client!). is there an equivalent for this?
> > > perhaps i missed it.
> > >  
> > >  
> > >  
> > > --  
> > > Shaun Reich,
> > > KDE Software Developer (kde.org (http://kde.org))
> > >  
> > >  
> > >  
> >  
> >  
>  

Re: [entityx] entityx usage questions (network serialization as well)

From:
ryan alexander
Date:
2014-10-02 @ 07:37
This specific component data is all pointers to physics objects anyway, so
the loss of coherency wouldn't make much difference. Backing components
with JSON seems like a useful way to ease the pain of serializing state.

Thanks for the suggestions!

# Ryan Alexander
# http://onecm.com

On Wed, Oct 1, 2014 at 11:41 PM, Alec Thomas <alec@swapoff.org> wrote:

>
>  On Thursday, 2 October 2014 at 3:35 pm, ryan alexander wrote:
>
> A question related to component initialization: Say I go with option 1 and
> assign a component, and then modify it after. On assign, a system will
> receive a ComponentAddedEvent. This is where I find myself doing things
> like adding a physics body to the world. But in this case the component
> hasn't really been initialized yet, so I'd need to add the body somewhere
> else.
>
>
> Yeah, in that situation you’d either need to fully initialise the
> component before assigning, or not use ComponentAddedEvent.
>
> Another option is to make the component a thin container for a pointer to
> the “complex” data. Then you pre-initialise the complex structure and
> assign from that. eg.
>
> struct MyComponentData {
> // complex data here
> };
>
> struct MyComponent : public ex::Component<MyComponent> {
> MyComponent(MyComponentData *d) : d(d) {}
> ~MyComponent() { delete d; }
>
> MyComponentData *d;
> };
>
> In this case though, you lose cache coherency when iterating over the
> component.
>
> The approach I usually take is to drive my components from external data
> stored in JSON. I just pass a pointer to the JSON structure in to the
> component constructor and let the component initialise itself. This allows
> for arb itrarily complex components with zero overhead.
>
>
>
> Does EntityX provide a mechanism for notifying systems of changes
> post-assignment? Maybe this is this something we'd use events for?
>
>
> There is no built-in facility for this, but yes, you could definitely use
> an event for this.
>
>
>
> Thanks!
>
> ryan
>
> # Ryan Alexander
> # http://onecm.com
>
> On Wed, Oct 1, 2014 at 9:39 PM, Alec Thomas <alec@swapoff.org> wrote:
>
>
>  On Thursday, 2 October 2014 at 12:33 pm, Shaun Reich wrote:
>
> so, having tried artemis i'd like to try entityx...but i have a few
> usage questions, as the api in question seems unclear
>
> so, my issues...specifically i need a few use cases for network
> serialization of components and i'd like to have this made more clear
> so i don't do a horrible approach...
>
> basically right now with artemis i grab an entities id on the server,
> put it in the packet, get a list of components, for each one i add it
> to a packet with an id that refers to the component type, and i
> serialize the data that each component would want to have serialized
> (somewhat manually, but only in one place..and then on deserialization
> end).
>
> so basically the problem is i need to tell the client "spawn this
> entity of id x", so that i can trivially refer to it when sending
> later c ommands. how can i create an entity with id of x? (assuming
> they never collide. which they should not, assuming the client is
> mostly in sync)
>
>
> The ID is actually two values, an index and a version number (which are
> also accessible). An ID is guaranteed to be unique for the lifetime of the
> EntityManager, but the version of an index can change over the lifetime of
> the EntityManager. This is a performance optimisation.
>
> Unfortunately, if you’re using EntityX on both client and server, there’s
> no way to guarantee that an ID can be the same. This is because entities
> are actually implemented as indices into (essentially) an array, and
> destroyed entity indices are reused. The API prohibits the creation of
> Entity::Id’s deliberately.
>
> Basically, the two goals are competing. The goal of EntityX is to provide
> extremely fast lookups and manageme nt of entities. The go al of a
> network-synchroinzable ID is to be unique across all peers.
>
> This has been asked a few times, so I think I’ll add it to the README.
>
>
> sidenote..why does entityx not return references at all it seems? e.g.
> entities.create() returns simply an Entity?
>
>
> Entity objects are just handles containing a pointer to the EntityManager,
> and an ID. An entity is purely an ID, so there’s nothing to reference.
> Components are allocated in arrays of the same type.
>
>
> also right now i have a bit of a hack which goes through each
> component and finds which m_componentType t hey are of, and switches
> based on that, appending a new component to the end of the message.
> wasn't sure how to do this in artemis either, without doing something
> pretty expensive...all i'd need is some identifier, and then be able
> to switch on said identifier.
>
>
> It sounds like you’re asking for a way to iterate over components for an
> entity?
>
> Unfortunately there’s no good solution to this due to limitations of C++
> and the approach taken by EntityX.
>
> The two options as far as I’m aware are:
>
>    - Iterate over all valid components of an entity as a base type
>    (BaseComponent), then cast to the appropriate type based on the ::family().
>    This is not type safe.
>    - Iterate over all known components, checking if an entity has that
>    component. This is type safe.
>
> I chose option 2 because it’s type safe, and probably about as fast. It is
> slightly mor e annoying for the user, but casting is annoying too.
>
>
> additionally, how does one add a component exactly? the example only
> seems to show constructor arguments, which doesn't scale past *maybe*
> 3 arguments.
>
>
> Components are allocated into slabs via placement new (for performance
> reasons). That is why components must be constructed through the provided
> interface.
>
> That said, there are two options for more complex construction:
>
>    1. ComponentManager::assign<C>(…) returns a pointer-like object
>    (<Component>::Handle) to the newly created component. You can use this to
>    do further initialisation.
>    2. You can create your object manually, then ::assign<C>(copy) via
>    copy constru ction.
>
> I wo uld use option 1 if possible, to avoid the overhead of copy
> construction.
>
>
> the artemis equivalent was entity->addComponent(new PlayerComponent),
> or obviously you could hoist that out. point being that components
> sometimes have *many* values that may need to be set (and may need to
> *not* be set on e.g. client!). is there an equivalent for this?
> perhaps i missed it.
>
>
>
> --
> Shaun Reich,
> KDE Software Developer (kde.org)
>
>
>
>
>