
前言
今天要推薦的是 Unity DOTS(Data-Oriented Technology Stack),一套資料驅動的開發工具組,為 Unity 遊戲帶來前所未有的高效能突破!
不同於傳統以 GameObject 為基礎的開發方式,DOTS 透過【ECS】、【Jobs】與【Burst Compiler】打造出極致的運行效率,特別適合需要處理【大量實體】、【複雜運算】或【大規模場景】的遊戲。
不論你正在開發【百萬物件的模擬遊戲】、【即時戰略 AI 控制系統】或【開放世界動態生態系統】,DOTS 都能【解放 CPU 能力】、【減少 GC 開銷】,甚至改變你對 Unity 效能的想像!
本篇文章將從 DOTS 的核心結構講起,介紹如何【安裝】與【啟用】 ECS 模組,並透過簡單案例逐步實作旋轉效果,讓你快速掌握 DOTS 的基礎用法!

Unity DOTS 插件介紹
DOTS(Data-Oriented Technology Stack)是 Unity 官方推出的高效能開發工具組,專為【解決大型場景】、【高頻運算】與【效能瓶頸問題】而設計。
從 Unity 2022 起,DOTS 中的 Entities 模組已進入穩定階段,在 Unity 6 中更可直接透過 Package Manager 安裝使用。
DOTS 適用於【URP】或【HDRP】渲染管線,可與現代化圖形流程無縫整合,支援【大量實體處理】與【高效能資料驅動邏輯】。
搭配 Entities Graphics 套件,可實現高效能的 ECS 實體渲染,讓你在場景中輕鬆操作數千甚至數萬個物件而不卡頓。

功能特色
- 高效資料導向架構
DOTS 採用 ECS 模型,讓【資料】與【邏輯】完全分離。實體(Entity)儲存資料,系統(System)負責運算,能精準控制【記憶體配置】與【資料存取順序】,大幅提升 CPU 【快取命中率】與【執行效率】,特別適合需要大量實體處理的遊戲開發。 - 全自動多執行緒排程
透過 Jobs System,開發者能輕鬆撰寫可平行執行的邏輯,Unity 會自動處理【執行緒安全】與【排程分配】,無需手動管理【鎖定】與【同步】。搭配 Burst Compiler 使用時,能進一步壓榨多核心 CPU 效能,讓大量邏輯同時執行不卡頓。 - 易於擴展與效能偵錯
DOTS 支援【SubScene 編輯】、【實體屬性檢視】與【System 運作追蹤】,可與 Unity Profiler 深度整合進行分析。開發者能快速定位效能瓶頸,針對【單一組件】或【系統】進行微調,也能彈性設計可重用的 ECS 模組,利於大型專案擴展。
適用場景
- 大規模實體模擬
適用於需要同時管理數千甚至數萬個物件的場景,例如【即時戰略遊戲中的士兵單位】、【開放世界遊戲中的動態生態系統】或【城市建造模擬遊戲中的市民與交通行為】。 - 高頻率邏輯運算系統
在遊戲中需要持續進行大量【數學】或【物理】計算的場景,如【物理模擬】、【粒子系統】、【路徑規劃】或【AI 行為演算】等。 - 資源受限的平台開發
特別適合開發【行動裝置】或【VR 裝置】等效能有限的平台,透過【Burst Compiler】與【ECS】的記憶體最佳化特性,是針對效能敏感應用的最佳選擇。

