框架介绍
entitas是一个超快、超轻量的c# Entity-Component-System (ECS)框架,专门为Unity引擎设计。提供内部缓存和高速的组件访问,经过精心设计,可以在垃圾收集环境中最优地工作。
 
框架解析
要理解框架,就需要知道这四种概念,分别是:Entiy实体、Context环境、Group组、Collector收集器。如图,在一个Context中,会有很多Entity,每个Entity都拥有若干Component,Component中只有数据,而Group是拥有相同Component的Entity集合,用于快速查找拥有特定属性的Entity。

aaarticlea/png;base64,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" alt="" />

 
Entity
Entity实体是保存数据的容器,用于表示应用程序中的某些对象。可以以IComponent的形式从实体中添加、替换或删除数据。实体有相应的事件来让你知道组件是否被添加、替换或删除。
 
Context
Context环境是用来创建和销毁entity的工厂,用它来过滤感兴趣的entity。
 
Group
Group支持对Context中的实体进行超级快速过滤。当实体发生变化时,它们会不断更新,并且可以立即返回实体组。假设有数千个实体,而你只想要那些具有PositionComponent的实体——只需为这个Group询问Context,就可以很方便的获得结果。
 
Collector
Collector 收集器提供了一种随时间变化对组中的更改作出反应的简单方法。它能很方便的汇总处理特定的Entity。
 
 
基本使用
 
Group
Group总是最新的,并且包含与指定匹配程序匹配的所有实体。每个环境都有一个特定的匹配器类型——如果在你的游戏环境中寻找实体(比如游戏实体),你需要使用GameMatcher
var context = contexts.game;

var movables = context.GetGroup(GameMatcher.Movable);
var count = movables.count; // count is 0, the group is empty var entity1 = context.CreateEntity();
entity1.isMovable = true;
var entity2 = context.CreateEntity();
entity2.IsMovable = true; count = movables.count; // count is 2, the group contains the entity1 and entity2 // GetEntities() always provides an up to date list
var movableEntities = movables.GetEntities();
foreach (var e in movableEntities) {
// Do sth
} entity1.Destroy();
entity2.Destroy(); count = movables.count; // count is 0, the group is empty
 
Matcher
Matcher匹配器由代码生成器生成,可以组合。匹配器通常用于从感兴趣的上下文中获取实体组。需要在匹配器前加上你感兴趣的上下文名称(例如GameMatcher, InputMatcher等)。
var matcher = GameMatcher.Movable;

GameMatcher.AllOf(GameMatcher.Movable, GameMatcher.Position);

GameMatcher.AnyOf(GameMatcher.Move, GameMatcher.Position);

GameMatcher
.AllOf(GameMatcher.Position)
.AnyOf(GameMatcher.Health, GameMatcher.Interactive)
.NoneOf(GameMatcher.Animating);
 
Systems
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();
 
System详解
总共有上述四种Systems,在实际开发中,需要为应用程序中的每个任务或行为创建systems,并按照定义的顺序执行它们。
 
InitializeSystem
InitializeSystem在程序开始时运行一次。它实现接口IInitializeSystem,后者定义了Initialize()方法。这是您设置初始游戏状态的地方,类似于Unity的Start()方法。
using Entitas;

public class MyInitSystem : IInitializeSystem {

    public void Initialize() {
// Initialization code here
} }
 
ExecuteSystem
ExecuteSystem每帧执行一次。它实现接口IExecuteSystem,接口定义了Execute()方法。这是放置需要每帧执行的代码的地方,类似于Unity的Update()方法。
using Entitas;

public class MyExecSystem : IExecuteSystem {

    public void Execute() {
// per-frame code goes here
} }
 
CleanupSystem
在所有其他systems完成它们的工作之后,CleanupSystem在每个帧的末尾运行。它实现了接口ICleanupSystem,接口定义了方法Cleanup()。如果想要创建只存在于一帧的实体,那么这个工具非常有用。
public class MyCleanupSystem : ICleanupSystem {

    public void Cleanup() {
// cleanup code here
// runs after every execute and reactive system has completed
} }
 
