From 01609cc7619d0dfa4157879d061d678f639a6416 Mon Sep 17 00:00:00 2001 From: GPU-Fried-Eggs Date: Wed, 20 Mar 2024 22:56:21 +0200 Subject: [PATCH 1/2] doc: add more doc details for the package --- README.md | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/README.md b/README.md index 16ac3fc..2aab9cc 100644 --- a/README.md +++ b/README.md @@ -4,6 +4,143 @@ Modern ECS framework for .NET +## Get started + +```console +dotnet add package Sia +``` + +The package uses [Roslyn Source Generators](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview). +Because of this, you should use an IDE that's compatible with source generators. Previous IDE versions might experience +slow-downs or mark valid code as errors. The following IDEs are compatible with source generators: + +- Visual Studio 2022+ +- Rider 2021.3.3+ +- ~~Visual Studio Code (preview LPS)~~ + +## Components overview + +Components represent the data in the Entity Component System (ECS) architecture. + +### Add components to an entity + +To add components to an entity, we provided multiple approachs for different scenario. + +```csharp +public static EntityRef> CreateInBucketHost< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TEntity>( + this World world, in TEntity initial, int bucketCapacity = 256) + where TEntity : struct +``` + +```csharp +public static EntityRef> CreateInHashHost< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TEntity>( + this World world, in TEntity initial) + where TEntity : struct +``` + +```csharp +public static EntityRef> CreateInArrayHost< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TEntity>( + this World world, in TEntity initial, int initialCapacity = 0) + where TEntity : struct +``` + +```csharp +public static EntityRef> CreateInSparseHost< + [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TEntity>( + this World world, in TEntity initial, int pageSize = 256) + where TEntity : struct +``` + +### Remove components from an entity + +The `EntityRef` is a class inherit from `IDisposable` interface. We can call `Dispose` to release the entity from the +world. + +### Read and write component values of entities + +TODO: I don't known about trigger related. + +## Systems overview + +### Introduction to systems + +We can register system to `world` in two approach: + +1. use method `RegisterTo` to `SystemChain`: + ```csharp + SystemChain.Empty.Add().RegisterTo(world, scheduler); + ``` + +2. use register api in `World`: + ```csharp + world.RegisterSystem(scheduler); + ``` + +#### The core of System: ISystem + +```csharp +public interface ISystem +{ + SystemChain? Children { get; } + IEntityMatcher? Matcher { get; } + IEventUnion? Trigger { get; } + IEventUnion? Filter { get; } + + void Initialize(World world, Scheduler scheduler); + void Uninitialize(World world, Scheduler scheduler); + void Execute(World world, Scheduler scheduler, IEntityQuery query); +} +``` + +#### Using SystemBase + +TODO: Trigger, children, Match, Filter + +#### Using ParallelSystemBase + +This system is a wrapper for `SystemBase` + +### Iterate over component data + +Iterating over data is one of the most common tasks you need to perform when you create a system. A system typically +processes a set of entities, reads data from one or more components, performs a calculation, and then writes the result +to another component. + +1. Use `Enumerator` for `query` each entity: + ```csharp + public class System : SystemBase + { + public override void Execute(World world, Scheduler scheduler, IEntityQuery query) + { + foreach (var entity in query) { + // Process each entity. + } + } + } + ``` + +2. Use `lambda` style for `query` either component or entity: + ```csharp + public class System : SystemBase + { + public override void Execute(World world, Scheduler scheduler, IEntityQuery query) + { + query.ForEach((ref T component) => { + // process each component. + }); + query.ForSliceOnParallel((ref T component) => { + // process each component. + }); + query.ForEach(entity => { + // process each entity. + }); + } + } + ``` + ## Example ```C# From f47ea13bbeb91c3ef3d188552522fb74cd723afb Mon Sep 17 00:00:00 2001 From: Valtameri Sieluna Date: Fri, 14 Jun 2024 22:34:37 +0300 Subject: [PATCH 2/2] Add more details and improve description --- README.md | 86 ++++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index 755b6d2..4c17800 100644 --- a/README.md +++ b/README.md @@ -6,17 +6,28 @@ Modern ECS framework for .NET ## Get started +To begin, you need to install the core package of the Sia Framework. Open your terminal and run the following command: + ```console dotnet add package Sia ``` -The package uses [Roslyn Source Generators](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview). +This package contains the core features of the Sia framework. + +If you would like to use the `source generation` features such as `template`, `view`, etc., you can install +the `Sia.CodeGenerators` package. + +```console +dotnet add package Sia.CodeGenerators +``` + +> [!NOTE] +> The package uses [Roslyn Source Generators](https://docs.microsoft.com/en-us/dotnet/csharp/roslyn-sdk/source-generators-overview). Because of this, you should use an IDE that's compatible with source generators. Previous IDE versions might experience slow-downs or mark valid code as errors. The following IDEs are compatible with source generators: - -- Visual Studio 2022+ -- Rider 2021.3.3+ -- ~~Visual Studio Code (preview LPS)~~ +> - Visual Studio 2022+ +> - Rider 2021.3.3+ +> - Visual Studio Code ## Components overview @@ -33,6 +44,9 @@ public static EntityRef> CreateInBucketHost< where TEntity : struct ``` +The `BucketHost`, using a list of buckets (`List`), is ideal for scenarios with large datasets that require +moderately sparse allocations. + ```csharp public static EntityRef> CreateInHashHost< [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TEntity>( @@ -40,6 +54,8 @@ public static EntityRef> CreateInHashHost< where TEntity : struct ``` +The `HashHost`, utilizing a dictionary (`Dictionary`), is perfect for highly sparse and unpredictable datasets. + ```csharp public static EntityRef> CreateInArrayHost< [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TEntity>( @@ -47,6 +63,8 @@ public static EntityRef> CreateInArrayHost< where TEntity : struct ``` +The `ArrayHost`, employing a array (`T[]`), is suitable for simple, contiguous data storage needs with predictable growth. + ```csharp public static EntityRef> CreateInSparseHost< [DynamicallyAccessedMembers(DynamicallyAccessedMemberTypes.All)] TEntity>( @@ -54,14 +72,18 @@ public static EntityRef> CreateInSparseHost< where TEntity : struct ``` +The `SparseHost`, using a sparse set (`SparseSet`), is optimized for extremely sparse datasets, where memory +efficiency is crucial. + ### Remove components from an entity -The `EntityRef` is a class inherit from `IDisposable` interface. We can call `Dispose` to release the entity from the -world. +The `EntityRef` is a class inherit from `IDisposable` interface. We can either call `Dispose` or just use `unsing` +keyword to release the entity from the world. ### Read and write component values of entities -TODO: I don't known about trigger related. +You can handle the entity by `Get` function easily, it will return a `ref` component type. You can update the value +directly. ## Systems overview @@ -69,18 +91,25 @@ TODO: I don't known about trigger related. We can register system to `world` in two approach: -1. use method `RegisterTo` to `SystemChain`: +1. using the `RegisterTo` method in a `SystemChain`: ```csharp SystemChain.Empty.Add().RegisterTo(world, scheduler); ``` + system can also be registered by a lambda expression as well: + ```csharp + SystemChain.Empty.Add((ref object _) => {}).RegisterTo(world, scheduler); + ``` -2. use register api in `World`: +3. using the register api in `World`: ```csharp world.RegisterSystem(scheduler); ``` #### The core of System: ISystem +When creating a custom system, you can either inherit from interface or create from System action wrapper. You need +to review all properties and functions in the `ISystem` interface + ```csharp public interface ISystem { @@ -95,13 +124,42 @@ public interface ISystem } ``` -#### Using SystemBase +1. When you inherit from `SystemBase`, `ParallelSystemBase` and etc. you can build your system as follows: -TODO: Trigger, children, Match, Filter +```csharp +public class MySystem(SystemChain next) : SystemBase( + matcher: Matchers.Of(), + trigger: EventUnion.Of(), + filter: EventUnion.Of>(), + children: next) +{ + public override void Initialize(World world, Scheduler scheduler) + { + // The logic When system is initialzed + } + public override void Uninitialize(World world, Scheduler scheduler) + { + // The logic When system un initialzed + } + public override void Execute(World world, Scheduler scheduler, IEntityQuery query) + { + // The logic When system is triggered + } +} +``` -#### Using ParallelSystemBase +2. The lambda style code: -This system is a wrapper for `SystemBase` +```csharp +var system = (ref object obj) => { + // The logic When system is triggered +}; + +var chain = SystemChain.Empty.Add(system, + matcher: Matchers.Of(), + trigger: EventUnion.Of(), + filter: EventUnion.Of>()); +``` ### Iterate over component data