unity Entitas框架简介
插件及文档: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();
Hello World (欲入我门,必先Hello World)
创建Component
作为数据容器,存储我们需要输出的字符串信息。同理如果是位置信息,则需要我们自己创建x,y,z坐标信息。这里的Game
namespace JunMoxiao
{
/// <summary>
/// 打印消息的组件
/// </summary>
[Game]//Entitas中Atrribute,方便标记组件所属entities,提高内存效率
public class LogComponent : IComponent
{
/// <summary>
/// 打印信息
/// </summary>
public string message;
}
}
Entitas中的Atrributes
Code Generator(代码生成器)目前支持与类、接口和结构一起使用的以下特性:
- Context: 可以使用此特性使组件仅在指定的context中可用;例如 [MyContextName], [Enemies], [UI]....提高内存效率。它还可以创建组件。
- Unique: 代码生成器将提供额外的方法,以确保最多存在一个具有该组件的实体,相当于单例。
- FlagPrefix:仅可用于支持标记组件的自定义前缀。
- PrimaryEntityIndex: 可用于将实体限制为唯一的组件值。
- EntityIndex: 可用于搜索具有组件值的实体。
- CustomComponentName: 为一个类或接口生成具有不同名称的多个组件。
- DontGenerate]: 代码生成器不会使用此属性处理组件。
- Cleanup: 代码生成器将生成删除组件或销毁实体的系统。
System
LogSystem
namespace JunMoxiao
{
public class LogSystem : ReactiveSystem<GameEntity>
{
public LogSystem(Contexts contexts) : base(contexts.game)
{
}
/// <summary>
///执行
/// </summary>
/// <param name="entities"></param>
protected override void Execute(List<GameEntity> entities)
{
foreach (GameEntity gameEntity in entities)
{
Debug.Log(gameEntity.junMoxiaoLog.message);
}
}
/// <summary>
/// 筛选器
/// </summary>
protected override bool Filter(GameEntity entity)
{
return entity.hasJunMoxiaoLog;
}
/// <summary>
/// 触发器
/// </summary>
protected override ICollector<GameEntity> GetTrigger(IContext<GameEntity> context)
{
return context.CreateCollector(GameMatcher.JunMoxiaoLog);
}
}
}
InitSystem
namespace JunMoxiao
{
/// <summary>
/// 初始化系统
/// </summary>
public class InitSystem : IInitializeSystem
{
private readonly GameContext _gameContext;
public InitSystem(Contexts contexts)
{
_gameContext = contexts.game;
}
public void Initialize()
{
_gameContext.CreateEntity().AddJunMoxiaoLog("hello world!");
}
}
}
Feature
entitas为提供了Features来组织你的system。使用Features将相关system组合在一起。这有一个额外的好处,就是可以在Unity层次结构中为你的system分离可视化调试对象。现在可以在逻辑组中检查它们,而不是一次检查所有。
Feature还可以帮助你在项目中执行更广泛的范例规则。功能的执行顺序由添加它们的顺序决定,然后按照这个顺序初始化它们,确保游戏逻辑不会被干扰。
Feature要求实现构造函数。使用Add()方法向Feature添加system。这里添加它们的顺序定义了它们在运行时的执行顺序。可以在Controller中使用Feature将systems组实例化。
namespace JunMoxiao
{
/// <summary>
/// 将创建的系统添加到框架内
/// </summary>
public class AddGameSystem : Feature
{
public AddGameSystem(Contexts contexts) : base("AddGameSystem")
{
Add(new LogSystem(contexts));
Add(new InitSystem(contexts));
}
}
}
Controller
namespace JunMoxiao
{
public class HelloWorldController : MonoBehaviour
{
private Systems _systems;
void Start()
{
var context = Contexts.sharedInstance;
_systems=new Feature("Systems").Add(new AddGameSystem(context));
_systems.Initialize();
}
void Update()
{
_systems.Execute();
_systems.Cleanup();
}
}
}
运行