ReactiveSystem
ReactiveSystem在底层是使用了group观察者。通过它,你可以轻而易举的拥有发生改变的你感兴趣的实体。假设你在战场上有100个战斗单位,但是只有10个单位改变了他们的位置。不使用普通的IExecuteSystem,根据位置更新所有100个视图,您可以使用IReactiveSystem,它只更新10个更改单元的视图。所以效率很高。与其他system不同,ReactiveSystem继承自基类ReactiveSystem,而不是实现接口。entitas为游戏中的每个context生成一个实体类型。如果您的context是Game, GameState and Input,那么将生成三种类型:GameEntity、GameStateEntity和InputEntity。ReactiveSystem要求提供它们响应的特定context和关联实体类型。基类定义了一些必须实现的抽象方法。首先,须创建一个构造函数,该构造函数调用基构造函数并为其提供适当的context。必须重写3个方法:GetTrigger()返回一个Collector收集器,它告诉system要响应什么事件。Filter()对collector收集器返回的实体执行最后检查,确保它们在对每个实体调用Execute()之前都附加了所需的组件。Execute()是游戏逻辑的主要位置。需要注意的是:不应该尝试将ReactiveSystem和ExecuteSystem相结合,只需将ReactiveSystem看作是ExecuteSystem的一种特殊情况。所有其他接口都可以混合使用。
using System.Collections.Generic;
using Entitas; public class MyReactiveSystem : ReactiveSystem<MyContextEntity> { public MyReactiveSystem (Contexts contexts) : base(contexts.MyContext) {
// pass the context of interest to the base constructor
} protected override ICollector<MyContextEntity> GetTrigger(IContext<MyContextEntity> context) {
// specify which component you are reacting to
// return context.CreateCollector(MyContextMatcher.MyComponent); // you can also specify which type of event you need to react to
// return context.CreateCollector(MyContextMatcher.MyComponent.Added()); // the default
// return context.CreateCollector(MyContextMatcher.MyComponent.Removed());
// return context.CreateCollector(MyContextMatcher.MyComponent.AddedOrRemoved()); // combine matchers with AnyOf and AllOf
// return context.CreateCollector(LevelMatcher.AnyOf(MyContextMatcher.Component1, MyContextMatcher.Component2)); // use multiple matchers
// return context.CreateCollector(LevelMatcher.MyContextMatcher, MyContextMatcher.Component2.Removed()); // or any combination of all the above
// return context.CreateCollector(LevelMatcher.AnyOf(MyContextMatcher.Component1, MyContextMatcher.Component2),
// LevelMatcher.Component3.Removed(),
// LevelMatcher.AllOf(MyContextMatcher.C4, MyContextMatcher.C5).Added());
} protected override bool Filter(MyContextEntity entity) {
// check for required components
} protected override void Execute(List<MyContextEntity> entities) {
foreach (var e in entities) {
// do stuff to the matched entities
}
}
}
 
要响应来自多个context的实体的更改,需要使用multi-reactive system(多响应系统)。首先,需要声明一个接口,该接口将组合来自具有相同组件的多个context的实体,并且需要通过部分类为实体类实现该接口。然后创建从MultiReactiveSystem继承的系统,并传递新接口。
public interface PositionViewEntity : IEntity, IPosition, IView {}

public partial class EnemyEntity : PositionViewEntity {}
public partial class ProjectileEntity : PositionViewEntity {} public class ViewSystem : MultiReactiveSystem<PositionViewEntity, Contexts> { public ViewSystem(Contexts contexts) : base(contexts) {} protected override ICollector[] GetTrigger(Contexts contexts) {
return new ICollector[] {
contexts.Enemy.CreateCollector(EnemyMatcher.Position),
contexts.Projectile.CreateCollector(ProjectileMatcher.Position)
};
} protected override bool Filter(PositionViewEntityentity) {
return entity.hasView && entity.hasPosition;
} protected override void Execute(List<PositionViewEntity> entities) {
foreach(var e in entities) {
e.View.transform.position = e.Position.value;
}
}
}
 
