ECS丨怎样写 ECS,及 ECS 的 ForEach 筛选机制

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

本系列博客地址:传送门

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

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

我们前文了解到。ECS是Entity(实体)、Component(只有数据的组件脚本)、System(只有方法的系统脚本)组成。

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

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

E:Entity

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

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

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

C:Component

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

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

[GenerateAuthoringComponent]特性:将该物体转化为实体。

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~

发布了335 篇原创文章 · 获赞 88 · 访问量 19万+

猜你喜欢

转载自blog.csdn.net/weixin_38239050/article/details/105504930
ECS