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\$
3
  • 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
    Commented Sep 9, 2018 at 14:56
  • \$\begingroup\$ Sorry, what's ECS in this context? Google is failing \$\endgroup\$
    – Paul
    Commented Sep 9, 2018 at 16:08
  • 1
    \$\begingroup\$ Entity component system, en.wikipedia.org/wiki/Entity%E2%80%93component%E2%80%93system \$\endgroup\$ Commented Sep 9, 2018 at 16:14

1 Answer 1

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.

\$\endgroup\$
4
  • \$\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\$ Commented Sep 9, 2018 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
    Commented Sep 9, 2018 at 15:41
  • \$\begingroup\$ Yes, exactly :) \$\endgroup\$ Commented Sep 9, 2018 at 15:43
  • \$\begingroup\$ @MathewO'Dwyer Edited. Not sure if that will work though since I cannot test it at the moment. \$\endgroup\$
    – Charanor
    Commented Sep 9, 2018 at 15:51

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .