浅尝一下ECS(Entity Component System)(学习笔记)

参考文章:浅谈Unity ECS(一)Uniy ECS基础概念介绍:面向未来的ECS - 知乎 (zhihu.com)

视频链接:【青幻译制】GDC讲座系列之三 守望先锋的游戏架构和网络代码_哔哩哔哩_bilibili

云风的 BLOG: 浅谈《守望先锋》中的 ECS 构架 (codingnow.com)

游戏开发中的ECS架构-CSDN博客

一个典型的 ECS 框架 ↑

世界->是系统和实体的组合 -> 实体是一个组件的集合所对应的ID,组件仅仅用于储存游戏状态,而不具备行为,系统具有行为却不保存游戏状态

组件没有函数,系统没有成员变量

Entity Component System (ECS) 是一个 gameplay 层面的框架,它是建立在渲染引擎、物理引擎之上的,主要解决的问题是如何建立一个模型来处理游戏对象 (Game Object) 的更新操作。

这边最主要区别就是把对象上的数据和行为剥离,由专门的System来处理某一种行为,而不是每个对象在自己的一个更新函数中处理所有和自己相关的操作

Unity ECS基本概念

Entity的概念

它的意义在于生命期管理,这里是用 32bit ID 而不是指针来表示的,另外附着了渲染用到的资源 ID 。因为仅负责生命期管理,而不设计调用其上的方法,用整数 ID 更健壮。整数 ID 更容易指代一个无效的对象,而指针就很难做到。

Entity为ECS中基本的成员,实际上只是由一个Index和一个Version组成(Version只有在Entity被回收后会加1),其实际的Component数据存储在一个Chunk上(Unity ECS特有的数据类型),需要操作其Component数据时,根据其index到EntityDataManager中找到其所在的Chunk和IndexInChunk,取到对应的Component数据后进行操作。

public struct Entity : IEquatable<Entity>
    {
        public int Index;
        public int Version;
        ......   
    }

Component的概念

component是Entity的一个属性,通常记成了IComponentISharedComponentData 接口的结构体(两个接口都为空接口,仅标记了类型)。一个 Entity 可以包含多个 Component ,记成了 ISharedComponentData 的数据会在多个 Entity 中共享,同时可以使用托管类型的成员,一般用来存放 GameObject 或 RenderMesh 等渲染相关的成员

一个Entity的Component可以在CreateEntity时指定,也可以使用一个ArcheType创建或从已有Entity复制来创建。同时已经创建的Entity还可以通过AddComponentRemoveComponent来动态进行Component的添加或删除(由于效率问题不推荐)。

Tips:Component可以用Proxy包装后直接挂在GameObject上,挂载多个Proxy的GameObject可以作为Prefab直接传入EntityManager.Instantiate来生成新的Entity,如:

// Create an entity from the prefab set on the spawner component.
    var prefab = spawnerData.prefab;
    var entity = EntityManager.Instantiate(prefab);

ArcheType的概念

ArcheType 是Unity ECS 中特有的概念,也是 Unity ECS 内存管理中的一个核心部分,许多重要操作都与此相关。ArcheType 是由几个固定 Component 组成的 Entity 原型

  • ArcheType管理所有属于它的Entity Component数据,对应数据存放在归属于它的chunk上
  • 可以通过ArcheType快速访问所有该类型的Entity Component数据
  • 拥有Component的Entity一定处在某个ArcheType的管理之下
  • ArcheType拥有缓存机制,第二次创建相同的ArcheType时会自动将现有的返回

我们可以使用EntityManager.CreateArchetype(params ComponentType[] types)来主动创建一个ArcheType,通过ArcheType可以直接调用EntityManager.CreateEntity(EntityArchetype archetype)来快速创建具有某一类特征的Entity。同时如果使用直接传入Components的方式来创建Entity时也会自动生成含有对应Component的ArcheType。

ComponentSystem的概念

ComponentSystem 为 System 在 Unity ECS 中的实现,一个 ComponentSystem 会对含有某些 Component 的 Entity 执行一些特定的操作,通常继承自 ComponentSystem    或          JobComponentSystem。区别是继承 ComponentSystem 只会在主线程执行,而继承自 JobComponentSystem 则可以利用 JobSystem 来进行多线程并发处理,但同时对应操作过程中的限制也更严格。在大部分情况下应当尽量使用 JobComponentSystem 来完成相关的操作,从而提升性能