Features
entitas为提供了Features来组织你的system。使用Features将相关system组合在一起。这有一个额外的好处,就是可以在Unity层次结构中为你的system分离可视化调试对象。现在可以在逻辑组中检查它们,而不是一次检查所有。
Feature还可以帮助你在项目中执行更广泛的范例规则。功能的执行顺序由添加它们的顺序决定,把你的系统分成InputSystems: Feature, GameLogicSystems: Feature和RenderingSystems: Feature,然后按照这个顺序初始化它们,确保游戏逻辑不会被干扰。
Feature要求实现构造函数。使用Add()方法向Feature添加system。这里添加它们的顺序定义了它们在运行时的执行顺序。可以在GameController中使用Feature将systems组实例化。
using Entitas;

public class InputSystems : Feature
{
public InputSystems(Contexts contexts) : base("Input Systems")
{
// order is respected
Add(new EmitInputSystem(contexts));
Add(new ProcessInputSystem(contexts));
}
}
在你的GameController中:
Systems createSystems(Contexts contexts) {

     // order is respected
return new Feature("Systems") // Input executes first
.Add(new InputSystems(contexts))
// Update
.Add(new GameBoardSystems(contexts))
.Add(new GameStateSystems(contexts))
// Render executes after game logic
.Add(new ViewSystems(contexts))
// Destroy executes last
.Add(new DestroySystem(contexts));
}
 
entitas中的Attributes
Code Generator(代码生成器)目前支持与类、接口和结构一起使用的以下特性:
  • [Context]: 可以使用此特性使组件仅在指定的context中可用;例如 [MyContextName], [Enemies], [UI]....提高内存占用。它还可以创建组件。
  • [Unique]: 代码生成器将提供额外的方法,以确保最多存在一个具有该组件的实体。
  • [FlagPrefix]:仅可用于支持标记组件的自定义前缀。
  • [PrimaryEntityIndex]: 可用于将实体限制为唯一的组件值。
  • [EntityIndex]: 可用于搜索具有组件值的实体。
  • [CustomComponentName]: 为一个类或接口生成具有不同名称的多个组件。
  • [DontGenerate]: 代码生成器不会使用此属性处理组件。
  • [Cleanup]: 代码生成器将生成删除组件或销毁实体的系统。
这些特性的具体使用可以参考https://github.com/sschmid/Entitas-CSharp/wiki/Attributes
 
Code Generator代码生成
code generator是entitas框架的一大特色,可以让我们在开发时少写一些代码,在unity编辑器project面板中,Generated目录下都是自动生成的文件,不要去修改它们。
官方文档中介绍说可以自定义以及扩展code generator,让codegenerator更好的为我们服务,这一点我暂时没有去尝试。
 
个人看法
以下是个人愚见,如有错误欢迎指正。
优点:
  • 遵循这个框架的规则去写代码,代码结构清晰。
  • 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热更的功能
 

