DOTS/ECS 迁移之后我学到的东西
我们把一个生产项目的一部分迁到了 ECS,帧时间下降了 34%。但收益并不来自我们预期的地方。
我们为什么迁移
屏幕上同时有接近 3000 个移动实体,性能分析器顶部每次都是同一个东西:MonoBehaviour.Update 调用的总和,以及它们引起的缓存未命中。
我们从来没打算把所有东西都搬到 ECS。我们只迁移了数量多、形态统一、密集的部分:子弹、集群单位、粒子逻辑。
真正的收益在内存布局
所有人都在谈 Burst 和 SIMD。在我们的测量里,差距并不来自那里,而是来自数据在内存中连续排列。
从堆里逐个读取 3000 个对象,与从一个数组里顺序读取 3000 个位置,在完全相同的数学运算下产生了最高 8 倍的时间差。
混合架构的代价
因为我们没有完全转向 ECS,就得在两个世界之间搭桥。这座桥带来的工作量远超预算。
我的建议是:一开始就把边界划清楚。哪些系统在 ECS 一侧、哪些留在传统一侧、它们之间的数据流是不是单向的 —— 在写代码之前就决定好。
[BurstCompile]
public partial struct MoveSystem : ISystem
{
[BurstCompile]
public void OnUpdate(ref SystemState state)
{
float dt = SystemAPI.Time.DeltaTime;
foreach (var (xf, vel) in
SystemAPI.Query<RefRW<LocalTransform>, RefRO<Velocity>>())
{
xf.ValueRW.Position += vel.ValueRO.Value * dt;
}
}
}
csharpMoveSystem.cs
什么时候不值得
如果实体数量没超过几百,ECS 带来的复杂度会盖过收益。如果团队不熟悉 ECS,还要把学习成本算进去。
我用一个简单的阈值来判断:如果超过 500 个对象执行相同行为且每帧更新,那就值得迁移。