组件-实体-系统 Entiy-Compoent-System ECS架构整理

继承体系的问题,为何要用ECS

面向对象的问题

  • 当一个新的类型须要多个老类型的不一样功能的时候,不能很好的继承出来
  • 游戏开发后期会有很是多的类,很难维护
  • 游戏中子系统不少,它们对一个对象的关注点每每互不相关,好比渲染.网络,战斗数据,若是都对应一个基础角色对象,这个类就会很大

ECS,经过组合而不是继承的方法来进行实体的构建

  • ECS的设计目的是用来把大量的模块进行集成并解耦,用最小的耦合来集成大量分散的系统
  • 每一个System能够只关注实体有什么,而不是实体是什么,这是与OOP的最大区别
  • 在网络同步的预测错误后能够很方便的纠正(全部元素都用Component分离了)
  • ECS的一个重要特性就是并发优点,由于提供了数据隔离

Unity推荐ESC的缘由

  • ECS专一于您正在解决的实际问题,即构成游戏的数据和行为。
  • 为了配合使用Job System和Burst 编译器。
  • 从以对象为导向的设计转到以数据为导向的设计,代码更为容易,也更易于他人掌握。

示例

假设一个简单的游戏,有石头,树,敌人,玩家三种物体
这个时候须要一个新的类型,能够攻击的树php

  • 按照OOP的设计大体是这样的
  • ECS的设计大体是这样的

    EvilTree拥有: Position,AI,Sprite,AABB

ECS结构图示

ECS基础规则

* Entity轻量级,甚至只有一个Id;
* System没有状态, Component 不带行为
* System不能调用其余System的函数,共享代码要放到Utils里(如敌对关系),Utils函数无反作用;
* 组件里复杂的反作用要经过队列的方式推迟处理,尤为是单例组件;

实体

一个实体指的是存在于你的游戏世界中的物体。实体在代码上就是一个组件的列表。
因为实体的结构实在是太简单了,因此不少实现都没有专门的设计一个实体的数据结构。相反的,一个实体就是一个ID,全部组成这个实体的组件将会被这个ID给标记,从而明确的知道哪些组件是属于哪一个实体的。若是你想的话,你能够在运行时,动态的将组件从实体中移除或者增长一个或多个你感兴趣的组件。好比说,若是玩家发出了一个冰系魔法,将敌人冻住,你只要简单的将它的速度组件移除,那么敌人就静止住了。

组件

没有行为(改变数据),只是用来存储一些数据(所有公开), 每个组件都描述了实体的某个属性特征。
每一个System会以本身的角度对待组件,不一样的观察者区别对待主体
单例组件: 属于单一匿名实体,能够直接访问,存放System大部分状态.好比Ipnut单例,从InputSys中剥离的数据.

系统

真正处理游戏逻辑的地方.
System不关注实体究竟是什么,只关心组件集合,在这个集合上执行一组行为
只会有不多的System改变组件状态,本身管理复杂性
系统会指明所须要的组件集合,由主逻辑筛选出全部知足要求的实体

守望先锋的ECS


EntityAdmin是个World,存储了一个全部System的集合,和一个全部实体的哈希表(ID为unit32)。html

单例组件

示例:命中处理System

  • ModifyHealthQueue组件,记录实体身上全部伤害和治疗效果
  • MovementState组件,移动数据处理
  • 一组Utility函数处理错误纠错,回滚相关Component

几个建议git

  • System定义组件的组合时,能够把组件标记为只读
  • 实体生命周期建议当即建立,延时销毁
  • 某些遗留子系统不能接入ECS时,就不要强行接入,保持子系统的整洁
  • 事实证实,网络同步真的很复杂,因此必须尽量的与引擎其他部分解耦,ECS是解决这个问题的好办法。

Unity中的ECS

在PackageManager中下载Entitiesgithub

参考

相关文章
相关标签/搜索