Unity DOTS 核心組成
- ECS(Entity Component System):以資料為中心,使用實體(Entities)、元件(Components)和系統(Systems)來組織和管理數據,旨在提升記憶體存取效率。
- Jobs System:透過多執行緒並行化任務,能將大量的運算工作分配給多個處理器核心,進而提升效能。
- Burst Compiler:透過靜態分析程式碼並優化產生的機器碼,可大幅提升 CPU 運算效能。
Unity DOTS 解決傳統問題的痛點
1.優化內存佈局:
DOTS 中的 ECS 透過將資料按組件組織,並優化內存佈局,能夠讓數據按照連續區塊儲存在內存中,從而大幅提高 CPU 緩存命中率,減少緩存未命中的問題。
這種資料佈局優化使得大量實體的處理能更有效率,尤其涉及大規模遊戲世界或複雜場景時。
2.減少垃圾回收及內存管理開銷:
DOTS 避免了傳統物件實例化和銷毀的開銷,透過使用物件池(或「內存分配池」)來重複使用實體,減少 GC(垃圾回收)的頻繁調用,從而降低效能損耗。
3.提高並行運算能力:
DOTS 通過 Jobs System 將任務分割並並行化,能夠充分利用多核心 CPU 的運算能力。開發者可以輕鬆編寫多執行緒代碼,而無需擔心執行緒安全性問題,系統會自動管理並行化。
Burst Compiler 進一步優化了程式碼的執行效率,確保多執行緒任務能夠最大化地提高效能。
4、高效率的系統和組件設計:
DOTS 的 ECS 模式簡化了邏輯和資料的分離,讓每個系統(System)只處理資料(Components)中的某一部分。
透過這種設計,開發者可以更方便地對資料進行分區、篩選和批次處理,提高程式的執行效率。
這種「數據驅動」模型使得開發者可以更直觀地分析和優化效能瓶頸。
5、易於擴展和優化:
DOTS 提供了一個高效的調試和分析工具鏈(如 Profiler),可幫助開發者即時監控和調整效能瓶頸。
同時,ECS 和 Jobs 使得開發者能夠在程式碼層級進行細粒度的優化。
Unity DOTS 安裝
我這裡使用的是最新的 Unity6,Unity6 Entities 已經從預覽版放出來了(貌似 2022 版本就不是預覽版了),直接搜尋安裝即可。
如果你用的是其他,可能方法各有不同,需要自行去查找如何進行安裝
(注意:推薦在 URP 或者 hdrp 中使用 DOTS)

安裝 Entities Graphics,實體的 DOTS 顯示包。

Unity DOTS 在編輯器下建置 ECS World
之前的流程是在GameObject 掛上一個 Convert To Entity 的元件,就能轉換成 Entity。
不過新的流程修改了,這個元件被移除了,新的流程如下:
在 Hierarchy 視窗下右鍵,選擇 New Subscene > Empty Scene,建立一個新的 SubScene。

現在只要在這個 SubScene 裡面的東西,就會自動轉換成實體(Entity)。

Unity DOTS 看 Entity 的屬性
之前這塊是在 EntityDebugger 裡面的,相信大家已經發現了,在 Entities 1.0 中,已經沒有這個 EntityDebugger 了。
查看Entity 的方法如下:
直接 Play,然後在 Hierarchy 中選擇對應的 Cube(已經轉成實體)。
你可以透過右上角查看實體情況。

裡面你就能看到 Entity 的屬性了。

可以看到這裡加了很多 Data,除了 LTW 相關的就是渲染相關的,東西還是非常多的。
不過這裡我們都完全不需要管它,只要知道這裡能看各 Data 的資料就 OK 了。
Unity DOTS 最簡單的 ecs 程序
這裡我我帶大家來實現一個簡單的印刷效果。
傳統方式
傳統方式應該不用我介紹太多了,相信大家用的已經很多了。
public class test : MonoBehaviour
{
void Update()
{
Debug.Log("傳統方式打印");
}
}
ecs 方式
要使用 Unity DOTS 實作類似傳統方式的 Update() 列印功能,首先需要了解如何在 DOTS 中使用 ECS(Entity Component System)。
DOTS 的核心思想是將資料(組件)與行為(系統)分離,使用不同的方式來處理每個畫面更新的邏輯。
1. 建立一個元件(Component)
定義一個結構體,表示一個組件,用於儲存印刷訊息。
using Unity.Collections;
using Unity.Entities;
public struct PrintMessageComponent : IComponentData {
// 固定長度字符串,用於存儲打印的消息
public FixedString128Bytes printData;
}
2. 建立一個系統(System)
定義一個系統,處理所有包含 PrintMessageComponent 的實體。
using Unity.Entities;
using Unity.Transforms;
using UnityEngine;
partial class PrintMessageSystem : SystemBase {
// 系統每幀更新時會調用此方法
protected override void OnUpdate()
{
// 查詢所有包含 LocalTransform 和 PrintMessageComponent 的實體 foreach ((RefRW<LocalTransform> localTransform, RefRO<PrintMessageComponent> printMessageComponent)
in SystemAPI.Query<RefRW<LocalTransform>, RefRO<PrintMessageComponent>>())
{
// 打印每個實體中的 printMessageComponent 內容
Debug.Log(printMessageComponent.ValueRO.printData);
}
}
}
3. 觸發打印
定義一個 MonoBehaviour 腳本,用於在場景中產生實體。
using Unity.Entities;
using UnityEngine;
public class EntitySpawner : MonoBehaviour
{
//用於在 Inspector 面板中輸入的字符串值
public string value;
// 內部類 Baker,用於將 MonoBehaviour 轉換為實體
private class Baker : Baker<EntitySpawner>{
// Bake 方法會在編輯器模式下調用,將 MonoBehaviour 組件數據轉為實體組件數據
public override void Bake(EntitySpawner authoring){
// 創建一個動態使用的實體
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
// 給實體添加 PrintMessageComponent 組件,並設置其 printData 為 authoring 中的值
AddComponent(entity, new PrintMessageComponent{
printData = authoring.value,
});
}
}
}
4. 新建空物件掛載腳本

