Browse Source

Merge remote-tracking branch 'origin/master'

master
Sebastiano Mandala 3 months ago
parent
commit
2d3cfe2cb4
1 changed files with 133 additions and 40 deletions
  1. +133
    -40
      README.md

+ 133
- 40
README.md View File

@@ -10,67 +10,160 @@ Svelto.ECS is easy to start with, but full of tricks for expert users. The harde
simplest setup:

```csharp
using System;
using Svelto.ECS;
using Svelto.ECS.Schedulers;
using Svelto.ECS.Vanilla.Example.SimpleEntityEngine;

/// <summary>
/// This is the common pattern to declare Svelto Exclusive Groups (usually split by composition root)
/// </summary>
public static class ExclusiveGroups
{
public static ExclusiveGroup group0 = new ExclusiveGroup();
public static ExclusiveGroup group1 = new ExclusiveGroup();
}

namespace Svelto.ECS.Vanilla.Example
{
/// <summary>
/// The Context is the application starting point.
/// As a Composition root, it gives to the coder the responsibility to create, initialize and
/// inject dependencies.
/// Every application can have more than one context and every context can have one
/// or more composition roots (a facade, but even a factory, can be a composition root)
/// </summary>
public class SimpleContext
{
//the group where the entity will be built in
public static ExclusiveGroup group0 = new ExclusiveGroup();

public SimpleContext()
{
var simpleSubmissionEntityViewScheduler = new SimpleEntitiesSubmissionScheduler();
//Build Svelto Entities and Engines container, called EnginesRoot
_enginesRoot = new EnginesRoot(simpleSubmissionEntityViewScheduler);

var entityFactory = _enginesRoot.GenerateEntityFactory();

//Add an Engine to the enginesRoot to manage the SimpleEntities
var behaviourForEntityClassEngine = new BehaviourForEntityClassEngine();
//an entity submission scheduler is needed to submit entities to the Svelto database, Svelto is not
//responsible to decide when to submit entities, it's the user's responsibility to do so.
var entitySubmissionScheduler = new SimpleEntitiesSubmissionScheduler();
//An EnginesRoot holds all the engines and entities created. it needs a EntitySubmissionScheduler to know when to
//add previously built entities to the Svelto database. Using the SimpleEntitiesSubmissionScheduler
//is expected as it gives complete control to the user about when the submission happens
_enginesRoot = new EnginesRoot(entitySubmissionScheduler);

//an entity factory allows to build entities inside engines
var entityFactory = _enginesRoot.GenerateEntityFactory();
//the entity functions allows other operations on entities, like remove and swap
var entityFunctions = _enginesRoot.GenerateEntityFunctions();

//Add the Engine to manage the SimpleEntities
var behaviourForEntityClassEngine = new BehaviourForEntityClassEngine(entityFunctions);
_enginesRoot.AddEngine(behaviourForEntityClassEngine);

//build a new Entity with ID 0 in group0
//build Entity with ID 0 in group0
entityFactory.BuildEntity<SimpleEntityDescriptor>(new EGID(0, ExclusiveGroups.group0));

//submit the previously built entities to the Svelto database
simpleSubmissionEntityViewScheduler.SubmitEntities();
entitySubmissionScheduler.SubmitEntities();

//as Svelto doesn't provide an engine ticking system, it's the user's responsibility to
//update engines
//as Svelto doesn't provide an engine/system ticking system, it's the user's responsibility to
//update engines
behaviourForEntityClassEngine.Update();

Console.Log("Done - click any button to quit");

System.Console.ReadKey();

Environment.Exit(0);
}
readonly EnginesRoot _enginesRoot;
}
```

your first entity descriptor:
readonly EnginesRoot _enginesRoot;
}

```csharp
//An EntityComponent must always implement the IEntityComponent interface
//don't worry, boxing/unboxing will never happen.
public struct EntityComponent : IEntityComponent
{
public int counter;
public int counter;
}

class SimpleEntityDescriptor : GenericEntityDescriptor<EntityComponent>
{}
```
your first engine executing entities behaviours:
/// <summary>
/// The EntityDescriptor identifies your Entity. It's essential to identify
/// your entities with a name that comes from the Game Design domain.
/// </summary>
class SimpleEntityDescriptor : GenericEntityDescriptor<EntityComponent> { }

