sschmid / Entitas

Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity
MIT License
7.18k stars 1.11k forks source link

Add TryGet to entities code generator to get components #1046

Open pereviader-popcore opened 2 years ago

pereviader-popcore commented 2 years ago

Is your feature request related to a problem? Please describe. Internally the entity.potato calls entity.hasPotato , so this would make it a tad faster by avoiding some branching and getting the component directly.

Describe the solution you'd like From:

if(entity.hasPotato)
{
   var potato = entity.potato;
   ...
}

To:

if(entity.TryGetPotato(out var potato))
{
    ...
}
sschmid commented 1 year ago

Hi! I'm thinking of this:

namespace MyFeature
{
    [Context(typeof(MainContext))]
    public sealed class PositionComponent : IComponent
    {
        public int X;
        public int Y;
    }
}

Will result in:

namespace MyFeature
{
    public static class MyAppMainPositionEntityExtension
    {
        public static Entity SetPosition(this Entity entity, int x, int y)
        {
            var index = Index.Value;
            var componentPool = entity.GetComponentPool(index);
            var component = componentPool.Count > 0
                ? (PositionComponent)componentPool.Pop()
                : new PositionComponent();
            component.X = x;
            component.Y = y;
            entity.ReplaceComponent(index, component);
            return entity;
        }

        public static Entity UnsetPosition(this Entity entity)
        {
            if (entity.HasComponent(Index.Value))
                entity.RemoveComponent(Index.Value);

            return entity;
        }

        public static PositionComponent? GetPosition(this Entity entity)
        {
            return entity.HasComponent(Index.Value)
                ? (PositionComponent)entity.GetComponent(Index.Value)
                : null;
        }
    }
}

Checking if an entity has a component could look like this:

if (entity.GetPosition() is { X: 10, Y: > 0 })
{
    // ...
}
sschmid commented 1 year ago

The first step would be just changes in the generated code which doesn't require any api changes in Entitas. Next step would be to move Entitas itself to nullables, which will get rid of the HasComponent check in GetPosition()

sschmid commented 1 year ago

New C# syntax might look weird, but it's essentially a TryGet :D

if (entity.GetPosition() is { } position)
{
    // position.X ... 
}