ECS框架的解析(什么是ECS框架)

一、ECS框架简介

ECS(Entity-Component-System)是一种游戏引擎开发中常见的架构,其主要思想是将游戏对象拆分为实体(Entity)、组件(Component)和系统(System)三个部分,分别处理不同的逻辑。在ECS架构中,实体仅仅是一个ID,而组件则是具体的属性,系统则用于处理这些属性。

以Unity为例,使用ECS框架可以提高游戏的性能,降低开发难度,提高游戏可玩性。其中,实体是一个GameObject,组件就是该GameObject上挂载的MonoBehaviour脚本,而系统则是用Job System编写的管理逻辑。下面我们将从组件、实体、系统三个方面详细讲解ECS框架。

二、ECS框架中的组件

组件是ECS框架中的核心,是游戏逻辑的具体表现。组件的表现形式是一个结构体,其中包含该组件的所有属性。一个实体可以拥有多个组件,通过组件的组合来表现实体的不同状态。

在Unity中,使用IComponentData接口或者Component基类来表示组件。其中,IComponentData接口只包含数据,而Component基类则可以继承MonoBehaviour,同时也包含一些函数接口(比如可以使用Start和Update函数)。


public struct Velocity : IComponentData {
    public float3 Value;
}
public class MoveSystem : JobComponentSystem {
    void OnUpdate () {
        Entities.
        ForEach ((ref Translation translation, in Velocity velocity) => {
            translation.Value += velocity.Value * Time.deltaTime;
        });
    }
}

上述代码展示了一个Velocity组件,其包含一个float3类型的速度值。同时,MoveSystem使用Job System实现了这个组件的计算逻辑。在这里,Entities.ForEach函数表示对于每个实体,都要执行后面的语句。其中,ref表示该参数即是输入又是输出参数,而in则表示该参数是只读参数,避免了多线程之间的数据冲突。

三、ECS框架中的实体

实体是ECS框架中最重要的概念,因为实体是游戏对象的具体表现形式。在ECS架构中,实体只是一个ID,所有实体的状态都由它所拥有的组件来决定。实体不包括任何行为,行为由组件和系统来完成。

在Unity中,Entity是通过EntityManager来管理的。EntityManager以实体的ID为索引,保存所有的实体信息。EntityManager还提供了一些函数接口,可以对实体进行增加、删除、查询等操作。


public class GameManager : MonoBehaviour {
    public static GameManager Instance;

    EntityManager entityManager;

    void Awake() {
        Instance = this;
        entityManager = World.DefaultGameObjectInjectionWorld.EntityManager;
    }

    public void CreateCube() {
        Entity entity = entityManager.CreateEntity(CubeArchetype);
        entityManager.SetComponentData(entity, new Translation { Value = new float3(Random.Range(-10,10),Random.Range(-10,10),0)});
        entityManager.SetComponentData(entity, new Velocity { Value = new float3(Random.Range(-10,10),Random.Range(-10,10),0)});
    }

    private void OnDestroy() {
        entityManager.DestroyEntity(Entities);
    }
}

上述代码展示了如何创建和销毁实体。其中,CreateCube函数创建了一个Cube实体,并将它的位置和速度设置为随机值。而OnDestroy函数则销毁了所有的实体。

四、ECS框架中的系统

系统是ECS框架中实际处理组件逻辑的部分,它们是本质上是依赖数据的代码片段,负责更新实体状态。每个系统专注于管理不同类型的组件,通过过滤器来获取匹配的实体并进行逻辑计算。

在Unity中,使用Job Component System编写系统,可以达到最佳的性能。Job Component System是一种基于Job System的高性能框架,利用了多线程的优势,实现了分离和并行计算。在系统中,可以使用Entities.ForEach函数来遍历匹配的实体和组件,或者通过JobHandle来处理大量的计算任务。


public struct RotationSpeed : IComponentData {
    public float Value;
}

public class RotationSystem : JobComponentSystem {
    [BurstCompile]
    struct RotationSpeedJob : IJobForEach {
        public float deltaTime;
        public void Execute(ref Rotation rotation, [ReadOnly] ref RotationSpeed speed) {
            rotation.Value = math.mul(math.normalize(rotation.Value), quaternion.AxisAngle(math.up(), speed.Value * deltaTime));
        }
    }
    protected override JobHandle OnUpdate(JobHandle inputDeps) {
        var job = new RotationSpeedJob {
            deltaTime = Time.deltaTime
        };
        return job.Schedule(this, inputDeps);
    }
}

上述代码展示了一个旋转系统,其包含一个RotationSpeed组件和一个Rotation组件。在Execute函数中,通过quaternion.AxisAngle函数计算旋转后的欧拉角,然后将结果赋给Rotation组件。

五、ECS框架的优缺点

优点:

1、性能优越。ECS框架可以充分利用 Job System 的多线程计算,提高游戏的性能。

2、代码可维护性高。在ECS框架中,同种类型的组件都是按照分类存放的,代码中的逻辑可以根据不同的系统来实现,更方便代码的维护和开发。

3、适合高并发场景。ECS的运行方式适合处理大量相似的结构,尤其适合高并发场景。

缺点:

1、学习曲线较陡峭。ECS框架和普通的游戏开发方法有较大的差异,需要一定的学习时间来适应。

2、不适合小型游戏。ECS框架适合大型游戏,因为它包含大量的组件和系统,对于小型游戏则有些繁琐。

3、不支持常规的Unity组件。在ECS框架中,仅支持IComponentData接口或者Component基类,无法很好地支持常规的Unity组件。

Published by

风君子

独自遨游何稽首 揭天掀地慰生平