ECS丨怎样写 ECS,ForEach 筛选机制 + [GenerateAuthoringComponent]创建实体

提示:选中右侧目录,可快速找到所需内容

本系列博客地址:传送门

 

安装package:

  • Mathematics
  • Hybird Renderer
  • Jobs
  • Burst

 

ECS有两种写法,一种是便于将旧项目移植成ECS框架的写法,这种写法实际还是单线程,有需要再补充。

我们直接讲高性能ECS的写法。

 

我们前文了解到。ECS由下面组成:

  • Entity(实体[转化实体的脚本]、ECS自带的转化脚本
  • Component(只有数据的组件脚本
  • System(只有方法的系统脚本

即只要写出这三部分,就完成了ECS框架。

 

但有时我们将转化实体的代码放在C里,这样就只有三个脚本了。有这个知识点的印象,我们在后面写时就明白了。

 

那么,我们就一个问题:不得到gameObject,该如何操作数据,让方块实现旋转。下面用ECS方法来写一下。

记得,下方红色代码,是规范格式。引用这些,继承这些,ECS便可自动帮你实现多线程等功能。

 

 

E:Entity

场景创建一个Cube,挂载 ConvertToEntity 组件。

但此时Cube还不是实体,只有挂上Component后,Component中的 [GenerateAuthoringComponent] 才会将Cube变为实体。

ConvertToEntity 组件:指定该物体参与 System 运算。不挂,则它不参与System 的筛选和运算。

 

 

C:Component

只包含数据,挂载到Entity实体上,即Cube上。

这个数据定义了旋转速度,并且也作为S的筛选条件。

[GenerateAuthoringComponent]特性:将该物体转化为实体。且有了这个特性,这个C才能挂载到物体上。否则因为没有继承Mono,不能挂载。

using Unity.Entities;

[GenerateAuthoringComponent]
public struct RotationSpeed_ForEach : IComponentData
{
    public float RadiansPerSecond;
}

 

 

S:System(Entities.ForEach筛选)

该脚本放在Assets即可,不用挂在场景。

继承了 JobComponentSystem,JobComponentSystem 就是上篇文章提到的 Job System,它将你的项目从单线程变成多线程。

该脚本作用:筛选场景中所有Entity,得到包含 Rotation、RotationSpeed_ForEach两个属性的实体。想要旋转,就对 Rotation 进行操作即可了。

你的项目同理。ForEach 是筛选组件,得到同时包含这几个组件的实体上的这几个组件,然后对这些组件数据操作即可。

注:如果筛出来两个物体,都含有这些组件,那这两个物体都会被进行操作。

using Unity.Collections;
using Unity.Entities;
using Unity.Jobs;
using Unity.Mathematics;
using Unity.Transforms;

public class RotationSpeedSystem_ForEach : JobComponentSystem
{
    //每帧执行
    protected override JobHandle OnUpdate(JobHandle inputDependencies)
    {
        float deltaTime = Time.DeltaTime;

        // Schedule job to rotate around up vector
        var jobHandle = Entities.ForEach((ref Rotation rotation, in RotationSpeed_ForEach rotationSpeed) =>
        {
            rotation.Value = math.mul(
             math.normalize(rotation.Value),
             quaternion.AxisAngle(math.up(), rotationSpeed.RadiansPerSecond * deltaTime));
        }
   ).Schedule(inputDependencies);

        // Return job handle as the dependency for this system
        return jobHandle;
    }
}

 

上面说了,System不用挂在场景中,那它为什么能运行,让我们的方块转呢(运行后看到,方块真的在转   疑惑脸)

这是因为:

ECS中有一个很基本的东西——世界(World)。

整个游戏过程中可以有多个世界,而ECS会自动为我们创建一个默认世界(可以关闭自动创建)。

默认创建的世界(World)包含了实体管理器(EntityManager),以及项目中所有可用的系统(System)。【这时我们写的System就运行啦】

这也就解释了为什么我们的System类会自动被执行,这因为它们被添加到了默认的世界中。至于怎么添加的,我们就先不管了(用了反射)。

 

 

上文的 S 讲了一种 Entities.ForEach 筛选组件的方法,这种方法是对一个个实体进行筛选,下篇我们讲讲另一个筛选机制,对块进行筛选 。

 

 

本节到此结束!

Enjoy~

你可能感兴趣的:(#,Entitas)