插件及文档:https://github.com/sschmid/Entitas-CSharp/wiki/Home
资料:

什么是Entitas
Entitas是一个运行效率高的轻量级C# Entity-Component-System(ECS)框架,专门为unity订制。提供内部缓存和快速的组件访问。它经过精心设计,可以在垃圾收集环境中发挥最佳作用。
## 优缺点:
来自大佬的点评
优点:
- 遵循这个框架的规则去写代码,代码结构清晰。
- ECS这种模式,耦合度就很低,所有的游戏物体都是组件的组合而已,可扩展性强,通过合理组合component就能配置出一个新的游戏物体。
- 很方便的管理所有实体状态,entitas提供了类似状态机的功能,当感兴趣的某个属性发生变化时,能在System中很方便的做出响应,不管什么状态,都能很方便的做出对应处理。
- unity本身的开发模式就类似ECS,unity2018更是推出了最新的ECS框架,entitas很符合这种开发模式
- entitas自开源以来,一直在更新维护,并受到了unity官方的认可,在unite大会上都有提到。所以,这个框架还是很靠谱的。
缺点:
- 国内资料少,上手难度高。国内用这个框架开发的特别少,遇到问题需要自己爬坑。
- 不适合小项目。小项目用entitas反而麻烦
- entitas更新太快,官方wiki文档更新没有跟上,比如,我在看官方Demo-MatchOne的时候,有个Event的Attribute, wiki上暂时还没有这个的
- 代码热更方面是个问题, entitas基本对unity开发定了一套完整的规则,特别是有Code Generate,如果项目发布后想要更新加入新的代码会很麻烦,官方对此也没有说明,目前好像也没有人分享在entitas中加入lua热更的功能
编程思想
面向对象思想强调对象,通过对象自身属性等完成具体实现。ECS则强调过程,通过并无实际意义的实体来收集作为数据的容器来完成具体实现。
- E:Entity无实际意义,仅作为收集组合C的容器。
- C:Component包含数据的组件,无方法实现。
S:处理数据的系统,自身无任何数据,通过方法来实现。
Entitas基本概念
+------------------+ | Context | |------------------| | e e | +-----------+ | e e---|----> | Entity | | e e | |-----------| | e e e | | Component | | e e | | | +-----------+ | e e | | Component-|----> | Component | | e e e | | | |-----------| | e e e | | Component | | Data | +------------------+ +-----------+ +-----------+ | | | +-------------+ Groups: | | e | Subsets of entities in the context | | e e | for blazing fast querying +---> | +------------+ | e | | | | e | e | e | +--------|----+ e | | e | | e e | +------------+
Entity
entity是一个存储数据的容器,用以表现程序中存在的对象。你可以添加,替换和移除数据通过IComponent。Entitas也有相应的事件event来通知你这些变化。
Entitas通过代码生成器可以自然的产生很多易读的代码如下文中的方法便是代码生成器自动产生的API调用。
entity.AddPosition(3, 7); entity.AddHealth(100); entity.isMovable = true; entity.ReplacePosition(10, 100); entity.ReplaceHealth(entity.health.value - 1); entity.isMovable = false; entity.RemovePosition(); var hasPos = entity.hasPosition; var movable = entity.isMovable;
Context
Context是一个让你可以创建和销毁实体entities的工厂。通过它可以过滤感兴趣的实体。
// Contexts.game is kindly generated for you by the code generator var gameContext = Contexts.game; var entity = gameContext.CreateEntity(); entity.isMovable = true; // Returns all entities having MovableComponent and PositionComponent. // Matchers are also generated for you. var entities = gameContext.GetEntities(Matcher<GameEntity>.AllOf(GameMatcher.Movable, GameMatcher.Position)); foreach (var e in entities) { // do something }
Group
通过组Group,可以对上下文中的实体进行超快速过滤。 当实体更改时,它们会不断更新,并且可以立即返回实体组。 想象一下,您有成千上万个实体,而您只需要那些具有PositionComponent的实体-只需询问该组Group的上下文,它的结果就已经被筛选完成。
gameContext.GetGroup(GameMatcher.Position).GetEntities();
Group和获取的entities都被缓存下来,所以该方法运行速度非常高。尽可能的优先使用Group。gameContext.GetEntities(GameMatcher.Moveble)同样可以内部地使用groups。
Groups有OnEntityAdded,OnEntityRemoved,OnEntityUpdated来对group变化作出响应。
gameContext.GetGroup(GameMatcher.Position).OnEntityAdded += (group, entity, index, component) => { // Do something };
如果你想汇总和处理这些变化,可以使用Collector
Collector
Collector提供了便捷的方法来对group的变化作出反应。比如你想汇总和处理所有添加或替换PositionComponent的实体entities。
var group = gameContext.GetGroup(GameMatcher.Position); var collector = group.CreateCollector(GroupEvent.Added);
接下来
foreach (var e in collector.collectedEntities) { // do something with all the entities // that have been collected to this point of time } collector.ClearCollectedEntities();
停用collector可以方便的结束监视
collector.Deactivate();
Matcher
Matcher匹配器由代码生成器生成,可以组合。匹配器通常用于从感兴趣的上下文中获取实体组。需要在匹配器前加上你感兴趣的上下文名称(例如GameMatcher, InputMatcher等)。
System
entitas中有四种Systems:
- IInitializeSystem: 只执行一次 (system.Initialize())
- IExecuteSystem: 每帧执行 (system.Execute())
- ICleanupSystem: 在其他系统完成后每一帧执行(system.Cleanup())
- ReactiveSystem: 当观察的group改变时执行(system.Execute(Entity[]))
public class MoveSystem : IExecuteSystem { public void Execute() { // Do sth } } public class CreateLevelSystem : IInitializeSystem { public void Initialize() { // Do sth } } public class RenderPositionSystem: ReactiveSystem<GameEntity> { public RenderPositionSystem(Contexts contexts) : base(contexts.Game) { } protected override Collector<GameEntity> GetTrigger(IContext<GameEntity> context) { return context.CreateCollector(GameMatcher.Position); } protected override bool Filter(GameEntity entity) { // check for required components (here it is position and view) return entity.hasPosition && entity.hasView; } protected override void Execute(List<GameEntity> entities) { foreach (var e in entities) { // do stuff to the matched entities e.view.gameObject.transform.position = e.position.position; } } }
最后需要注意的是,需要创建一个管理System的System,因为一个游戏开发过程中,不可能只有一个System的,为了方便管理,便有了[Feature]System的概念。这个类要继承Feature,在构造器里Add所有System进去。Feature就像一个管理System的SystemManager。
var systems = new Systems(contexts) .Add(new CreateLevelSystem(contexts)) .Add(new UpdateBoardSystem(contexts)) .Add(new MoveSystem(contexts)) .Add(new RenderPositionSystem(contexts)); // Call once on start systems.Initialize(); // Call every frame systems.Execute();
/ 未完待续
来源:https://www.cnblogs.com/Firepad-magic/p/12155705.html