mirror of
https://github.com/DCFApixels/DragonECS.git
synced 2025-09-18 18:14:37 +08:00
Merge branch 'main' into dev
This commit is contained in:
commit
b893291090
@ -308,7 +308,7 @@ EcsPipeline pipeline = EcsPipeline.New()
|
|||||||
|
|
||||||
Для добавления нового процесса создайте интерфейс наследованный от `IEcsProcess` и создайте раннер для него. Раннер это класс реализующий интерфейс запускаемого процесса и наследуемый от `EcsRunner<TInterface>`. Пример:
|
Для добавления нового процесса создайте интерфейс наследованный от `IEcsProcess` и создайте раннер для него. Раннер это класс реализующий интерфейс запускаемого процесса и наследуемый от `EcsRunner<TInterface>`. Пример:
|
||||||
``` c#
|
``` c#
|
||||||
// Интерфейс.
|
// Интерфейс процесса.
|
||||||
interface IDoSomethingProcess : IEcsProcess
|
interface IDoSomethingProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Do();
|
void Do();
|
||||||
@ -448,7 +448,6 @@ class Aspect : EcsAspect
|
|||||||
public OtherAspect2 otherAspect2;
|
public OtherAspect2 otherAspect2;
|
||||||
public EcsPool<Pose> poses;
|
public EcsPool<Pose> poses;
|
||||||
|
|
||||||
// Функция Init аналогична конструктору Aspect(Builder b).
|
|
||||||
protected override void Init(Builder b)
|
protected override void Init(Builder b)
|
||||||
{
|
{
|
||||||
// Комбинирует с SomeAspect1.
|
// Комбинирует с SomeAspect1.
|
||||||
|
45
README-ZH.md
45
README-ZH.md
@ -65,7 +65,7 @@ DragonECS 是一个[实体组件系统](https://www.imooc.com/article/331544)框
|
|||||||
- [方面](#方面)
|
- [方面](#方面)
|
||||||
- [查询](#查询)
|
- [查询](#查询)
|
||||||
- [集合](#集合)
|
- [集合](#集合)
|
||||||
- [根本](#根本)
|
- [ECS入口](#ECS入口)
|
||||||
- [Debug](#debug)
|
- [Debug](#debug)
|
||||||
- [元属性](#元属性)
|
- [元属性](#元属性)
|
||||||
- [EcsDebug](#ecsdebug)
|
- [EcsDebug](#ecsdebug)
|
||||||
@ -308,12 +308,12 @@ EcsPipeline pipeline = EcsPipeline.New()
|
|||||||
|
|
||||||
Для добавления нового процесса создайте интерфейс наследованный от `IEcsProcess` и создайте раннер для него. Раннер это класс реализующий интерфейс запускаемого процесса и наследуемый от `EcsRunner<TInterface>`. Пример:
|
Для добавления нового процесса создайте интерфейс наследованный от `IEcsProcess` и создайте раннер для него. Раннер это класс реализующий интерфейс запускаемого процесса и наследуемый от `EcsRunner<TInterface>`. Пример:
|
||||||
``` c#
|
``` c#
|
||||||
//Интерфейс.
|
// 流程接口。
|
||||||
interface IDoSomethingProcess : IEcsProcess
|
interface IDoSomethingProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Do();
|
void Do();
|
||||||
}
|
}
|
||||||
//Реализация раннера. Пример реализации можно так же посмотреть в встроенных процессах
|
// 启动器实现. 也可以在内置的流程中参考实现示例。
|
||||||
sealed class DoSomethingProcessRunner : EcsRunner<IDoSomethingProcess>, IDoSomethingProcess
|
sealed class DoSomethingProcessRunner : EcsRunner<IDoSomethingProcess>, IDoSomethingProcess
|
||||||
{
|
{
|
||||||
public void Do()
|
public void Do()
|
||||||
@ -323,25 +323,25 @@ sealed class DoSomethingProcessRunner : EcsRunner<IDoSomethingProcess>, IDoSomet
|
|||||||
}
|
}
|
||||||
//...
|
//...
|
||||||
|
|
||||||
//Добавление раннера при создании пайплайна.
|
// 添加启动器到管线
|
||||||
_pipeline = EcsPipeline.New()
|
_pipeline = EcsPipeline.New()
|
||||||
//...
|
//...
|
||||||
.AddRunner<DoSomethingProcessRunner>()
|
.AddRunner<DoSomethingProcessRunner>()
|
||||||
//...
|
//...
|
||||||
.BuildAndInit();
|
.BuildAndInit();
|
||||||
|
|
||||||
//Запуск раннера если раннер был добавлен.
|
// 如果启动器已经添加,运行它。
|
||||||
_pipeline.GetRunner<IDoSomethingProcess>.Do()
|
_pipeline.GetRunner<IDoSomethingProcess>.Do()
|
||||||
|
|
||||||
//Или если раннер не был добавлен(Вызов GetRunnerInstance так же добавит раннер в пайплайн).
|
// 如果启动器尚未添加,使用 GetRunnerInstance 将其添加并运行
|
||||||
_pipeline.GetRunnerInstance<DoSomethingProcessRunner>.Do()
|
_pipeline.GetRunnerInstance<DoSomethingProcessRunner>.Do()
|
||||||
```
|
```
|
||||||
> Раннеры имеют ряд требований к реализации:
|
> 启动器的实现有一些要求:
|
||||||
> * Наследоваться от `EcsRunner<T>` можно только напрямую;
|
> * 必须直接继承自 `EcsRunner<T>`;
|
||||||
> * Раннер может содержать только один интерфейс(за исключением `IEcsProcess`);
|
> * 启动器只能包含一个接口(除了 `IEcsProcess` 接口);
|
||||||
> * Наследуемый класс `EcsRunner<T>,` должен так же реализовать интерфейс `T`;
|
> * 继承的 `EcsRunner<T>,` 类必须实现接口 `T`;
|
||||||
|
|
||||||
> Не рекомендуется в цикле вызывать `GetRunner`, иначе кешируйте полученный раннер.
|
不建议在循环中频繁调用 `GetRunner` 方法,建议缓存获取的启动器实例。
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## 世界
|
## 世界
|
||||||
@ -438,7 +438,7 @@ class Aspect : EcsAspect
|
|||||||
<details>
|
<details>
|
||||||
<summary>结合方面</summary>
|
<summary>结合方面</summary>
|
||||||
|
|
||||||
В аспекты можно добавлять другие аспекты, тем самым комбинируя их. Ограничения так же будут скомбинированы.
|
可以把一个方面加入另一个方面,从而组合它们。限制也会被组合
|
||||||
``` c#
|
``` c#
|
||||||
using DCFApixels.DragonECS;
|
using DCFApixels.DragonECS;
|
||||||
...
|
...
|
||||||
@ -448,25 +448,24 @@ class Aspect : EcsAspect
|
|||||||
public OtherAspect2 otherAspect2;
|
public OtherAspect2 otherAspect2;
|
||||||
public EcsPool<Pose> poses;
|
public EcsPool<Pose> poses;
|
||||||
|
|
||||||
// функция Init аналогична конструктору Aspect(Builder b)
|
|
||||||
protected override void Init(Builder b)
|
protected override void Init(Builder b)
|
||||||
{
|
{
|
||||||
// комбинирует с SomeAspect1.
|
// 与 SomeAspect1 进行组合。
|
||||||
otherAspect1 = b.Combine<OtherAspect1>(1);
|
otherAspect1 = b.Combine<OtherAspect1>(1);
|
||||||
// хотя для OtherAspect1 метод Combine был вызван раньше, сначала будет скомбинирован с OtherAspect2, так как по умолчанию order = 0.
|
// 即使对 OtherAspect1 调用 Combine 方法更早,Aspect 会首先与 OtherAspect2 进行组合,因为默认情况下 order = 0。
|
||||||
otherAspect2 = b.Combine<OtherAspect2>();
|
otherAspect2 = b.Combine<OtherAspect2>();
|
||||||
// если в OtherAspect1 или в OtherAspect2 было ограничение b.Exclude<Pose>() тут оно будет заменено на b.Include<Pose>().
|
// 如果 OtherAspect1 或 OtherAspect2 中有 b.Exclude<Pose>() 的限制条件,这里将被替换为 b.Include<Pose>()。
|
||||||
poses = b.Include<Pose>();
|
poses = b.Include<Pose>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Если будут конфликтующие ограничения у комбинируемых аспектов, то новые ограничения будут заменять добавленные ранее. Ограничения корневого аспекта всегда заменяют ограничения из добавленных аспектов. Визуальный пример комбинации ограничений:
|
如果组合的方面存在冲突的限制条件,则新的限制条件将替换先前添加的限制条件。根方面的限制条件始终会替换添加的方面中的限制条件。限制条件组合的视觉示例:
|
||||||
| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | разрешение конфликтных ограничений|
|
| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | разрешение конфликтных ограничений|
|
||||||
| :--- | :--- | :--- | :--- | :--- | :--- |:--- |
|
| :--- | :--- | :--- | :--- | :--- | :--- |:--- |
|
||||||
| OtherAspect2 | :heavy_check_mark: | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | |
|
| OtherAspect2 | :heavy_check_mark: | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | |
|
||||||
| OtherAspect1 | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_minus_sign: | Для `cmp2` будет выбрано :heavy_check_mark: |
|
| OtherAspect1 | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_minus_sign: | 对于 `cmp2` 将选择 :heavy_check_mark: |
|
||||||
| Aspect | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | Для `cmp1` будет выбрано :x: |
|
| Aspect | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | 对于 `cmp1` 将选择 :x: |
|
||||||
| Итоговые ограничения | :x: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_check_mark: | |
|
| 最终的限制 | :x: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_check_mark: | |
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@ -571,9 +570,9 @@ groupA.Inverse();
|
|||||||
EcsGroup newGroup = EcsGroup.Inverse(groupA);
|
EcsGroup newGroup = EcsGroup.Inverse(groupA);
|
||||||
```
|
```
|
||||||
|
|
||||||
## 根本
|
## ECS入口
|
||||||
这是一个用户定义的类,作为 ECS 的入口点。其主要目的是初始化和启动每个 Update 引擎上的系统,并在使用结束后释放资源。
|
这是一个用户定义的类,作为 ECS 的入口点。其主要目的是初始化和启动每个 Update 引擎上的系统,并在使用结束后释放资源。
|
||||||
### Пример для Unity
|
### Unity示例
|
||||||
``` c#
|
``` c#
|
||||||
using DCFApixels.DragonECS;
|
using DCFApixels.DragonECS;
|
||||||
using UnityEngine;
|
using UnityEngine;
|
||||||
@ -619,7 +618,7 @@ public class EcsRoot : MonoBehaviour
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
### Общий пример
|
### 公用示例
|
||||||
``` c#
|
``` c#
|
||||||
using DCFApixels.DragonECS;
|
using DCFApixels.DragonECS;
|
||||||
public class EcsRoot
|
public class EcsRoot
|
||||||
|
65
README.md
65
README.md
@ -311,14 +311,14 @@ Processes are queues of systems that implement a common interface, such as `IEcs
|
|||||||
<details>
|
<details>
|
||||||
<summary>Custom Processes</summary>
|
<summary>Custom Processes</summary>
|
||||||
|
|
||||||
Для добавления нового процесса создайте интерфейс наследованный от `IEcsProcess` и создайте раннер для него. Раннер это класс реализующий интерфейс запускаемого процесса и наследуемый от `EcsRunner<TInterface>`. Пример:
|
To add a new process, create an interface inherited from `IEcsProcess` and create a runner for it. A runner is a class that implements the interface of the process to be run and inherits from `EcsRunner<TInterface>`. Example:
|
||||||
``` c#
|
``` c#
|
||||||
// Интерфейс.
|
// Process interface.
|
||||||
interface IDoSomethingProcess : IEcsProcess
|
interface IDoSomethingProcess : IEcsProcess
|
||||||
{
|
{
|
||||||
void Do();
|
void Do();
|
||||||
}
|
}
|
||||||
// Реализация раннера. Пример реализации можно так же посмотреть в встроенных процессах
|
// Implementation of a runner. An example of implementation can also be seen in built-in processes.
|
||||||
sealed class DoSomethingProcessRunner : EcsRunner<IDoSomethingProcess>, IDoSomethingProcess
|
sealed class DoSomethingProcessRunner : EcsRunner<IDoSomethingProcess>, IDoSomethingProcess
|
||||||
{
|
{
|
||||||
public void Do()
|
public void Do()
|
||||||
@ -328,25 +328,25 @@ sealed class DoSomethingProcessRunner : EcsRunner<IDoSomethingProcess>, IDoSomet
|
|||||||
}
|
}
|
||||||
// ...
|
// ...
|
||||||
|
|
||||||
// Добавление раннера при создании пайплайна.
|
// Adding the runner when creating the pipeline
|
||||||
_pipeline = EcsPipeline.New()
|
_pipeline = EcsPipeline.New()
|
||||||
//...
|
//...
|
||||||
.AddRunner<DoSomethingProcessRunner>()
|
.AddRunner<DoSomethingProcessRunner>()
|
||||||
//...
|
//...
|
||||||
.BuildAndInit();
|
.BuildAndInit();
|
||||||
|
|
||||||
// Запуск раннера если раннер был добавлен.
|
// Running the runner if it was added
|
||||||
_pipeline.GetRunner<IDoSomethingProcess>.Do()
|
_pipeline.GetRunner<IDoSomethingProcess>.Do()
|
||||||
|
|
||||||
// or если раннер не был добавлен(Вызов GetRunnerInstance так же добавит раннер в пайплайн).
|
// or if the runner was not added (calling GetRunnerInstance will also add the runner to the pipeline).
|
||||||
_pipeline.GetRunnerInstance<DoSomethingProcessRunner>.Do()
|
_pipeline.GetRunnerInstance<DoSomethingProcessRunner>.Do()
|
||||||
```
|
```
|
||||||
> Раннеры имеют ряд требований к реализации:
|
> Runners have several implementation requirements:
|
||||||
> * Наследоваться от `EcsRunner<T>` можно только напрямую;
|
> * Inheritance from `EcsRunner<T>` must be direct.
|
||||||
> * Раннер может содержать только один интерфейс(за исключением `IEcsProcess`);
|
> * Runner can only contain one interface (except `IEcsProcess`);
|
||||||
> * Наследуемый класс `EcsRunner<T>,` должен так же реализовать интерфейс `T`;
|
> * The inheriting class of `EcsRunner<T>,` must also implement the `T` interface;
|
||||||
|
|
||||||
> Не рекомендуется в цикле вызывать `GetRunner`, иначе кешируйте полученный раннер.
|
> It's not recommended to call `GetRunner` in a loop; instead, cache the retrieved runner instance.
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
## World
|
## World
|
||||||
@ -401,7 +401,7 @@ poses.Del(entityID);
|
|||||||
|
|
||||||
> It is possible to implement a user pool. This feature will be described shortly.
|
> It is possible to implement a user pool. This feature will be described shortly.
|
||||||
|
|
||||||
## Аспект
|
## Aspect
|
||||||
These are custom classes inherited from `EcsAspect` and used to interact with entities. Aspects are both a pool cache and a component mask for filtering entities. You can think of aspects as a description of what entities the system is working with.
|
These are custom classes inherited from `EcsAspect` and used to interact with entities. Aspects are both a pool cache and a component mask for filtering entities. You can think of aspects as a description of what entities the system is working with.
|
||||||
|
|
||||||
Simplified syntax:
|
Simplified syntax:
|
||||||
@ -443,7 +443,7 @@ class Aspect : EcsAspect
|
|||||||
<details>
|
<details>
|
||||||
<summary>Combining aspects</summary>
|
<summary>Combining aspects</summary>
|
||||||
|
|
||||||
В аспекты можно добавлять другие аспекты, тем самым комбинируя их. Ограничения так же будут скомбинированы.
|
Aspects can have additional aspects added to them, thus combining them. The constraints will also be combined accordingly.
|
||||||
``` c#
|
``` c#
|
||||||
using DCFApixels.DragonECS;
|
using DCFApixels.DragonECS;
|
||||||
// ...
|
// ...
|
||||||
@ -453,25 +453,24 @@ class Aspect : EcsAspect
|
|||||||
public OtherAspect2 otherAspect2;
|
public OtherAspect2 otherAspect2;
|
||||||
public EcsPool<Pose> poses;
|
public EcsPool<Pose> poses;
|
||||||
|
|
||||||
// Функция Init аналогична конструктору Aspect(Builder b).
|
|
||||||
protected override void Init(Builder b)
|
protected override void Init(Builder b)
|
||||||
{
|
{
|
||||||
// Комбинирует с SomeAspect1.
|
// Combines with SomeAspect1.
|
||||||
otherAspect1 = b.Combine<OtherAspect1>(1);
|
otherAspect1 = b.Combine<OtherAspect1>(1);
|
||||||
// Хотя для OtherAspect1 метод Combine был вызван раньше, сначала будет скомбинирован с OtherAspect2, так как по умолчанию order = 0.
|
// Although Combine was called earlier for OtherAspect1, it will first combine with OtherAspect2 because the default order is 0.
|
||||||
otherAspect2 = b.Combine<OtherAspect2>();
|
otherAspect2 = b.Combine<OtherAspect2>();
|
||||||
// Если в OtherAspect1 или в OtherAspect2 было ограничение b.Exclude<Pose>() тут оно будет заменено на b.Include<Pose>().
|
// If b.Exclude<Pose>() was specified in OtherAspect1 or OtherAspect2, it will be replaced with b.Include<Pose>() here.
|
||||||
poses = b.Include<Pose>();
|
poses = b.Include<Pose>();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Если будут конфликтующие ограничения у комбинируемых аспектов, то новые ограничения будут заменять добавленные ранее. Ограничения корневого аспекта всегда заменяют ограничения из добавленных аспектов. Визуальный пример комбинации ограничений:
|
If there are conflicting constraints between the combined aspects, the new constraints will replace those added earlier. Constraints from the root aspect always replace constraints from added aspects. Here's a visual example of constraint combination:
|
||||||
| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | разрешение конфликтных ограничений|
|
| | cmp1 | cmp2 | cmp3 | cmp4 | cmp5 | разрешение конфликтных ограничений|
|
||||||
| :--- | :--- | :--- | :--- | :--- | :--- |:--- |
|
| :--- | :--- | :--- | :--- | :--- | :--- |:--- |
|
||||||
| OtherAspect2 | :heavy_check_mark: | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | |
|
| OtherAspect2 | :heavy_check_mark: | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | |
|
||||||
| OtherAspect1 | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_minus_sign: | Для `cmp2` будет выбрано :heavy_check_mark: |
|
| OtherAspect1 | :heavy_minus_sign: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_minus_sign: | For `cmp2` will be chosen. :heavy_check_mark: |
|
||||||
| Aspect | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | Для `cmp1` будет выбрано :x: |
|
| Aspect | :x: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_minus_sign: | :heavy_check_mark: | For `cmp1` will be chosen. :x: |
|
||||||
| Итоговые ограничения | :x: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_check_mark: | |
|
| Final Constraints | :x: | :heavy_check_mark: | :heavy_minus_sign: | :x: | :heavy_check_mark: | |
|
||||||
|
|
||||||
</details>
|
</details>
|
||||||
|
|
||||||
@ -793,40 +792,42 @@ var _someDataB = _pipeline.Configs.Get<SomeDataB>();
|
|||||||
```
|
```
|
||||||
|
|
||||||
## World Components
|
## World Components
|
||||||
С помощью компонентов можно прикреплять дополнительные данные к мирам. В качестве компонентов используются `struct` типы. Доступ к компонентам через `Get` оптимизирован, скорость почти такая же как доступ к полям класса.
|
Components can be used to attach additional data to worlds. World components are `struct` types. Access to components via `Get` is optimized, the speed is almost the same as access to class fields.
|
||||||
|
|
||||||
|
Get component:
|
||||||
``` c#
|
``` c#
|
||||||
// Получить компонент.
|
|
||||||
ref WorldComponent component = ref _world.Get<WorldComponent>();
|
ref WorldComponent component = ref _world.Get<WorldComponent>();
|
||||||
```
|
```
|
||||||
Реализация компонента:
|
Component Implementation:
|
||||||
``` c#
|
``` c#
|
||||||
public struct WorldComponent
|
public struct WorldComponent
|
||||||
{
|
{
|
||||||
// Данные.
|
// Data.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
Или:
|
Or:
|
||||||
``` c#
|
``` c#
|
||||||
public struct WorldComponent : IEcsWorldComponent<WorldComponent>
|
public struct WorldComponent : IEcsWorldComponent<WorldComponent>
|
||||||
{
|
{
|
||||||
// Данные.
|
// Data.
|
||||||
|
|
||||||
void IEcsWorldComponent<WorldComponent>.Init(ref WorldComponent component, EcsWorld world)
|
void IEcsWorldComponent<WorldComponent>.Init(ref WorldComponent component, EcsWorld world)
|
||||||
{
|
{
|
||||||
// Действия при инициализации компонента. Вызывается до первого возвращения из EcsWorld.Get .
|
// Actions during component initialization. Called before the first return from EcsWorld.Get().
|
||||||
}
|
}
|
||||||
void IEcsWorldComponent<WorldComponent>.OnDestroy(ref WorldComponent component, EcsWorld world)
|
void IEcsWorldComponent<WorldComponent>.OnDestroy(ref WorldComponent component, EcsWorld world)
|
||||||
{
|
{
|
||||||
// Действия когда вызывается EcsWorld.Destroy.
|
// Actions when EcsWorld.Destroy is called.
|
||||||
// Вызов OnDestroy, обязует пользователя вручную обнулять компонент, если это необходимо.
|
// Calling OnDestroy, obliges the user to manually reset the component if necessary.
|
||||||
component = default;
|
component = default;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
<summary>Пример использования</summary>
|
<summary>Example of use</summary>
|
||||||
|
|
||||||
События интерфейса IEcsWorldComponent<T>, могут быть использованы для автоматической инициализации полей компонента, и освобождения ресурсов.
|
IEcsWorldComponent<T> interface events, can be used to automatically initialize component fields, and release resources.
|
||||||
``` c#
|
``` c#
|
||||||
public struct WorldComponent : IEcsWorldComponent<WorldComponent>
|
public struct WorldComponent : IEcsWorldComponent<WorldComponent>
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user