效果。

Unity DOTS 旋轉組件
定義一個旋轉速度組件,用於儲存每個實體的旋轉速度。
using Unity.Entities;
// 定義一個實現 IComponentData 接口的結構體,用於表示旋轉速度
public struct RotateSpeed : IComponentData {
// 旋轉速度的數值
public float value;
}
定義一個旋轉速度的 Authoring 類,用於在 Unity 編輯器中設定旋轉速度的值。
public class RotateSpeedAuthoring : MonoBehaviour {
// 用於設置旋轉速度的公共字段
public float value;
// Baker 類用於將 MonoBehaviour 組件轉換為 ECS 的組件數據
private class Baker : Baker<RotateSpeedAuthoring>{
// 該方法在實體生成時被調用,負責將 MonoBehaviour 上的屬性數據化為 ECS 組件
public override void Bake(RotateSpeedAuthoring authoring){
// 獲取當前的實體,並設置為動態使用(TransformUsageFlags.Dynamic)
Entity entity = GetEntity(TransformUsageFlags.Dynamic);
// 為實體添加 RotateSpeed 組件,並將作者的旋轉速度值傳遞給它
AddComponent(entity, new RotateSpeed{
value = authoring.value, // 設置旋轉速度
});
}
}
}
定義一個旋轉立方體系統,負責處理與旋轉速度相關的邏輯。
public partial struct RotatingCubeSystem : ISystem
{
// 系統創建時調用的方法
public void OnCreate(ref SystemState state){
// 在系統創建時要求必須有 RotateSpeed 組件才能進行更新
state.RequireForUpdate<PrintMessageComponent>();
}
// 系統更新時調用的方法
void OnUpdate(ref SystemState state)
{
// 查詢所有包含 LocalTransform 和 RotateSpeed 組件的實體
foreach ((RefRW<LocalTransform> localTransform, RefRO<RotateSpeed> rotateSpeed)
in SystemAPI.Query<RefRW<LocalTransform>, RefRO<RotateSpeed>>())
{
// 通過當前的旋轉速度(rotateSpeed)來更新實體的旋轉
// 使用 RotateY 方法按照 Y 軸旋轉,旋轉角度由旋轉速度與 DeltaTime 計算得出
localTransform.ValueRW =localTransform.ValueRO.RotateY(rotateSpeed.ValueRO.value * SystemAPI.Time.DeltaTime);
}
}
}
掛載腳本。

效果。

Unity DOTS 最佳化
新增 OnCreate,當系統第一次被建立時,OnCreate 方法會被呼叫。
在此方法中,呼叫 state.RequireForUpdate<RotateSpeed>() 來確保系統只會在實體中包含 RotateSpeed 元件時進行更新。
這保證了只有需要旋轉的實體會觸發系統的更新。
using Unity.Transforms;
using Unity.Entities;
// 定義一個旋轉立方體系統,負責處理與旋轉速度相關的邏輯
public partial struct RotatingCubeSystem : ISystem
{
// 系統創建時調用的方法
public void OnCreate(ref SystemState state){
// 在系統創建時要求必須有 RotateSpeed 組件才能進行更新
state.RequireForUpdate<RotateSpeed>();
}
// 系統更新時調用的方法
void OnUpdate(ref SystemState state)
{
// 查詢所有包含 LocalTransform 和 RotateSpeed 組件的實體
foreach ((RefRW<LocalTransform> localTransform, RefRO<RotateSpeed> rotateSpeed)
in SystemAPI.Query<RefRW<LocalTransform>, RefRO<RotateSpeed>>())
{
// 通過當前的旋轉速度(rotateSpeed)來更新實體的旋轉
// 使用 RotateY 方法按照 Y 軸旋轉,旋轉角度由旋轉速度與 DeltaTime 計算得出
localTransform.ValueRW = localTransform.ValueRO.RotateY(rotateSpeed.ValueRO.value * SystemAPI.Time.DeltaTime);
}
}
}
Unity DOTS 多執行緒並行執行
系統仍在主執行緒執行。

