参考:entity component system vs entity component
参考:Entity Component System FAQ
参考:EC vs ECS for Roguelikes
参考:ECS概述

在学习这章之前,先提出几个问题:

  • 什么是ECS
  • 什么是EC
  • ECS和EC有何区别
  • Unity里用的是不是ECS?
  • UE4里用的是不是ECS?

什么是ECS?

我学习写游戏引擎的时候,学过这一部分的内容,相关知识参考:Entity Component System | Game Engine series

Entity-Component-System (ECS) is a software architectural pattern mostly used on video game development for the storage of game world objects. An ECS follows the pattern of “entities” with “components” of data.
An ECS follows the principle of composition over inheritance, meaning that every entity is defined not by a “type”, but by the components that are associated with it. The design of how components relate to entities depend upon the Entity Component System being used.

先不谈ECS架构,先来思考思考,假设我们有一个场景Scene,里面一个是正方体,那么我可以设计这么几个类:

class Entity
{float[3] m_Position;
};class Box : public Enitty {};class Scene
{std::vector<Entity> m_Entities;
};

在C++里,public继承是is-a的关系,private继承是has-a的关系,那么如果我需要两个正方体,一个可以播放音频,一个可以播放动画,那么代码是这样:

class Entity
{float[3] m_Position;
};class Box : public Enitty {};class Scene
{std::vector<Entity> m_Entities;
};class BoxWithAudio : public Box {};
class BoxWithAnimator : public Box {};

当如果Box既可以播放音频、又可以播放动画,那么一共会有这么些类:

class Box : public Enitty {};
class BoxWithAudio : public Box {};
class BoxWithAnimator : public Box {};
// 出现了multiple inheritance
class BoxWithAnimatorAndAudio : public BoxWithAnimator, public BoxWithAudio {};

这里很容易就出现了一个类继承于两个类的情况,而BoxWithAnimatorBoxWithAudio 又同时继承于Box,所以这是个菱形继承。Box类才添加了两个功能就会造成这么复杂的类设计,所以说这种写法,很容易造成类混乱,更何况其他的很多语言里根本不支持多重继承。

所以,这里有个更好的设计思路,代码如下:

class Entity
{std::vector<Component> m_Components;float[3] m_Position;
};class Scene
{std::vector<Entity> m_Entities;
};class BoxComponent : public Component {};
class AudioComponent : public Component {};
class AnimatorComponent : public Component {};// 创建Entity
Entity boxWithAnimatorAndAudio;
boxWithAnimatorAndAudio.AddComponent(new BoxComponent());
boxWithAnimatorAndAudio.AddComponent(new AudioComponent());
boxWithAnimatorAndAudio.AddComponent(new AnimatorComponent());

此时的Entity,它需要什么功能,就会在其m_Components里添加对应的Component组件,这样代码设计就不混乱了。

上面的代码,是ECS架构的雏形,但还远远不够。假设我们的Scene里有一堆Entity,每个Entity都有自己的Mesh和自己的Position,那么我们渲染的时候,大概会这么写代码:

// 遍历Scene里的entities
for(Entity& e: m_Entities)
{if(e.GetMeshComponent() ! = null){PrepareToDrawMesh(e.GetMeshComponent().mesh, e.GetPosition());}
}// 批处理一起绘制Mesh
DrawMesh();

上面的代码,最大的问题是,没有Cache Friendly,由于Mesh是存在每个Entity里的,它们的内存必然是散布于计算机各个位置的,那么计算机必然经常会产生缺页情况。没有遵循计算机的局部访问性的代码,效率是很差的。

为了解决这个问题,更好的思路产生了,这里变成了data-oriented programming,Scene里相同Component的数据,应该是连续存储的,大概思路如下:

class Scene
{std::vector<Entity> m_Entities;// 真正的数据连续的存在于Scene的Data里std::vector<MeshComponent> m_MeshComponents;std::vector<AudioComponent> m_AudioComponents;std::vector<AnimatorComponent> m_AnimatorComponents;
};// Entity本质就是一个UniqueId, 加上对一堆Component位置的记录
class Entity
{uint32_t m_UniqueId;uint32_t m_AnimatorId;// 代表Entity对应的Animator在Scene里m_AnimatorComponents的iduint32_t m_AudioId;float[3] m_Position;
};class BoxComponent : public Component {};
class AudioComponent : public Component {};
class AnimatorComponent : public Component {};

