Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Suggestion: Allow multiple components of the same type #56

Closed
Necromantic opened this issue Jan 16, 2016 · 11 comments
Closed

Suggestion: Allow multiple components of the same type #56

Necromantic opened this issue Jan 16, 2016 · 11 comments

Comments

@Necromantic
Copy link

Hey,

I've been looking into Entity Systems for a while and I've recently played around with Entitas.
One scenario I came across where Entitas is inappropriate is in any Application/Game that might play with multiple components of the same type on an Entity.

Let me give you an example:
Any kind of RPG or MOBA or other game that involves buffs or similar things.
For example you have a character and you give him multiple HealOverTime/HealthRegeneration components. The data they hold is just time between "ticks", time of last "tick", amount of "ticks" and how much they heal. They might vary in their data like the ticks left, the interval, the next time they will tick etc. so you can't combine them to just one component. They could all play together well with the same system and the same component structure. As far as I can tell Entitas does not support this thus far as it only allows one component of a given type to be present on any Entity. Even two Component of the same type with just varying start time and therefore just an offset in tick time and amounts left would require its own Component class and to be added to the group to be handled.

I've been starting to try to add this to Entitas myself but I've not yet had that much time to get it done in a way that works well with the code generation and just adding component list storages and adding methods for it is a big hacky. I think it would be based to adapt the system to this functionality from the core.

Is there already a way to solve this with Entitas that I might have missed? If not, do you plan to add this kind of functionality?
I do believe this would be a good feature that could apply to many possible game scenarios.

@Necromantic Necromantic changed the title [Feature] Multiple components of the same type Multiple components of the same type Jan 16, 2016
@Necromantic Necromantic changed the title Multiple components of the same type Suggestion: Allow multiple components of the same type Jan 16, 2016
@sschmid
Copy link
Owner

sschmid commented Jan 16, 2016

You are right, entities can only have one component per type. At the moment this behaviour is intended. I'll think about your suggestion next week if it might make sense to add sth like [AllowMultipleComponents].

For now, in order that you can continue, I'd suggest having a HealthRegeneration class which contains all needed information about start/end time/interval etc. Then create a HealthRegenerationsComponent(plural) which has a List.

e.AddHealthRegenerations(new List<HealthRegeneration>());

// later somewhere else in the code
var list = e.healthRegenerations.list;
list.Add(new HealthRegeneration(...));
e.ReplaceHealthRegenerations(list);

Hope that helps. I'll keep you updated

@Necromantic
Copy link
Author

Thanks for the response. I thought about multiple solutions and that was one of them, but to be honest that one kind of defeats the point of the entity system and would basically be a system in itself. You also couldn't use any of the group callbacks etc. when adding new components, you'd have to replace the whole component(with the list) just for changing one of its sub-components, which just doesn't feel right.

What I've done so far is make a [MultipleInstance] Attribute and basically duplicated the components array and all it's utility variables and methods like:

        readonly IComponent[] _components;
        readonly List<IComponent>[] _componentLists;

I even went so far to check for that attribute on code generation.
But because everything is kind of duplicated with list behaviours you'd also have to separate component index, type and name lists etc. in order to not clutter the different arrays with empty references that would only ever be filled in the other.
So at some point it feels like the only good and clean solution would be to build it into the system from the ground off.

I'm not really working on a specific project right now so it's nothing I need urgently, it's just something I noticed when trying to implement an old attribute/skill system based on a (really simplistic) entity system of my own with Entitas.
I just thought it would be an interesting feature for more applications and that it might be interesting to have it as part of Entitas.
If I find a good solution myself I'll let you know.or possibly create a fork.

@sschmid
Copy link
Owner

sschmid commented Jan 18, 2016

I was thinking a little bit about it now. I'm not sure if it's a good idea to allow multiple components. It will add quite some complexity I think. For instance, what does entity.RemovePosition(); mean when you have multiple positions? You'd have to also manage indices like entity.RemovePosition(3);

I think with the given example of the health regenerators it's better to sth like I just mentioned before.

e.AddHealthRegenerations(new List<HealthRegeneration>());