修改代碼,使用 rotatingCubeJob.ScheduleParallel(); 系統在多執行緒並行執行。
public partial struct RotatingCubeSystem : ISystem
{
// 系統創建時調用的方法
public void OnCreate(ref SystemState state)
{
// 在系統創建時要求必須有 RotateSpeed 組件才能進行更新
state.RequireForUpdate<RotateSpeed>();
}
// 系統更新時調用的方法
void OnUpdate(ref SystemState state)
{
// 創建旋轉立方體的工作作業,並傳遞時間增量信息
RotatingCubeJob rotatingCubeJob = new RotatingCubeJob
{
deltaTime = SystemAPI.Time.DeltaTime // 獲取每幀的時間增量
};
// 調度工作作業
// rotatingCubeJob.Schedule();
// state.Dependency = rotatingCubeJob.Schedule(state.Dependency);
//在多個線程上並行
rotatingCubeJob.ScheduleParallel();
}
// 定義旋轉立方體的作業,IJobEntity 用於操作實體
{
public float deltaTime; // 存儲時間增量,用於旋轉計算
// 執行作業時的具體操作:旋轉實體
public void Execute(ref LocalTransform localTransform, in RotateSpeed rotateSpeed)
{
// 旋轉的倍率系數
float power = 1f;
// 根據旋轉速度和時間增量來旋轉實體
localTransform = localTransform.RotateY(rotateSpeed.value * deltaTime * power);
}
}
}

Unity DOTS 使用 Burst 編譯器優化效能
加入關鍵字 [BurstCompile] 即可,使用 Burst 編譯器優化效能。
![加入關鍵字 [BurstCompile] 即可,使用 Burst 編譯器優化效能。](/upload/1338/ckeditor_images/710bfb96-7091-482a-b090-5389126ebc49.webp)
記得查看 Burst 編譯器是否勾選使用。

Unity DOTS 屏蔽系統間的干擾
前面我們實現了一個打印和旋轉系統,雖然我們的打印功能已經被隱藏了。

但是如果通過在打印系統 OnUpdate 裡打印日誌。

你會發現系統其實仍然在執行。

我們可以加上 [DisableAutoCreation] 特性,屏蔽該系統的干擾,這樣這個系統就不會再運行了。
![我們可以加上 [DisableAutoCreation] 特性,屏蔽該系統的干擾,這樣這個系統就不會再運行了。](/upload/1338/ckeditor_images/56d1ce6a-9f67-425d-8372-28f408706c1a.webp)
Unity DOTS 偵錯視窗

- Hierarchy : 顯示目前場景中的實體訊息
- Components :顯示所有 ComponentData 的結構體資訊。
- Systems:顯示目前執行的所有System 訊息,能看到其使用了哪些實體。
- Archetypes:顯示原型資訊。
- Journaling:日誌記錄,可以顯示用了哪些方法,有哪些實體、ComponentData 之類,應該是可以用來分析效能,但我還沒有仔細研究。
Unity DOTS 後續
DOTS 基礎篇就先寫到這裡了,如果你有興趣也可以用傳統方式進行效能比較,這裡我就不寫了。
後續我看有時間再考慮寫一些進階知識或是 DOTS 項目實戰內容,可以敬請期待一下。
Unity DOTS 相關介紹 & 教學影片
Connecting the DOTS: Let’s make a game with Entities | Unite 2024
Learn Unity DOTS! (FREE Tutorial Course)
UNITY DOTS (ECS) - Beginners Guide
Unity DOTS 效能咒術師相關網站 & 插件下載點
【DOTS】
官方文檔:DOTS
GitHub 下載連結:DOTS
————————————————
更多好用插件:【Unity 好用插件推薦】持續更新,一起讓遊戲開發事半功倍!
本文原創(或整理)於亞洲電玩通,未經作者與本站同意不得隨意引用、轉載、改編或截錄。
特約作家簡介
支持贊助 / DONATE
亞洲電玩通只是很小的力量,但仍希望為復甦台灣遊戲研發貢獻一點動能,如果您喜歡亞洲電玩通的文章,或是覺得它們對您有幫助,歡迎給予一些支持鼓勵,不論是按讚追蹤或是贊助,讓亞洲電玩通持續產出,感謝。
BTC |
![]() |
352Bw8r46rfXv6jno8qt9Bc3xx6ptTcPze |
|
ETH |
![]() |
0x795442E321a953363a442C76d39f3fbf9b6bC666 |
|
TRON |
![]() |
TCNcVmin18LbnXfdWZsY5pzcFvYe1MoD6f |