实际绘制的时候,代码就变成了:

// 遍历Scene里的entities
for(int i = 0; i < m_MeshComponents.count; i++)
{// 遍历Scene里的Entity数组, 找到包含当前遍历的MeshComponent的Entityconst Entity& entity = FindEntityWhoseMeshIdEquals(i);if(entity ! = null){...// 需要的话, 可以根据entity取得一些别的Component数据PrepareToDrawMesh(m_MeshComponents[i], entity.GetPosition());}
}// 批处理一起绘制Mesh
DrawMesh();

一般来说, 一个Entity只会有一个某种类型的Component, 比如Animator、Audio组件等,所以前面的Entity里都是用单个uint32_t记录Component在对应数组里的id,但ScriptComponent一般可以有多个挂在一个Entity上,不过思路是一样的。

顺便提一句,为了方便说明,我在Entity里存了三个float,但这里的Entity.GetPosition可能仍然会产生缺页的情况。实际上应该把Transform信息也作为Component存到Scene里,Entity里不会存储任何实际数据,它的作用是把特定的Components组合起来,然后实际绘制Mesh的时候,内存可能是这样的:

Mesh | Transform | Mesh | Transform

Mesh并不是直接连续的,可能是Mesh | Transform 两两一组,分布于Memory里。


什么是EC?

EC frameworks, as typically found in game engines, are similar to ECS in that they allow for the creation of entities and the composition of components. However, in an EC framework, components are classes that contain both data and behavior, and behavior is executed directly on the component.

EC框架跟ECS非常类似,无非ECS框架里,Component只负责存Data,而EC框架里,Component除了存Data,还要存Behavior相关的逻辑代码。

Unity和UE4里用的是EC还是ECS?

网上直接看到这么个图:

参考:https://medium.com/ingeniouslysimple/entities-components-and-systems-89c31464240d
参考:https://forums.unrealengine.com/t/ue4-vs-entity-component-system/307744/3

核心内容都抄在这里,总之就是说Unity和UE4里都是用的EC架构,而不是ECS

Unity and Unreal are examples of popular game engines with an EC (entity-component) architecture. Annoyingly, these architectures are sometimes called Entity-Component Systems, which are easily confused with Entity-Component-System Architectures (talked about in the next section)

Unreal like Unity is a EC (notice missing the “S”) Entity-Component based Game Engine, the difference with the well-known ECS pattern is that logic is still present in components in UE4, I think it is actually possible use a full ECS approach with UE4 (even if not natively supported), the main problem would be for networked code, for which at some point you’ll need to pass from an Actor, but apart that you can treat certain Actors as components (pure data) and certain actors as systems (pure logic) without too much issues in UE4. However be aware that I saw no major experimentations with UE4 and ECS pattern so there could be some subtle issue that you will it along the way if you decide to do ECS with UE4.

顺便说一句,Unity和UE4里的Component都可以写逻辑代码,如下图所示,划线部分是可以自定义的代码,甚至UE4的Actor本身就可以在内部写逻辑代码(Unity则不可以),而且UE4里的Component可以形成父子层级关系:


结论

所以说,ECS里,Components基本上都是存Data的,对Components处理的逻辑代码都放到System里;而EC里,Components里不仅存Data,也存放代码逻辑,所以没有System这个概念。UE4和Unity里基本都是用的EC架构,而不是ECS系统。

