0
\$\begingroup\$

I'm currently designing a game engine and want to implement my own ECS implementation, so I decided to look around for ideas.

Unity has recently updated their engine and seems to be pushing towards using ECS, instead of their original components-are-systems design.

I noticed that Unity has a method called "GetEntities", a generic method which can do something like this:

public struct SomeComponent : IEntityComponent
{
    public string Message = "Hello, World!";
}

public struct Filter
{
    SomeComponent someComponent;
}

public MovementSystem : EntitySystem
{
    public override Process()
    {
        // How can I accomplish something like this?
        foreach(var entity in GetEntities<Filter>())
        {
            Console.WriteLine(entity.someComponent.Message);
        }
    }
}

I like this style of iterating over entities, given a filter for a specific component they need to include. But I'm not sure how to accomplish something like this.

If someone could shed some light on how something like this is even possible in C# that would be great!

\$\endgroup\$
  • 1
    \$\begingroup\$ Hi Mathew O'Dwyer, I've edited your question to ask how you can accomplish this feature, rather than about how Unity did it. This form tends to get more constructive answers, since the way a particular existing product did something might not be public knowledge, or it might not be the best way you can do it in your game. Answers explaining how Unity's implementation works are still on-topic, but so are suggestions for alternative solutions, so we can vote on the best answers out of all of them. \$\endgroup\$ – DMGregory Sep 9 '18 at 14:56
  • \$\begingroup\$ Sorry, what's ECS in this context? Google is failing \$\endgroup\$ – Paul Sep 9 '18 at 16:08
  • 1
    \$\begingroup\$ Entity component system, en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system \$\endgroup\$ – Mathew O'Dwyer Sep 9 '18 at 16:14
1
\$\begingroup\$

I'm a little rusty with C# but something like this might work:

public List<FilterType> GetEntities<FilterType>()
{
    // Assume all entities are valid
    List<Entity> entities = new List<Entity>(allEntities);
    var fields = FilterType.GetFields();
    foreach(var field in fields)
    {
        var componentType = field.FieldType;
        foreach(var entity in entities)
        {
            // Remove any invalid entities
            if(!entity.HasComponent(componentType))
                entities.Remove(entity);
        }
    }

    List<FilterType> filters = new List<FilterType>();
    foreach(var entity in entities)
    {
        FilterType filter = (FilterType) Activator.CreateInstance(FilterType);
        foreach(var field in fields)
            field.SetValue(filter, entity.GetComponent(field.FieldType));
        filters.Add(obj);
    }

    return filters;
}

This uses reflection to get the type of all (public!) fields in the struct/class FilterType and then checks if an entity does not have that component. In that case that entity is invalid and is removed from the final list result.

| improve this answer | |
\$\endgroup\$
  • \$\begingroup\$ Whilst this answer is surely helpful and has gotten me a little closer. The problem is your return type is a list of entities, whereas I wish for the return type to be the filter type :) \$\endgroup\$ – Mathew O'Dwyer Sep 9 '18 at 15:37
  • \$\begingroup\$ @MathewO'Dwyer Ah, so you mean that entity is not of type Entity but an instance of the Filter struct? If so give me a second I will edit the answer. \$\endgroup\$ – Charanor Sep 9 '18 at 15:41
  • \$\begingroup\$ Yes, exactly :) \$\endgroup\$ – Mathew O'Dwyer Sep 9 '18 at 15:43
  • \$\begingroup\$ @MathewO'Dwyer Edited. Not sure if that will work though since I cannot test it at the moment. \$\endgroup\$ – Charanor Sep 9 '18 at 15:51

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.