Search Unity

Designing components

Discussion in 'Entity Component System' started by Suike, May 8, 2019.

  1. Suike

    Suike

    Joined:
    Jul 25, 2013
    Posts:
    16
    Hi,
    I'm new to ECS and been experimenting with a few things. While ECS splits the data into components, each with its own relevant information to be used by systems, I assume (please correct me if I'm wrong) it is not a bad design decision to use a component just to store data.

    But I don't really know what the best way to design components in this case:

    Let's say I have Enemy entries in a database with some simple fields like "Max Health" and "Movespeed". This data is supposed to be immutable in the client, it comes from the database and is read-only.
    But it is also used by systems, for instance, the "Current Health" of an enemy cant be over it's "Max Health".

    Should I have an EnemyModel component with the immutable data, and some other components like RuntimeHealth with the "Current Health" and have the HealthSystem lookup values from both components in the entity when increasing "Current Health" so it doesn't go over "Max Health". Or have a HealthComponent with "Current Health" and "Max Health" and having the HealthSystem just looking up one component, but resulting in the external data (from the database) being split into multiples components?

    What are the advantages and disadvantages of both approaches? I believe that in the second the memory is more easily available to the system (since it is in the same component) so it will be faster (although IDK if the speed significant looking at how ECS is designed); while in the first I keep a direct representation of the model in the database as a component, so I think it should be easier to understand/maintain.

    Please feel free to correct me if I'm wrong anywhere, still learning about this.

    Basically: What should I do with immutable, read-only data that multiples systems need to access? should I copy the values in each component for each entity? is there an ECS way to only keep 1 instance of the values and have all systems read from a reference to that instance?

    I think this is kinda similar to the embedded vs reference debate in a NoSQL database

    Tried to do some nice formatting so it is easier to read :p

    Edit: I'm not really sure what are "best practices" for ECS.
     
    Last edited: May 9, 2019
  2. siggigg

    siggigg

    Joined:
    Apr 11, 2018
    Posts:
    247
    I too have been thinking about something similar.

    An archetype is a combination of what components an entity has.
    But a designer also has to be able to set what values those components have, often done in a content authoring tool and stored in some kind of database (json file for example).

    Then when you instantiate a type at runtime, you want it to be of the specified archetype but also have the values set correctly.

    I've been bouncing between two approaches, but not really certain which one is better.

    1) Eat the memory duplication cost and copy the data into the component values for each entity instantiated. So in your example the HealthComponent would have a MaxHealth that is read from the database and set at time of initialization. This should give you faster memory access when you need to read authored values like MaxHealth.

    2) Keep the authored static data as separate entities for read only lookup. Each instantiated entity would have a type reference, which is an EntityId. Then whenever you need to look up MaxHealth, you would need to use GetComponentDataFromEntity<Health>() and then index into that in the job with the type reference id.

    I would be interested to hear what approaches people have been using for this.