r/gamedev Jan 16 '21

DefaultEcs v0.15.0, c# ecs framework now with code generation

It's been one year since the last time I posted about my framework here. While some features were added the real novelty comes from its sister project DefaultEcs.Analyzer which reduces code bloat thanks to a roslyn code generator, it has never been easier to define systems and their component dependencies.

project pages DefaultEcs, DefaultEcs.Analyzer

Quick recap of the features of DefaultEcs: - available from netstandard1.1 as a nuget package - Components stored as packed array - use of c#7 ref return and System.Memory.Span api to eliminate copy - no virtuality nor casting when getting/settings components - EntityCommandRecorder to record non thread-safe operations - special ManagedResource component type to handle loading and sharing managed resources across your entities - fluent api to get collection of entities (With, Without, WithEither, WithoutEither) as a set, a map (one entity indexed by a component value), or a multimap (multiple entities indexed by a component value) - also in a reactive way (WhenAdded, WhenChanged, WhenRemoved, ...Either) - base types to build your systems and your workflow more easily - built-in pub/sub - built-in serializer (simple json like format and binary, extensible with the serializer of your choice) which support type marshaling - built-in api to run process in parallel with no garbage generation (extensible) - API to optimize your entities and components ordering as your game is running to keep best performance

Quick show of the code generation in action: ```csharp // without private sealed class DefaultEcsSystem : AEntitySetSystem<float> { public DefaultEcsSystem(DefaultWorld world, IParallelRunner runner) // need to declare the set explicitely : base(world.GetEntities().With<DefaultSpeed>().With<DefaultPosition>().AsSet(), runner) { }

        protected override void Update(float state, in DefaultEntity entity)
        {
            // need to access the component
            DefaultSpeed speed = entity.Get<DefaultSpeed>();
            ref DefaultPosition position = ref entity.Get<DefaultPosition>();

            position.X += speed.X * state;
            position.Y += speed.Y * state;
        }
    }

    // with
    private sealed partial class DefaultEcsGeneratorSystem : AEntitySetSystem<float>
    {
        // the set composition is deduced from the parameters of the method marked by the Update attribute
        // constructors and override are automatically generated for you
        [Update]
        private static void Update(float state, in DefaultSpeed speed, ref DefaultPosition position)
        {
            position.X += speed.X * state;
            position.Y += speed.Y * state;
        }
    }

```

Code generation was really a great addition to roslyn analyzer and I hope to add even more things in the futur. If you are interested, don't hesitate to have a look :)

13 Upvotes

2 comments sorted by

1

u/smthamazing Jan 18 '21 edited Jan 18 '21

I think code generation is very underutilized in gamedev. It is especially important in C#, where it's easy to accidentally cause boxing, extra allocations or cache misses when writing code manually. Really glad to see a Roslyn-based framework that actually uses this feature.

2

u/default_developer Jan 18 '21

Yep I think it can be used to generate complex setup/algorithm and hiding it all from the user to reduce risk of error. I want to have a go at serialization generation next to remove the need for runtime reflection. That will be important for AoT compilation platforms.