unity + ECS 第一章 Entitas

Entitas介绍

GitHub地址:https://github.com/sschmid/Entitas-CSharp

Entitas is a super fast Entity Component System (ECS) Framework specifically made for C# and Unity

简单来说就是个基于C#和unity的ECS框架

 

Entitas使用

一    安装

https://github.com/sschmid/Entitas-CSharp/releases 最新应该是1.8.0

unity + ECS 第一章 Entitas_第1张图片

两个文件夹复制到自己的项目中

unity + ECS 第一章 Entitas_第2张图片

导入编译出现上述选项。打开preference

unity + ECS 第一章 Entitas_第3张图片

点击点击AutoImport

unity + ECS 第一章 Entitas_第4张图片

选择continue and overwrite

unity + ECS 第一章 Entitas_第5张图片

点击Generate 生成所需代码

unity + ECS 第一章 Entitas_第6张图片

编译后会有一个sources的文件夹 生成成功

二   HelloWorld

官方实例  https://github.com/sschmid/Entitas-CSharp/wiki/Unity-Tutorial-Hello-World

官方描述的很详细这里就不做赘述了

需要看懂下面的代码最好看下官方的案例,直接观看可能无法理解

在这里解释几个概念

Contexts

unity + ECS 第一章 Entitas_第7张图片

这里这个Attribute是在

unity + ECS 第一章 Entitas_第8张图片

是在Preferences下的Contexts里面定义的

Context是一种为Entity服务的的管理性数据结构。一个Entity不能自己独立创建,它必须通过context.CreateEntity()创建。通过这种方式,Context可以管理我们创建的所有Entity的生命周期。

在程序中是通过

var contexts = Contexts.sharedInstance;

获得contexts(需要重新生成如果新添加了contexts)

unity + ECS 第一章 Entitas_第9张图片

再获得定义的game,input等等的entity

再通过CreateEntity创建, 然后便可以进行添加组件的操作

这个Attribute也可以不写,同时还有除了Contexts的其他定义 比如Unique Component

[Unique]
public class DebugMessageComponent : IComponent
{
    public string Message;
}

在每个应用程序中,有许多情况下你只想要一个物体的一个实例。这个想法一般呈现在大家多知道并且常常讨厌的单例模式中。在Entitas中,有类似的但更好的东西,我们之前讨论的每种类型的组件都可以定义为一个唯一组件。

component写完点击Preferences下的Generate 生成对应的代码

unity + ECS 第一章 Entitas_第10张图片

就可以给entity添加组件

 
  

ps: (addxxx和编写的xxxcomponent是一一对应,同时还会有hasxxx,Replacexxx等等)

Group 组合

Context管理着所有实体 因此我们可以向Context请求并遍历所有Entity 从而收集具有我们关心的Component的那些Entites  这将是一个非常(naive)的实现。针对这种情况下,我们在Entitas中应对措施就是Group。

通过匹配器(matcher)获得我们的group  通过里面的

unity + ECS 第一章 Entitas_第11张图片

AllOf(包含输入的所有组件),AnyOf(包含输入的其中的一种组件)等等来获得我们想要的Group(实际上就是获得所有满足条件的entity)

Matcher 匹配器

Matcher是我们如何描述我们感兴趣的Entity的一种方式。你可以说它就是我们的小型查询语言(query language)。 GameMatcher意味着我们有一个GameContext,我们可以访问与此Context相关的所有Component类型。如果我们写context.GetGroup(GameMatcher.DebugMessage);我们会得到一组包含DebugMessage组件的Entites。为了定义更复杂的Group,我们可以使用AllOfAnyOfNoneOf方法。 “AllOf”表示所有列出的Component都必须出现在Entity中才能使此Entity成为Group的一部分;“AnyOf”表示必须存在列出的组件中的一个;而在NoneOf的情况下,我们则不希望任何列出的组件存在。 NoneOf不是一个独立的描述,这意味着你将无法编写;因为它会创建一个非常大的集合,所以是被禁止单独使用的。 NoneOf只能与AllOfAnyOf结合使用。

System 系统

ECS或是面向数据设计最主要的目标就是从行为中分理出状态(State from behaviour)。System是我们定义行为的地方(简单来说就是逻辑主要都放在这里)我们可以在system种利用代码来创建新的状态,改变或是删除已有的状态。

Entitas里面System的最基础的接口是ISystem

