Unity ECS学习笔记(7)System执行顺序

最近在学习unity的ecs框架,转载几篇写的比较好的文章帮助理解

原文日期 2019-12-5 避免误导未来使用正式版的开发者。

 

1.逻辑的先后顺序

我们已经知道,System的OnUpdate函数会在每一帧自动被调用。

唔,实际上,更准确的,应该分两种情况:

ComponentSystem的OnUpdate:每帧都会被调用。

JobComponentSystem的OnUpdate:取决于Job里筛选出来的实体数量是否大于0,如果是,则每帧都会调用OnUpdate;如果筛选出来的实体数量是0,那么,OnUpdate不会被调用。

这个不太重要。

重要的是,我们的System是处理游戏逻辑,游戏逻辑肯定就会涉及到先后顺序。

比如…玩家走到某个地方后,我才能做一些操作。假设【走动的逻辑】和【做一些操作的逻辑】分别在两个System里。那么,【走动的逻辑】的应该在【做一些操作的逻辑】前面执行。

这时候就涉及到先后顺序了,没错,为了解决这类问题,System的OnUpdate函数的执行是有先后顺序的。

2.系统分组(ComponentSystem Group)

在了解系统如果控制先后顺序之前,需要先了解系统的分组。

唔,其实很简单,就是分组…

比如,SystemA和SystemB都属于一个叫做SystemGroupHello的分组(名字无所谓),SystemC和SystemD属于SystemGroupOther分组。

就是这么简单,就是我们所认知的普通的分组概念。

3.System的执行顺序(System Update Order)

InitializationSystemGroup(负责初始化工作的系统分组)

SimulationSystemGroup(负责逻辑运算的系统分组)

PresentationSystemGroup(负责图形与渲染工作的系统分组)

以上三个是ECS默认的系统分组,很重要,这三个分组里的System从上到下按照顺序被执行。(实际上SystemGroup本身也属于System,也会被调用OnUpdate函数)。

