插件及文档: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框架简介的更多相关文章

  1. unity游戏开发之entitas框架

    框架介绍 entitas是一个超快.超轻量的c# Entity-Component-System (ECS)框架,专门为Unity引擎设计.提供内部缓存和高速的组件访问,经过精心设计,可以在垃圾收集环 ...

  2. Unity 游戏框架搭建 2018 (一) 架构、框架与 QFramework 简介

    约定 还记得上版本的第二十四篇的约定嘛?现在出来履行啦~ 为什么要重制? 之前写的专栏都是按照心情写的,在最初的时候笔者什么都不懂,而且文章的发布是按照很随性的一个顺序.结果就是说,大家都看完了,都还 ...

  3. Unity StrangeIoC框架

    Unity StrangeIoC框架  http://blog.csdn.net/y1196645376/article/details/52746251    

  4. Spring 系列: Spring 框架简介 -7个部分

    Spring 系列: Spring 框架简介 Spring AOP 和 IOC 容器入门 在这由三部分组成的介绍 Spring 框架的系列文章的第一期中,将开始学习如何用 Spring 技术构建轻量级 ...

  5. 《HiWind企业快速开发框架实战》(0)目录及框架简介

    <HiWind企业快速开发框架实战>(0)目录及框架简介 本系列主要介绍一款企业管理系统快速开发框架,该框架旨在快速完成企业管理系统,并实现易维护可移植的目标. 使用逐个系统模块进行编码的 ...

  6. Yaf零基础学习总结1-Yaf框架简介

    从今天开始,给大家讲解下yaf框架,讲解之前肯定要了解下yaf是个什么东西,当然,从标题我们已经知道yaf是个PHP框架了,也许大家对于PHP框架并不陌生,一般PHP程序员用过的框架至少有一两个吧,国 ...

  7. hdwiki 框架简介

    虽然HDwiki是一个开源的wiki系统,并且代码简洁易懂,但如果想在系统上做做进一步开发还需要对框架有一个整体的认识.熟悉了HDwiki的框架以后完全可以独立出来做其他功能的开发,当做一个开源的PH ...

  8. Apache—DBUtils框架简介

    转载自:http://blog.csdn.net/fengdongkun/article/details/8236216 Apache—DBUtils框架简介.DbUtils类.QueryRunner ...

  9. Jersey框架一:Jersey RESTful WebService框架简介

    Jersey系列文章: Jersey框架一:Jersey RESTful WebService框架简介 Jersey框架二:Jersey对JSON的支持 Jersey框架三:Jersey对HTTPS的 ...

  10. Web自动化框架LazyUI使用手册(1)--框架简介

    作者:cryanimal QQ:164166060 web端自动化简介 web端自动化,即通过自动化的方式,对Web页面施行一系列的仿鼠标键盘操作,以达到对Web页面的功能进行自动化测试的目的. 其一 ...

随机推荐

  1. [FAQ] crontab 执行curl xxx 好像没有执行 ?

      如果你的crontab任务中的curl命令没有执行,可能有几个原因需要检查: 1. 检查命令路径:确保你在crontab任务中指定了正确的curl命令路径.你可以使用 which curl 命令来 ...

  2. [Go] go build 和 go install 的区别

    $ go build 源文件及其包依赖 编译成二进制. install 不仅执行build过程 而且会把编译的二进制放到 $GOPATH/bin/,包放到 $GOPATH/pkg/ Link:http ...

  3. WPF 将控件放入到 UserControl 里获取 HwndSource 为空的情况

    本文记录将 WPF 控件放入到 UserControl 里,如果此 UserControl 没有被设置 Visibility 为可见过,那么放在此 UserControl 内的控件将获取不到 Hwnd ...

  4. WPF 引用 UWP 控件 不打包为 MSIX 分发的方法

    按照微软的官方文档,大部分的文档都会说如果用了 XAML Islands 等技术的时候,需要新建一个打包项目,将 WPF 应用打包为 msix 等才可以进行分发和使用.但是实际上不打包也可以,此时可以 ...

  5. NopCommerce 多数据库方案

    本文转自:http://www.cnblogs.com/YUTOUYUWEI/p/5538200.html 有时候一个项目需要连接多个数据库,以实现不同数据库的数据在同个项目的共享. 如果已经安装了n ...

  6. Mac安装mysql5.7

    1.下载文件(访问就直接下载了) http://dev.mysql.com/get/Downloads/MySQL-5.7/mysql-5.7.10-osx10.10-x86_64.dmg 2.打开下 ...

  7. gprMax电磁波正演模拟方法

    文章首发于:https://blog.zhaoxuan.site/archives/37.html: 第一时间获取最新文章请关注博客个人站:https://blog.zhaoxuan.site. 目录 ...

  8. js图片懒加载,在不做分页的情况下的解决方案

    Intersection Observer API 1.注意点 一般都是后端返回数据, 用 this.$nextTick(() => { this.handleScroll(); }); 确保d ...

  9. 每天上一当系列之vue修饰符.number

    今天使用number修饰符去处理el-input的内容为数字做校验原本以为省事不少,没想到,为0开头无法输入第二位以后,并且输入的比较多的时候会出现Infinity 很神奇,网上查了说是element ...

  10. Django国际化与本地化指南

    title: Django国际化与本地化指南 date: 2024/5/12 16:51:04 updated: 2024/5/12 16:51:04 categories: 后端开发 tags: D ...