The good thing is, when you do sth like

var list = e.healthRegenerations.list;
list.Add(new HealthRegeneration(...));
e.ReplaceHealthRegenerations(list);

Entitas is smart enough not to change any data structures under the hood. You'll reuse the some instance of the list over and over again, so there will be no overhead. e.ReplaceHealthRegenerations(list); will also not change groups but only dispatch event, so it's efficient, too.

@SvDvorak
Copy link

I've also given this idea some thought and come to the same conclusion, it'll make the API more confusing while only giving you a bit more granular notifications. And you can wrap the code sschmid wrote in an extension so that you'd only have to write

e.AddHealthGeneration(index, new HealthGeneration(...))
e.ReplaceHealthGeneration(index, new HealthGeneration(...))
e.RemoveHealthGeneration(index)

If you absolutely had to only update a single HealthGeneration then you're still stuck with writing some more code to compare the previous and new list but I'd say this is more an exception rather than a rule.

@Necromantic
Copy link
Author

I don't see how it would make the API that much more confusing just by allowing more of the same component type. It would give a lot more possibilities and opens up more elaborate game design.

Having to manage Lists of "components" in a component kind of defeats the point of an Entity System and only data being in components. What's in the Lists would be the components, not the components themselves and those wouldn't play along well with any of the rest of the system.
You'd also end up with old list contents unless you clear them every time you remove and cache a component else you end up with a whole lot. And if you want to cache those actual embedded components in the list you'd have to build your own cache and your own reactive system.
What's important is the single components in the list, not the whole list of them. For adding you only want those actually added etc.
One-to-many relationships (which are pretty common) are just not feasible that way.

Oh well, guess I'll have to go back to my own implementations. Thanks for considering it anyway.

@hypernewbie
Copy link

hypernewbie commented May 10, 2020

The discussion here neatly sums up the difference between the people making tools for theoretical games in a theoretical world of ideal philosophies vs the people actually trying to make physical games in the real world with physical teams of real people.

@sschmid
Copy link
Owner

sschmid commented May 10, 2020

Haha ;) Entitas came to live because of real games and real problems. Nothing theoretical about it.

@ghost
Copy link

ghost commented May 10, 2020

The discussion here neatly sums up the difference between the people making tools for theoretical games in a theoretical world of ideal philosophies vs the people actually trying to make physical games in the real world with physical teams of real people.

Bullshit.
I have been working with Entitas for years on professional projects with different team sizes. I can assure you that Entitas was created through practical work with ECS. Creating a list of components with a 1..* relation is incredibly easy in the ECS universe:
(pseudo)

EntityA
    IdComponent(for example Int = 3) with [PrimaryEntityIndex]
EntityB
    ParentComponent (with Int = 3 pointing to EntityA) with [EntityIndex]
    SomeValueComponent
EntityC
    ParentComponent (with Int = 3 pointing to EntityA) with [EntityIndex]
    SomeValueComponent

SomeSystem
    Execute()
    var entities = context.GetEntitiesWithParent(entityA.id);
    foreach(entities) DoSomething(entity.someValue)

This procedure also applies in other ECS environments. Not only Entitas and is one of the fundamental principles of understanding ECS. Necromantic and some others here in the issue have not, in my opinion, understood the basics.

@sschmid
Copy link
Owner

sschmid commented May 10, 2020

It's a good and valid question and something you will likely encounter when starting with ECS. Lets focus on developing and sharing solutions, please.

@ghost
Copy link

ghost commented May 10, 2020

Wasn't meant to be offensive. I understand that this question comes up frequently, but to call the design theoretical without any proof is a bit provocative and degrading 😬

@JesseTG
Copy link

JesseTG commented May 10, 2020

I've never had the need to give an entity multiple instances of the same component. I guess if I decided that was the best option, I'd either give said component a collection or I'd just split it into multiple smaller entities as @StormRene suggested.

I do have a prefab with two instances of the same MonoBehaviour, but that's to simplify integrating parts of my game's UI with a particular library. Not really pertinent to Entitas, though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
Archived in project
Development

No branches or pull requests

5 participants