(以上三个分组的中文翻译参考来源:https://connect.unity.com/p/unity-ecs-wu-liao-jie-systemzhi-xing-shun-xu

 

  • InitializationSystemGroup

    • BeginInitializationEntityCommandBufferSystem
    • CopyInitialTransformFromGameObjectSystem
    • SubSceneLiveLinkSystem
    • SubSceneStreamingSystem
    • EndInitializationEntityCommandBufferSystem
  • SimulationSystemGroup

    • BeginSimulationEntityCommandBufferSystem
    • TransformSystemGroup

      • EndFrameParentSystem
      • CopyTransformFromGameObjectSystem
      • EndFrameTRSToLocalToWorldSystem
      • EndFrameTRSToLocalToParentSystem
      • EndFrameLocalToParentSystem
      • CopyTransformToGameObjectSystem
    • LateSimulationSystemGroup
    • EndSimulationEntityCommandBufferSystem
  • PresentationSystemGroup

    • BeginPresentationEntityCommandBufferSystem
    • CreateMissingRenderBoundsFromMeshRenderer
    • RenderingSystemBootstrap
    • RenderBoundsUpdateSystem
    • RenderMeshSystem
    • LODGroupSystemV1
    • LodRequirementsUpdateSystem
    • EndPresentationEntityCommandBufferSystem

    以上全部都是ECS自带的System,这是基于0.3.0版本,以后的版本可能会发生变化。

    注意粗体部分的内容:InitializationSystemGroup,SimulationSystemGroup,PresentationSystemGroup。

    这三个是我们刚刚提到的默认系统分组,实际当中,我们大部分人可能都会在默认的分组下搞事情。

    每个分组下有很多个System,而某些System下又可能包含子System。

    至于这些System有什么用,大家当然是先不用管了。

    以上贴出的所有System,都会按照罗列的顺序执行OnUpdate函数,如果System又包含了子System,那么就子System也会执行OnUpdate函数。

    这个有什么用呢?大家可以理解为”生命周期”(实际上官方没有提到这个东西),这些按顺序执行的System,会影响到我们的某些决策。

    比如,我们想在初始化之前搞事情,那就看看初始化的第一个System是谁,然后让我们自己的System在它之前执行。

    如果大家之前有看过Entity Debugger(Window->Analysis->Entity Debugger)的话,应该就会发现,上面列出的部分System就在Debugger里:

    Debugger里的System也是按照执行顺序逐一罗列的,未来我们新增的System也会出现在这里。

    4.控制System的执行顺序

    等等,怎么样可以让我们的System在别的System之前搞事情呢?

    我们来看看三个特性(Attribute)

    UpdateInGroup:指定当前System在哪个分组下

    UpdateBefore:指定当前System在哪个System之前执行

    UpdateAfter:指定当前System在哪个System之后执行

    我们直接看代码,随便创建一个场景,然后场景一个System类:

    1

    2

    3

    4

    5

    6

    7

    using Unity.Entities;

     

    [UpdateBefore(typeof(SceneSystem))]

    public class MutouSystem : ComponentSystem

    {

        protected override void OnUpdate () { }

    }

    我创建了一个很简单的System,但是附加了UpdateBefore特性,并指定了SceneSystem类型。

    这样的话,我们的MutouSystem肯定就会在SceneSystem之前执行了。

  • 然后,什么都不用做,直接运行,然后看看Entity Debugger:

  • 怎么样,MutouSystem是不是出现在SceneSystem之前了…

    对…没错…才怪啊喂!竟然不是!很奇怪,MutouSystem出现的地方和我们想象的不一样,这是为什么呢?

    唔,很重要的一点,System的执行顺序首先是按照System Group排序的,比如InitializationSystemGroup一定是在SimulationSystemGroup之前执行,那么,InitializationSystemGroup下的所有System肯定也是在SimulationSystemGroup下所有System之前执行。

    有点绕,换句话说,先按分组排序,然后分组内部自己再排序,无论你内部怎么排序,都不可能跨越分组的排序。

    所以,我们要指定System的执行顺序,首先就得确认System所属的分组,然后System就在分组内部调整排序。

    如果我们不知道System所属分组,那么,它就会默认分配到SimulationSystemGroup分组下。

    所以,我们的MutouSystem是属于SimulationSystemGroup分组的,而这个分组下不存在SceneSystem,因此,我们的UpdateBefore特性是无效的。

    于是,改改代码:

    1

    2

    3

    4

    5

    6

    7

    8

    using Unity.Entities;

     

    [UpdateInGroup(typeof(InitializationSystemGroup))]

    [UpdateBefore(typeof(SceneSystem))]

    public class MutouSystem : ComponentSystem

    {

        protected override void OnUpdate () {}

    }

    我在MutouSystem顶部又加了一个UpdateInGroup特性,指定MutouSystem所属分组,于是,再次运行:

    好了,正常了。

    不过,MutouSystem和SceneSystem中间还隔了很多System,也就是说,UpdateBefore只能保证在某个System之前执行,而不能保证是严格地在某个System的上一个执行。

    我们再改改,新增一个System:

    1

    2

    3

    4

    5

    6

    [UpdateInGroup(typeof(InitializationSystemGroup))]

    [UpdateAfter(typeof(MutouSystem))]

    public class LoveSystem : ComponentSystem

    {

        protected override void OnUpdate () {}

    }

    这次我们指定LoveSystem在MutouSystem之后执行,运行看看效果:

    结果和我们预想一样。

    我们再改改,把MutouSystem放到SceneSystem之后执行:

    1

    2

    3

    4

    5

    6

    [UpdateInGroup(typeof(InitializationSystemGroup))]

    [UpdateAfter(typeof(SceneSystem))]

    public class MutouSystem : ComponentSystem

    {

        protected override void OnUpdate () {}

    }

    运行看看效果:

    好,依旧完美,LoveSystem永远跟在MutouSystem身后了。

    好了,关于System的执行顺序,就介绍这么多吧。

     

    注意,本系列教程基于DOTS相关预览版的Package包,是预览版,不代表正式版的时候也适用。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Unity ECS(Entity Component System)是Unity引擎的一种编程范式,它是一种数据驱动的编程模型,它将游戏对象(Entity)分解为数据和行为两个部分,其中数据由组件(Component)来表示,行为则由系统(System)来实现。相对于传统的面向对象编程模型,ECS提供了更高效、更灵活的编程方式,可以有效地提高游戏的性能和扩展性。 下面是我学习Unity ECS时的笔记: ## Entity Entity是ECS中最基本的概念,它表示游戏对象。每个Entity由一个唯一的ID来标识,可以通过EntityManager来创建、销毁、查询和管理Entity。 ## Component Component是Entity的数据部分,用来描述Entity的属性和状态。每个Component包含一些数据成员和一些方法,用来操作这些数据成员。Component是以结构体(struct)的形式定义的,通常只包含数据成员,不包含方法。 ## System System是Entity的行为部分,用来实现游戏逻辑和操作Component。System可以访问和操作EntityManager和Component,但不能直接访问Entity。每个System包含一个或多个Component,表示它所处理的数据类型。System是以类(class)的形式定义的,通常包含一个Update方法,用来实现游戏逻辑。 ## Job Job是一种轻量级的线程,用于并行执行System中的任务。Job可以访问和操作Component,但不能直接访问Entity和EntityManager。Job通常是以结构体(struct)的形式定义的,不包含方法。 ## Archetype Archetype是Entity的集合,包含一组具有相同Component类型的Entity。Archetype可以用来优化数据的访问和处理,可以在不同的System之间共享。 ## Chunk Chunk是Archetype中的数据块,包含一组连续的Entity和它们的Component数据。Chunk可以用来优化内存的分配和访问,可以在Job中进行并行处理。 ## Buffer Buffer是一种Component类型,用来存储可变长度的数据,例如数组或列表。Buffer可以在System和Job中进行修改和访问。 以上是我学习Unity ECS时的笔记,希望对你有所帮助。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值