多个不同的 ComponentSystem 可以在定义时通过 UpdateBefore ,UpdateAfter,UpdateBefored 等标签来控制其执行顺序,这会在一定程度上影响并发执行,通常只在必要时使用

一个 ComponentSystem 通常关注一个包含特定的 Component 组合的 Entity 集合(称为 Component Group)这个 ComponentGroup 集合可以通过 GetComponentGroup 主动获取

ComponentGroup m_Spawners;
//获取包含ObjectSpawner和Position两个Component的ComponentGroup
protected override void OnCreateManager()
{
    m_Spawners = GetComponentGroup(typeof(ObjectSpawner), typeof(Position));
}

也可以使用 IJobProcessComponentData 中定义和 RequireSubtractiveComponentAttribute 等标签自动注入(Inject),同样也会生成一个 ComponentGroup

//通过RequireComponentTagAttribute为JobComponentSystem添加额外的依赖项
//[RequireComponentTagAttribute(typeof(Object))]
//通过RequireSubtractiveComponentAttribute为JobComponentSystem添加额外的排除项
[RequireSubtractiveComponentAttribute(typeof(ObjectSpawner))]  
struct ObjectMove : IJobProcessComponentData<Position>
{
    ......
    public void Execute(ref Position position)
    {
        ......
    }
}

数据存储相关

Chunk的概念

chunk 是Unity ECS 中特有的一个数据结构,在ECS部分代码中有大量使用,通常是指用来存放 Component 信息的 ArchetypeChunk,此外还有更一般的 Chunk 通过 ChunkAllocator 进行开辟,可以存放 ArcheType 中的各类型信息,大小和存储结构都与 ArchetypeChunk 不同,此处的 Chunk 特指存放 ArcheType 中Component 信息的 ArchetypeChunk。chunk 有以下几个特点:

  • EntityManager会将Component数据存放在固定的16kb大小的Chunk中(可以在Chunk定义中找到指定大小kChunkSize)
  • 每个Chunk结构包含了这个区块中内容的相关信息
  • 每个EntityArchetype都包括了一个Chunk的独特集合
  • 一个chunk只能存在于一个archetype
  • 一个ArchetypeChunk结构是一个到具体Chunk的指针

  • 5
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
 一: 什么是ECS?       ECS是一种新的架构模式(当然是针对Unity本身来说),这是一个取代GameObject / Component 的模式。 其模式遵循组合优于继承原则,游戏内的每一个基本单元都是一个实体,每个实体又由一个或多个组件构成,每个组件仅仅包含代表其特性的数据(即在组件中没有任何方法)。系统便是来处理拥有一个或多个相同组件的实体集合的工具,其只拥有行为(即在系统中没有任何数据)。       ECS旨在比GameObject / MonoBehaviour更容易处理大量物体。ECS由于是面向数据的设计,所以很容易并行高速处理,以及与Unity开发的C#JobSystem/Burst Compiler一起工作,从而获取更高的项目运行性能。二:ECS总体发展历史       目前Unity公司由Mike Acton 大佬主持DOD(Data Oriented Design 面向数据设计)的全面改革与推进工作,目的是旨在进一步推进Unity系统本身与Unity项目的执行效率。    ECS总体发展:    A: 在Unity2018引入Entities之前,其实ECS框架早已经出现,但是ECS还是因为守望先锋采用了这个框架才被我们所熟知,后来Git上面出现了一个Entitas的插件可以直接用在Unity上面。Entitas-Unity(有多个语言的port版本,Entitas-Unity下统一称为Entitas) 是 Unity的一个ECS(Entity/Component/System)框架,是在github上面的一个开源项目。    B: 经过Unity公司的认可与改造,目前Unity2018.x 版本已经通过 Package Manager 提供了Unity版本的ECS插件,名称为:“Entities”。    C: Unity2019.x 版本,对“Entities”插件的API进行了进一步改造与完善,以更规范的API实现更加高效的与规范的编程模式。 三:ECS(一)轻松入门篇       本“ECS入门篇”旨在全面讲解ecs 的相关理论与简单Hello World 的编程模式,且通过Unity2018.x与Unity2019.x 两个不同API的编程模式,初步讲解ECS的编程规范与模式规范。        需要进一步学习ECS的小伙伴们,可以关注后续“ECS(二)小试牛刀”篇的进一步讲解。   《Unity ECS(二) 小试牛刀》https://edu.csdn.net/course/detail/27096 

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值