/ 未完待续
unity Entitas框架简介的更多相关文章
- unity游戏开发之entitas框架
框架介绍 entitas是一个超快.超轻量的c# Entity-Component-System (ECS)框架,专门为Unity引擎设计.提供内部缓存和高速的组件访问,经过精心设计,可以在垃圾收集环 ...
- Unity 游戏框架搭建 2018 (一) 架构、框架与 QFramework 简介
约定 还记得上版本的第二十四篇的约定嘛?现在出来履行啦~ 为什么要重制? 之前写的专栏都是按照心情写的,在最初的时候笔者什么都不懂,而且文章的发布是按照很随性的一个顺序.结果就是说,大家都看完了,都还 ...
- Unity StrangeIoC框架
Unity StrangeIoC框架 http://blog.csdn.net/y1196645376/article/details/52746251
- Spring 系列: Spring 框架简介 -7个部分
Spring 系列: Spring 框架简介 Spring AOP 和 IOC 容器入门 在这由三部分组成的介绍 Spring 框架的系列文章的第一期中,将开始学习如何用 Spring 技术构建轻量级 ...
- 《HiWind企业快速开发框架实战》(0)目录及框架简介
<HiWind企业快速开发框架实战>(0)目录及框架简介 本系列主要介绍一款企业管理系统快速开发框架,该框架旨在快速完成企业管理系统,并实现易维护可移植的目标. 使用逐个系统模块进行编码的 ...
- Yaf零基础学习总结1-Yaf框架简介
从今天开始,给大家讲解下yaf框架,讲解之前肯定要了解下yaf是个什么东西,当然,从标题我们已经知道yaf是个PHP框架了,也许大家对于PHP框架并不陌生,一般PHP程序员用过的框架至少有一两个吧,国 ...
- hdwiki 框架简介
虽然HDwiki是一个开源的wiki系统,并且代码简洁易懂,但如果想在系统上做做进一步开发还需要对框架有一个整体的认识.熟悉了HDwiki的框架以后完全可以独立出来做其他功能的开发,当做一个开源的PH ...
- Apache—DBUtils框架简介
转载自:http://blog.csdn.net/fengdongkun/article/details/8236216 Apache—DBUtils框架简介.DbUtils类.QueryRunner ...
- Jersey框架一:Jersey RESTful WebService框架简介
Jersey系列文章: Jersey框架一:Jersey RESTful WebService框架简介 Jersey框架二:Jersey对JSON的支持 Jersey框架三:Jersey对HTTPS的 ...
- Web自动化框架LazyUI使用手册(1)--框架简介
作者:cryanimal QQ:164166060 web端自动化简介 web端自动化,即通过自动化的方式,对Web页面施行一系列的仿鼠标键盘操作,以达到对Web页面的功能进行自动化测试的目的. 其一 ...
随机推荐
- CNCF TOC 委员张磊:不断演进的云原生给我们带来了什么?
简介: 任何一种云原生技术,它不再是某种能力的弥补,而是更多地将云的能力以某种方式更简单.更高效地透出给我的应用去使用.无论是容器.K8s 还是 Service Mesh,他们都是在不同的环节帮助应用 ...
- Linux内核社区迁移到github?
简介: github是目前最火的开源软件代码托管平台,那么Linux内核社区能否迁移到github上呢?Intel的Daniel Vetter写了一篇关于这个问题的博客,他给出的答案是NO.至于这个答 ...
- [GPT] php 报错 Unsupported operand types
Unsupported operand types 这个错误通常发生在使用了不支持的操作数类型时.例如,当您尝试对两个不同类型的值执行算术运算时,就会出现这个错误. 例如,如果您尝试将字符串与数字相加 ...
- WPF 已知问题 资源字典树引用与资源寻找的坑
大家都知道,在 WPF 里面,可以让资源字典合并其他资源字典,从而定义出资源字典引用树.然而在资源字典引用树里面,如果没有理清关系,将可以作出一个超级复杂的引用关系网.如果在性能优化中,将网断开部分, ...
- 二、Doris架构原理
Doris是一个MPP的OLAP系统,以较低的成本提供在大数据集上的高性能分析和报表查询功能. MPP (Massively Parallel Processing),即大规模并行处理.简单来说,MP ...
- 校园圈子系统前后端安装开发app小程序h5
四川掌上时代开发公司,作为一家专注于提供高质量软件解决方案的企业,在信息技术领域已经积累了丰富的经验和良好的声誉.位于中国四川省成都市,该公司不仅服务于本地市场,还将业务拓展到了全国乃至国际市场,与多 ...
- vue03 01.vite创建项目
目录 01.创建项目 打包工具 vite介绍 安装命令 安装项目依赖 启动项目 浏览效果 代码目录 打包 预览运行 插件使用 编辑器 01.创建项目 打包工具 vite官网 vite创建项目 vite ...
- axios的基本
目录 axios基本使用.html axios+vue.html axios基本使用.html <!DOCTYPE html> <html lang="en"&g ...
- docker-compose 安装 mysql:5.7.31
目录 一.新建一个启动服务的目录 二.新建文件docker-compose.yml 三.新建角本文件 init-mysql.sh 四.实使化目录和配置文件 启动服务 登陆mysql 其它操作 参考文档 ...
- grads读取netcdf文件,报错SDF file has no discernable X coordinate解决办法
1.netcdf文件格式说明 netCDF数据格式在气象中有广泛的应用,这种格式有一定的复杂性.作为数据的使用者可以不用对数据格式了解得很详细,不过大致的了解还是有必要的.netCDF是自描述的二进制 ...