Unity DOTS 架构下的高性能游戏开发实践

深入 Entity Component System 架构,探索 Unity 高性能开发的正确姿势。

DOTS 概述

DOTS(Data-Oriented Technology Stack)是 Unity 近年来最重要的架构变革。它包含三个核心组件:

三者结合,可以让游戏性能提升一个数量级。

Entity Component System 基础

核心概念

ECS 与传统 OOP 的最大区别在于数据与逻辑的分离:

// Component:纯数据,无逻辑
public struct Position : IComponentData
{
    public float3 Value;
}

// System:纯逻辑,无数据
public partial struct MovementSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        foreach (var (pos, vel) in
            SystemAPI.Query<RefRW<Position>, RefRO<Velocity>>())
        {
            pos.ValueRW += vel.ValueRO * SystemAPI.Time.DeltaTime;
        }
    }
}

组件类型

组件类型用途内存布局
IComponentData可读写组件紧凑数组
IEnableableComponent可开关组件位掩码
ISharedComponentData共享组件按值分组
BufferElementData动态数组连续内存

Job System 深度应用

IJobEntity:ECS 查询的并行化

[BurstCompile]
public partial struct CollisionJob : IJobEntity
{
    public float DeltaTime;

    void Execute(ref Position pos, in Velocity vel, in Collider col)
    {
        pos.Value += vel.Value * DeltaTime;
        // 碰撞检测逻辑...
    }
}

Job 依赖管理

public partial struct GameSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        var job1 = new MovementJob().ScheduleParallel(state.Dependency);
        var job2 = new CollisionJob().ScheduleParallel(job1);
        var job3 = new RenderJob().Schedule(job2);
        state.Dependency = job3;
    }
}

Burst Compiler 优化技巧

使用 SIMD 指令

[BurstCompile(FloatMode = FloatMode.Fast)]
public struct SimdJob : IJob
{
    [ReadOnly] public NativeArray<float4> Input;
    [WriteOnly] public NativeArray<float4> Output;

    public void Execute()
    {
        for (int i = 0; i < Input.Length; i++)
        {
            Output[i] = math.sqrt(Input[i] * Input[i] + 1.0f);
        }
    }
}

实战案例:万人同屏

在某 SLG 项目中,需要同时渲染 10000+ 单位的战斗场景。

性能对比

场景MonoBehaviourDOTS提升
1000 单位45 FPS120 FPS2.7x
5000 单位12 FPS90 FPS7.5x
10000 单位3 FPS60 FPS20x

踩坑记录

  1. 主线程访问:ECS World 只能在主线程访问,Job 中无法直接创建/销毁 Entity。需要使用 EntityCommandBuffer。
  2. 内存对齐:Burst 要求数据按 16 字节对齐。自定义结构体注意内存布局。
  3. 编译时间:Burst 编译会显著增加编译时间,建议在开发阶段关闭。

总结

DOTS 是 Unity 性能优化的终极武器,但它不是银弹。适合大量同类实体(RTS、弹幕游戏、模拟类)和计算密集型逻辑。不适合 UI 系统和少量实体的简单游戏。掌握 DOTS 需要转变思维方式——从面向对象到面向数据。

← 回到文章列表