「这是我参与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 : MonoBehaviour
{
public float Speed;
}
// 行为:继承自ComponentSystem来处理旋转操作
class RotatorSystem : ComponentSystem
{
struct 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说明中展开.