unity游戏开发之entitas框架的更多相关文章

  1. Unity游戏开发之C#快速入门

    C#是微软团队在开发.NET框架时开发的,它的构想接近于C.C++,也和JAVA十分相似,有许多强大的编程功能. 个人感受是C#吸收了众多编程语言的优点,从中可以看到C.C++.Java.Javasc ...

  2. Unity游戏开发之“屏幕截图”

    原地址:http://sygame.lofter.com/post/117105_791680 在unity游戏开发中,可能会遇到在游戏中截屏的效果.这儿提供两种截屏方法.(方法二提供显示截图缩略图代 ...

  3. Unity游戏开发之“分层碰撞”

    有没有同学遇到过这样的情况:在游戏开发3D游戏中非经常见,比方让一个物体能穿过一个物体 而还有一个物体不能穿过这个物体,并且3个物体都不能穿过地面.在unity中这样的情况的处理是通过分层碰撞来解决的 ...

  4. unity游戏开发之NGUI的UISprite染色

    游戏的UI开发中常常会遇到染色问题.比如button失效变灰的效果,同一个道具通过策划表配的颜色值染上红绿蓝紫等颜色,效果例如以下 最笨最挫的方法当然是让美术多出几个资源图.这种一个缺点是浪费资源,在 ...

  5. Cocos2d-x 3.x游戏开发之旅

    Cocos2d-x 3.x游戏开发之旅 钟迪龙 著   ISBN 978-7-121-24276-2 2014年10月出版 定价:79.00元 516页 16开 内容提要 <Cocos2d-x ...

  6. 【转载】浅谈游戏开发之2D手游工具

    浅谈游戏开发之2D手游工具 来源:http://www.gameres.com/459713.html 游戏程序 平台类型: iOS Android  程序设计: 其它  编程语言:   引擎/SDK ...

  7. [整理]Unity3D游戏开发之Lua

    原文1:[Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘(上) 各位朋友,大家好,我是秦元培,欢迎大家关注我的博客,我地博客地址是blog.csdn.net/qinyuanpei.如果 ...

  8. [Unity3D]Unity3D游戏开发之Lua与游戏的不解之缘终结篇:UniLua热更新全然解读

    ---------------------------------------------------------------------------------------------------- ...

  9. iOS游戏开发之UIDynamic

    iOS游戏开发之UIDynamic 简介 什么是UIDynamic UIDynamic是从iOS 7开始引入的一种新技术,隶属于UIKit框架 可以认为是一种物理引擎,能模拟和仿真现实生活中的物理现象 ...

随机推荐

  1. python 实现判断一个用户输入字符串是否是小数的小程序

    要判断一个字符串是否是小数:1先判断小数点的个数,即如果是小数,则必须有且仅有一个'.'号2再分别判断'.'号的左右两边是否是数字: 判断左边时,如果负数,则左边包含'-'号:必须以'-'号开头(校验 ...

  2. 自己从0开始学习Unity的笔记 I (C#字符串转换为数字)

    我基本上从0开始学习编程,运算符基本上跳过,因为知道了 “=”这个符号相当于赋值,然后“==”才是等于,其他和普通运算符号差不都,也就跳过了. 最基础的赋值那种,我看了下代码,似乎没什么难度,估计新手 ...

  3. 《ASP.NET MVC 5 破境之道》:第一境 ASP.Net MVC5项目初探 — 第三节:View层简单改造

    第一境 ASP.Net MVC5项目初探 — 第三节:View层简单改造 MVC默认模板的视觉设计从MVC1到MVC3都没有改变,比较陈旧了:在MVC4中做了升级,好看些,在不同的分辨率下,也能工作得 ...

  4. netty网络通信中的tcp拆包问题

    工作中的一个项目,我们的一个应用与银行系统进行tcp通信的时候,银行下送的报文有时会分多次返回.在tcp中这种数据包分多次小数据包发送的情况成为拆包问题. 其中一个,也是最常见的思路就是在报文的报文头 ...

  5. AJPFX的资金安全性

    AJPFX承诺保证客户资金安全,并严格按照英国的相关规章制度从事经营活动.客户资金存放于投资级银行的独立账户中.通过实行公司资产与客户资金分别保管,在发生无偿债能力的罕见情况下,客户可获退还独立存放资 ...

  6. Exp6 信息搜集与漏洞扫描 20164323段钊阳

    20164323 Exp6 信息搜集与漏洞扫描 回答问题 1.哪些组织负责DNS,IP的管理. 全球根服务器均由美国政府授权的ICANN统一管理,负责全球的域名根服务器.DNS和IP地址管理.全球一共 ...

  7. Django signal 信号机制的使用

    Django中提供了"信号调度",用于在框架执行操作时解耦,当某些动作发生的时候,系统会根据信号定义的函数执行相应的操作 一.Django中内置的 signal 类型主要包含以下几 ...

  8. 七,mysql优化——表的垂直划分和水平划分

    1,表的水平划分 如果一个表的记录数太多,比如成千上万条,而且需要经常检索,那么我们有必要化整为零.如果我拆成100个表,那么每个表只有10万条记录.当然需要数据在逻辑上可以划分.一个好的划分依据,有 ...

  9. 用node.js写一个简单爬虫,并将数据导出为 excel 文件

    引子 最近折腾node,最开始像无头苍蝇一样到处找资料,然而多数没什么卵用,都在瞎比比.在一阵瞎搞后,我来分享一下初步学习node的三个过程: 1 撸一遍NODE入门,对其有个基本的了解: 2 撸一遍 ...

  10. PHP之旅4 php 超全局变量

    预定义数组: 自动全局变量---超全局数组 1.包含了来自web服务器,客户端,运行环境和用户输入的数据 2.这些数组比较特别 3.全局范围内自动生效,都可以直接使用这些数组 4.用户不能自定义这些数 ...