unity + ECS 第一章 Entitas_第12张图片不需要实现,用于内部标记俗称幽灵协议.....

unity + ECS 第一章 Entitas_第13张图片

Entitas内部写了不少种类的system,就不一一说明 说几个常用的

IExecuteSystem 可持续执行系统

IExecuteSystem是一种可持续执行的system

unity + ECS 第一章 Entitas_第14张图片

这个接口只有一个方法void Execute();。这是我们写需要每tick(或者unity内的update内)都需要执行的代码的地方。

实例

unity + ECS 第一章 Entitas_第15张图片

结果

unity + ECS 第一章 Entitas_第16张图片

ICleanupSystem 清理系统

同样也是可持续执行这个system是为了我们在执行完所有的IExecuteSystem之后执行的逻辑所设立的。像他名字建议的一样,你应该放清理(clean up)的代码到它的void Cleanup();方法中去。他们都只是接口,你可以有用一个类同时实现这些协议,有时候这样做从游戏逻辑上来说非常有意义。

Reactive System 响应式系统

Reactive System是一个当有需要我们处理Entity才会被调用的system。

通过里面的GetTrgger方法 只关心我们只关心的含有我们想要的组件(Component)的实体(Entity)

通过里面Filter方法 过滤掉不含有我们关心的组件的实体

Hello World实例内的 DebugMessageSystem 过滤器和收集器关心的都是同一个组件 显得有些重复 实际应用当中 随着组件的增多 二者的作用也会更具体现

实例

unity + ECS 第一章 Entitas_第17张图片

响应式的系统就像执行式系统一样,会每隔一段时间或是在每一个Update中被触发,然而Execute(List entities) 方法只会在收集器距离上一次Execute收集到新的Entity才会被执行。(这句是重点,这个系统会将上次收集到的复合条件的执行Execute方法然后清空buffer和collect)

unity + ECS 第一章 Entitas_第18张图片

Composing systems 组合系统

Entitas提供了一个Sysetms类,实现了 IInitializeSystem, IExecuteSystem, ICleanupSystem, ITearDownSystem接口。我们可以Add一个system到Systems的实例中,然后当我们调用Systems上的Execute(), Cleanup(), Initialize(), TearDown()方法,它会调用所有添加了的system的对应方法。

在这里,Entitas扩展了一个Feature类。根据我们选择是否开启 visual debugging ,会生成一个Feature 类集成Systems或者DebugSystems类。VIsual debugging消耗非常多的资源,所以当你在移动设备上运行或者制作产品Build的时候,你应该将VIsual debugging关闭掉。所以Feature就是为了让我们的代码更加简单而创造出来的类。

unity + ECS 第一章 Entitas_第19张图片

Systems的使用

unity + ECS 第一章 Entitas_第20张图片

在这里需要注意的是 类似于ReactiveSystem筛选Entity是在过滤器和收集器当中的进行的 所以再初始化System后添加Component

而有些System的筛选是在构造当中 需要在初始化之前添加Component

关于上述的组件使用可以看Entitas的git上面的wiki上面又详细的描述 只不过是纯英文的

在https://github.com/mzaks/EntitasCookBook/tree/master/chapters/1_ingredients 作者的cookbook里面有具体的描述

(觉得英文看起来比较吃力的话推荐https://www.jianshu.com/u/f26ca74e2fd7 )

小结

Entitas 本身是一个非常好用的框架,帮助程序员编写完善,健壮以及高复用性的代码。框架本身对UNITY进行过高度优化,大量的缓存对象管理,使得Entity/Component的访问以及Grouping非常的简单快速。此外附带代码生成器确保了TypeSafety并且节省了一些重复构建代码的时间,Entitas 同时也有自己无法避免的缺点,代码的重构比较困难(不是ecs的缺点)如果你对代码进行添加还好,如果进行修改,一般来说会产生很多的错误,而这些错误使得Entitas无法重新生成新的代码,同时这些错误还会嵌套其中,代码少还可以,多的话,可以想像修改代码的量还是很可观的以及代码量会大量增加。

相对来说使用起来可能还不是呢么方便 下一章研究下unity2018带来的ecs框架 

参考文献

https://www.jianshu.com/u/f26ca74e2fd7

http://www.benmutou.com/archives/2431

http://piemaster.net/2011/07/entity-component-primer/

https://github.com/sschmid/Entitas-CSharp/wiki/Unity-Installation-Guide

你可能感兴趣的:(unity,+,ECS)