```csharp
public class BehaviourForEntityClassEngine : IQueryingEntitiesEngine
namespace SimpleEntityEngine
{
public EntitiesDB entitiesDB { get; set; }

public void Ready() { }

public void Update()
public class BehaviourForEntityClassEngine :
//this interface makes the engine reactive, it's absolutely optional, you need to read my articles
//and wiki about it.
IReactOnAddEx<EntityComponent>, IReactOnSwapEx<EntityComponent>, IReactOnRemoveEx<EntityComponent>,
//while this interface is optional too, it's almost always used as it gives access to the entitiesDB
IQueryingEntitiesEngine
{
var (components, count) = entitiesDB.QueryEntities<EntityComponent>(ExclusiveGroups.group0);

for (var i = 0; i < count; i++)
components[i].counter++;
//extra entity functions
readonly IEntityFunctions _entityFunctions;

public BehaviourForEntityClassEngine(IEntityFunctions entityFunctions)
{
_entityFunctions = entityFunctions;
}

public EntitiesDB entitiesDB { get; set; }

public void Ready() { }

public void Update()
{
//Simple query to get all the entities with EntityComponent in group1
var (components, entityIDs, count) = entitiesDB.QueryEntities<EntityComponent>(ExclusiveGroups.group1);

uint entityID;
for (var i = 0; i < count; i++)
{
components[i].counter++;
entityID = entityIDs[i];
}

Console.Log("Entity Struct engine executed");
}

//the following methods are called by Svelto.ECS when an entity is added to a group
public void Add((uint start, uint end) rangeOfEntities, in EntityCollection<EntityComponent> entities
, ExclusiveGroupStruct groupID)
{
var (_, entityIDs, _) = entities;

for (uint index = rangeOfEntities.start; index < rangeOfEntities.end; index++)
//Swap entities between groups is a very common operation and it's necessary to
//move entities between groups/sets. A Group represent a state/adjective of an entity, so changing
//group means change state/behaviour as different engines will process different groups.
//it's the Svelto equivalent of adding/remove components to an entity at run time
_entityFunctions.SwapEntityGroup<SimpleEntityDescriptor>(new EGID(entityIDs[index], groupID), ExclusiveGroups.group1);
}

//the following methods are called by Svelto.ECS when an entity is swapped from a group to another
public void MovedTo((uint start, uint end) rangeOfEntities, in EntityCollection<EntityComponent> entities
, ExclusiveGroupStruct fromGroup, ExclusiveGroupStruct toGroup)
{
var (_, entityIDs, _) = entities;
for (var index = rangeOfEntities.start; index < rangeOfEntities.end; index++)
{
Console.Log($"entity {entityIDs[index]} moved from {fromGroup} to {toGroup}");
//like for the swap operation, removing entities from the Svelto database is a very common operation.
//For both operations is necessary to specify the EntityDescriptor to use. This has also a philosophical
//reason to happen, it's to always remind which entity type we are operating with.
_entityFunctions.RemoveEntity<SimpleEntityDescriptor>(new EGID(entityIDs[index], toGroup));
}
}

//the following methods are called by Svelto.ECS when an entity is removed from a group
public void Remove((uint start, uint end) rangeOfEntities, in EntityCollection<EntityComponent> entities, ExclusiveGroupStruct groupID)
{
var (_, entityIDs, _) = entities;

for (uint index = rangeOfEntities.start; index < rangeOfEntities.end; index++)
Console.Log($"entity {entityIDs[index]} removed from {groupID.ToString()}");
}
}
}
}
```

learn more about svelto on the Wiki page: https://github.com/sebas77/Svelto.ECS/wiki
@@ -100,10 +193,10 @@ _Svelto.ECS is lean. It hasn't been designed to move a whole engine such as Unit
Svelto.ECS is partially compatible with Unity 2019.3.x cycle as long as it's not used with any DOTS package (including collections). It is compatible with all the versions of Unity from 2020 and above.

### Svelto.ECS is fully compatible with DOTS Burst and Jobs.
Svelto.ECS is designed to take full advantange of the DOTS modules and to use specifically DOTS ECS as an engine library, through the (optional) SveltoOnDOTS wrapper.
Svelto.ECS is designed to take full advantange of the DOTS modules and to use specifically DOTS ECS as an engine library, through the (optional) SveltoOnDOTS wrapper. Svelto.ECS native components and interfaces are fully compatible with Burst.

## Why using Svelto.ECS without Unity?
There are so many c# game engines out there (Stride, Flax, Monogame, FlatRedBall, Evergine, UnrealCLR, UniEngine just to mention some) and Svelto.ECS is compatible with all of them!
There are so many c# game engines out there (Stride, Flax, Monogame, FlatRedBall, Evergine, Godot, UniEngine just to mention some) and Svelto.ECS is compatible with all of them!

## Performance considerations
Aside from resizing the database absolutely when necessary, all the Svelto operations are memory allocation free. Some containers may need to be preallocated (and then disposed) but those are already advanced scenarios. When using pure ECS (no EntityViewComponents) components are stored in native collections across all the platforms, which means gaining some performance from losing the managed memory checks. With pure ECS, iterating components is automatically cache-friendly.


Loading…
Cancel
Save