Skip to content

Commit

Permalink
Merge pull request #164 from stride3d/master
Browse files Browse the repository at this point in the history
Testing recent updates in staging.
  • Loading branch information
VaclavElias authored Oct 9, 2023
2 parents 91e28b2 + fb73d1c commit 876559f
Show file tree
Hide file tree
Showing 5 changed files with 161 additions and 25 deletions.
53 changes: 31 additions & 22 deletions en/manual/engine/entity-component-model/index.md
Original file line number Diff line number Diff line change
@@ -1,38 +1,47 @@
# Entity-Component Model
# ECS (Entity Component System) Introduction

[!INCLUDE [stride-studio-note](../../../includes/under-construction-note.md)]
# Problem
> `Dog` is a subclasses of `Animal`.
# Overview
This example is often used as an example of inheritance
in introductions to programming. However, when things get more complex,
we get problems:
- `Dog` and `Fish` can swim, so we create `SwimmingAnimal` as a class in between
- `Bee` and `Bird` can fly, so we create `FlyingAnimal`
- What do we now do with the `Duck`, who can do both?

@'Stride.Engine.Entity' is the base class for objects that are managed by the high-level engine.
We have the exact same problem in video games.
Enemies can walk, shoot, fly - but not all of them can do everything.
Even something basic like hitpoints is not universal, as some enemies are indestructible.

To improve flexibility, entity are component-based: they can contains as many components as required, containing data and/or logic.
# Solution


> Entity component system (ECS) is a software architectural pattern mostly used in video game development for the representation of game world objects. An ECS comprises entities composed from components of data, with systems which operate on entities' components.
> _-[Wikipedia](https://en.wikipedia.org/wiki/Entity_component_system)_

![media/7438980.png](media/7438980.png)
The general idea of an ECS is that an _entity_ - an "object" in your virtual world -
does not really do anything. It is mostly just a "bag of components".

The selection of components on an entity decides what it does.
An entity with a collider component can collide, an entity with a sound component can make a noise, etc.

## Differing opinions

For the "System" part of the term, there are two interpretations:

A @'Stride.Engine.Entitycomponent' is tied to its entity (that is, one component can't be added to two entities at the same time).
A) "Entity-and-Component System"
...in which the components contain the data they need, and also the functionality that works with that data.

# How to create an entity and some components
B) "Entity, Component, System"
...in which a component only contains data, while a third part - the system -
contains the functionality.

```cs
// Create entity
var myEntity = new Entity();

// Create a model component (so that model is rendered)
var modelComponent = new ModelComponent { Model = model };
myEntity.Set(ModelComponent.Key, modelComponent);

// Set entity position
myEntity.Transformation.Translation = new Vector3(100.0f, 100.0f, 0.0f);

// Add entity to scene; from now on its model will be rendered
Entities.Add(myEntity);
```
Stride allows working in both ways. A) can be achieved by using
[scripts](https://doc.stride3d.net/latest/en/manual/scripts/index.html)
while the usage of B) is described in this section of the manual.

### Which one to choose?

![media/ecs-choice.jpg](media/ecs-choice.jpg)
3 changes: 0 additions & 3 deletions en/manual/engine/entity-component-model/media/7438980.png

This file was deleted.

3 changes: 3 additions & 0 deletions en/manual/engine/entity-component-model/media/ecs-choice.jpg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
126 changes: 126 additions & 0 deletions en/manual/engine/entity-component-model/usage.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# ECS Usage

## Classes

The three parts of "Entity Component System" map to the following classes:

- Entity - [`Stride.Engine.Entity`](https://doc.stride3d.net/latest/en/api/Stride.Engine.Entity.html)
- Component - [`Stride.Engine.EntityComponent`](https://doc.stride3d.net/latest/en/api/Stride.Engine.EntityComponent.html)
- System - [`Stride.Engine.EntityProcessor`](https://doc.stride3d.net/latest/en/api/Stride.Engine.EntityProcessor.html)


## Minimal Setup

A component can be defined by deriving a class from `EntityComponent`.

By adding the attribute `DefaultEntityComponentProcessor` to an `EntityComponent`,
an `EntityProcessor` can be assigned to it. This will automatically set up and run
the `EntityProcessor` if the `EntityComponent` is in the scene.

An `EntityComponent` also needs to indicate that it can be serialized
by adding the attribute `DataContract` to it.

A system can be defined by deriving a class from `EntityProcessor`.


### Code

#### Component
```csharp
[DataContract(nameof(MyComponent))]
[DefaultEntityComponentProcessor(typeof(MyProcessor))]
public class MyComponent : EntityComponent
{
public int MyValue { get; set; }
}
```

#### System
```csharp
public class MyProcessor : EntityProcessor<MyComponent>
{
public override void Update(GameTime time)
{
foreach (var myComponent in ComponentDatas.Values)
{
Console.WriteLine($"myComponent with value {myComponent.MyValue} at {time.Total.TotalSeconds}");
}
}
}
```

### Additional Note
An `EntityComponent` can currently not be drag-dropped onto an entity in Game Studio.
It has to be added by selecting an entity, and then clicking the "Add component" button
in the property grid.

Alternatively, this can also be done in [code via `entity.Add(entityComponent)`](https://doc.stride3d.net/latest/en/api/Stride.Engine.Entity.html#Stride_Engine_Entity_Add_Stride_Engine_EntityComponent_).


## Advanced Features

### More Component Attributes

#### Display
By adding the `Display` attribute, a nicer name can be shown in Game Studio.
```csharp
[Display("My better name")]
```

#### ComponentCategory
By default, your components will be listed in the category "Miscellaneous".
By adding the `ComponentCategory` attribute, a different category can be chosen.
If the chosen name does not exist yet, it will be added to the list in Game Studio.
```csharp
[ComponentCategory("My own components")]
```

#### ComponentOrder
By adding the `ComponentOrder` attribute, the order in which
components are listed in Game Studio can be changed.
```csharp
[ComponentOrder(2001)]
```


### Component Combinations
By passing the types of other components to the `EntityProcessor` constructor,
it will only include entities _that also have those other components_.

For example, the following `EntityProcessor` is for `MyComponent`, but will skip any entity
that does not also have both `TransformComponent` and `AnimationComponent` on it.

```csharp
public class MyProcessor : EntityProcessor<MyComponent>
{
public MyProcessor() : base(typeof(TransformComponent), typeof(AnimationComponent))
{
}
}
```


### Non-default Processors
Adding processors for a type of component via the attribute `DefaultEntityComponentProcessor`
has been explained above. However, as the name implies, this is for the _default_ processor.
Non-default processors can also be added via
```csharp
SceneSystem.SceneInstance.Processors.Add(entityProcessor);
```


### Separation of EntityComponent and Data

`EntityProcessor<TComponent>` is a shortcut for `EntityProcessor<TComponent, TComponent>`.

By explicitly using `EntityProcessor<TComponent, TData>` instead, a different type can be chosen
for the actual data. This way, the `EntityComponent` can e.g. have "heavier" startup data and
references, while the data object that needs to be processed every frame can be kept small.

This will require overriding a method `GenerateComponentData`, which produces a `TData` instance
from a `TComponent` instance.

### Overrides
`EntityProcessor` also provides several methods which can be overridden in order to react to certain events.
They are not overly complicated, so that their usage should be clear from their doc comments.

1 change: 1 addition & 0 deletions en/manual/toc.md
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
### [Asset bundles](engine/assets/asset-bundles.md)
### [Asset control](engine/assets/asset-control.md)
## [Entity component model](engine/entity-component-model/index.md)
### [Usage](engine/entity-component-model/usage.md)
### [Manage entities](engine/entity-component-model/managing-entities.md)
## [File system](engine/file-system.md)

Expand Down

0 comments on commit 876559f

Please sign in to comment.