Unity-ECS架构-01-初探

1,056 阅读3分钟

「这是我参与2022首次更文挑战的第9天,活动详情查看:2022首次更文挑战」。

作为一名优秀的开发者,对于技术的探求应该是永无止步的,如何让自己更进步,那就只有不停的学习,不停的充电.而这些都都是说起来容易做起来难,坚持才是难的地方 --蛙哈哈

什么是ECS

ECS ,即 Entity (实体) - Component (组件) - System (系统),是一种 组合优于继承 的设计模式.

Entity : 没有数据,没有行为,在游戏内存在的实体,也只是实体没有任何的行为.

Component : 只有数据,没有行为, Entity 会挂在若干 Component ,用来表示 Entity 有某些行为,并保存行为的数据

System (系统): 只有行为,没有数据,不同的 System 会筛选 Entity 身上不同的 Component ,并基于 Component 对 Entity 做不同的操作

graph LR
World --- 
	System --- System1
	System --- System2
World --- 
	Entity1 --- 
		Component --- Component1
		Component --- Component2
		Component --- Component3
		


World 就是一个所有 Entity 和 System 的集合, Component 拥有 Entity 的状态而没有行为能力, System 拥有个改变 Entity 的能力 但是并没有 Entity 的状态.

ECS的种类

HybridECS(混合ECS)

在现有OOP架构的基础上,修改为ECS架构.

在Unity中的表现为:在 Monobehaviour 和 GameObject 的基础上快速实现ECS的架构,实现数据和行为逻辑的分离.

主要是用来转换编程思想,没有很大的性能提升.

比如:

// 数据:可以在Inspector窗口中编辑的旋转速度值
class Rotator : MonoBehaviourpublic float Speed;
}
    
// 行为:继承自ComponentSystem来处理旋转操作
class RotatorSystem : ComponentSystemstruct Group// 定义该ComponentSystem需要获取哪些components
        public Transform Transform;
        public Rotator   Rotator;
    }

    override protected void OnUpdate()
    {
        // 这里可以看第一个优化点:
        // 我们知道所有Rotator所经过的deltaTime是一样的,
        // 因此可以将deltaTime先保存至一个局部变量中供后续使用,
        // 这样避免了每次调用Time.deltaTime的开销。
        float deltaTime = Time.deltaTime;

        // ComponentSystem.GetEntities<Group>可以高效的遍历所有符合匹配条件的GameObject
        // 匹配条件:即包含Transform又包含Rotator组件(在上面struct Group中定义)
        foreach (var e in GetEntities<Group>())
        {
            e.Transform.rotation *= Quaternion.AngleAxis(e.Rotator.Speed * deltaTime, Vector3.up);
        }
    }
}

优点:

  • 更好的兼容原来OOP架构的项目,降低转换的工作量,也降低了思维转换的坡度
  • 数据与行为的分离的方式,会让代码整体看起来更清晰
  • 系统对许多对象是可以进行批量操作的,避免了一些无意义的调用。(见上面deltaTime优化)

缺点:

  • 实例化时间并没有得到优化
  • 加载时间并没有得到优化
  • 数据是随机访问的,没有线性内存访问的高效性
  • 没有发挥多核功能
  • 没有SIMD

PureECS(纯ECS)

完全基于ECS理念而设计出来的ECS架构,即 Entity 既没有状态也没有行为, Component 只有状态, System 只有行为.

在Unity中的表现为完全抛弃 MonoBehaviour,不再使用 MonoBehaviour 的生命周期来控制 Entity 的状态,只使用ECS的架构

具体性能的提升,会在下面的Dots说明中展开.