Entity Component System与Entity Component相关推荐

  1. Entity Component System

    2019独角兽企业重金招聘Python工程师标准>>> http://t-machine.org/index.php/2007/09/03/entity-systems-are-th ...

  2. Unity下一轮最大的变革-Entity Component System C# Jobs System

    ECS+jobs实现的酷炫效果 新一代Entity Component System(ECS)将会彻底改变Unity的底层概念(GameObject-Component 系统)和现有工作方式.Mono ...

  3. Unity2018新功能之Entity Component System(ECS)一

    Entities介绍 Entities是Unity2018新引入的一个全新游戏设计框架,我们称之为实体组件系统(Entity Component System,简称ECS),它的出现使我们能够集中精力 ...

  4. “System.Data.Entity.ModelConfiguration.ModelValidationException”类型的未经处理的异常在 EntityFramework.dll 中发生

    "System.Data.Entity.ModelConfiguration.ModelValidationException"类型的未经处理的异常在 EntityFramewor ...

  5. Entityframework:“System.Data.Entity.Internal.AppConfig”的类型初始值设定项引发异常。

    Entityframework:"System.Data.Entity.Internal.AppConfig"的类型初始值设定项引发异常. 参考文章: (1)Entityframe ...

  6. 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用

    学习 EF Code First+MVC 时遇到了在请求JsonResult时出现 序列化类型 System.Data.Entity.DynamicProxies 的对象时检测到循环引用 的异常,原因 ...

  7. EF sqlite3报错 System.Data.Entity.Core.EntityException: 在提供程序连接上启动事务时出错。有关详细信息,请参阅内部异常。...

    问题:sqlite3使用ef框架操作数据库报错 问题原因:数据库文件没有访问权限 结局方案:可以将数据库文件所在的文件夹的访问权限添加Everyone用户权限. 错误:"System.Dat ...

  8. C#------引用System.Data.Entity后DbContext依然无法继承解决方法

    C#------引用System.Data.Entity后DbContext依然无法继承解决方法 参考文章: (1)C#------引用System.Data.Entity后DbContext依然无法 ...

  9. dhl:类型“System.Data.Objects.DataClasses.EntityObject”在未被引用的程序集中定义必须添加对程序集“System.Data.Entity引用...

    必须添加对程序集"System.Data.Entity, Version=3.5.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089& ...

  10. 《A hybrid system for entity recognition ...》阅读笔记

    2019独角兽企业重金招聘Python工程师标准>>> A hybrid system for entity recognition from Chinese clinical te ...

最新文章

  1. Docker中的Java内存消耗优化以及我们如何使用Spring Boot
  2. 全文详解:「深度学习」如何协助处理医疗中的「数据难题」
  3. pyhton3 模拟打开网页
  4. Python 【好看视频】短视频的自动上传与发布实例演示,同时支持抖音、快手、哔哩哔哩、小红书、微视、西瓜视频、微信视频号等平台的视频自动化同步发布
  5. 【数学基础】正态分布为什么如此常见?
  6. CodeForces - 1337D Xenia and Colorful Gems(二分)
  7. java oca_OCA第2部分中的Java难题
  8. 弗林的计算机体系结构分类
  9. UVALive4256 Salesmen
  10. 【PyTorch v1.1.0文档研习】60分钟快速上手
  11. 直接在低版本IE6/7/8浏览器中使用HTML5的audio和video标签播放视频音频的办法
  12. java-乐观锁与悲观锁
  13. Java实现图片水印
  14. 开发者如何提升和推销自己
  15. 项目2:数据可视化(五)绘制世界人口地图
  16. JavaScript实现动态添加的元素添加点击事件
  17. Top 25 sourceforge上开源项目介绍
  18. 计算机动作路径教案,《引导路径动画》教案
  19. 会声会影2022中文版主要功能讲解64位安装下载
  20. 知音微服务平台网上订烟_96368手机订烟统一订单下载|96368统一订单平台(湖南烟草统一订单)下载v1.3.6 安卓版_ 2265安卓网...

热门文章

  1. 知乎live-李笑来-人人都能用英语-笔记
  2. 02、RabbitMQ之交换机
  3. 如何用工具自动修复数字IC后端设计实现绕线后的Physical DRC_
  4. 为什么要面向对象编程?
  5. 极坐标可以用计算机吗,极坐标
  6. hdoj1814 Peaceful Commission【2-set】
  7. 微信支付普通商户模式实现分账操作
  8. android命令行启动,Android中使用am命令实现在命令行启动程序详解
  9. BUUCTF WEB PIAPIAPIA1
  10. 《Loy解说Eureka客户端源码(一)》