· unity unity ecs · 6 min read

Giới thiệu Unity ECS & DOTS Architecture

Khi bắt đầu học tập Unity, mọi người thường bắt đầu với MonoBehaviour. Tuy nhiên, khi dự án trở nên phức tạp hoặc đòi hỏi hiệu suất cao (ví dụ như game có nhiều đối tượng, môi trường rộng lớn, hoặc cần tối ưu), MonoBehaviour bộc lộ nhiều vấn đề. Vì vậy, Unity giới thiệu ECS (Entity Component System) và DOTS (Data-Oriented Technology Stack) để giải quyết những vấn đề trên.

Khi bắt đầu học tập Unity, mọi người thường bắt đầu với MonoBehaviour. Tuy nhiên, khi dự án trở nên phức tạp hoặc đòi hỏi hiệu suất cao (ví dụ như game có nhiều đối tượng, môi trường rộng lớn, hoặc cần tối ưu), MonoBehaviour bộc lộ nhiều vấn đề. Vì vậy, Unity giới thiệu ECS (Entity Component System) và DOTS (Data-Oriented Technology Stack) để giải quyết những vấn đề trên.

Giới thiệu về Seri

Seri bài viết này sẽ giúp bạn tiếp cận và làm chủ kiến trúc ECS (Entity Component System) cùng DOTS (Data-Oriented Technology Stack) trong Unity. Qua từng bài, bạn sẽ được hướng dẫn từng bước từ lý thuyết nền tảng, cách cài đặt môi trường, đến thực hành xây dựng các ví dụ thực tế. Mục tiêu của seri là giúp bạn hiểu rõ sự khác biệt giữa cách làm truyền thống (MonoBehaviour) và cách tiếp cận mới với ECS, đồng thời khai thác tối đa hiệu năng mà DOTS mang lại cho các dự án Unity quy mô lớn. Nếu bạn muốn phát triển game hiệu suất cao, dễ mở rộng và bảo trì, đây là seri dành cho bạn!

Trong bài viết đầu tiên này, chúng ta sẽ cùng tìm hiểu:

  • Các khái niệm cơ bản trong về Entity Component System
  • Hiểu cách cài đặt Unity Project với ECS
  • Tạo Entity HelloWorld đầu tiên dựa vào các khái niệm đã được trình bày

Giới thiệu về Entity Component System

Entity Component System (ECS) là một kiến trúc lập trình hiện đại được Unity phát triển nhằm tối ưu hiệu năng và khả năng mở rộng cho các dự án game lớn. Thay vì tổ chức code theo kiểu hướng đối tượng truyền thống (OOP) với các class kế thừa từ MonoBehaviour, ECS chia nhỏ logic thành ba phần riêng biệt:

  • Entity: Là các đối tượng trừu tượng trong game, chỉ đơn giản là một ID, không chứa dữ liệu hay logic.
  • Component: Chỉ chứa dữ liệu thuần túy (data), không có hành vi. Mỗi entity có thể gắn nhiều component khác nhau để mô tả trạng thái hoặc thuộc tính.
  • System: Chứa toàn bộ logic xử lý, thực hiện các thao tác trên các entity có các component phù hợp.

Cách tiếp cận này giúp tận dụng tối đa khả năng xử lý song song của CPU, tối ưu bộ nhớ, và dễ dàng mở rộng, bảo trì dự án. ECS là nền tảng cốt lõi của DOTS (Data-Oriented Technology Stack), giúp Unity xử lý một lượng lớn đối tượng một cách hiệu quả mà không bị giới hạn bởi các vấn đề của MonoBehavior truyền thống. Mình sẽ đào sâu hơn về vấn đề này ở những bài viết tiếp theo.

Các bước setup ECS với một dự án mới trong Unity

Bạn có thể tham khảo tài liệu chính thức của Unity tại địa chỉ này. Mình sẽ tóm tắt một số chi tiết hơn ở bên dưới.

Bước 1: Tạo Project mới

  1. Mở Unity Hub
  2. Tạo project mới với Unity 6000.0.45f1 LTS hoặc phiên bản mới hơn
  3. Chọn template “2D Core” hoặc “3D Core”

Theo dõi giao diện ở phần hình ảnh bên dưới.

Giao diện trên Unity

Bước 2: Install DOTS Packages

  1. Mở Window > Package Manager
  2. Chuyển sang Unity Registry
  3. Install các packages sau:
  • com.unity.entities
  • com.unity.entities.graphics
  • com.unity.physics

Unity Package Manager

Hoặc thêm những package sau vào file manifest.json trong thư mục Packages

{
  "dependencies": {
    "com.unity.entities": "1.3.14",
    "com.unity.entities.graphics": "1.4.12",
    "com.unity.physics": "1.3.14",
    "com.unity.burst": "1.8.21",
    "com.unity.mathematics": "1.3.2",
    "com.unity.collections": "2.5.7"
  }
}

Bước 3: Tắt Domain Reloading trong Unity

Để đạt được hiệu suất tốt với ECS, Untiy đề suất tắt domain reloading

Để tắt Domain Reloading, bạn làm theo hướng dẫn sau:

  1. Mở Edit > Project Settings > Editor
  2. Ở mục Enter Play Mode Settings > When Entering Play Mode, chọn Reload Scene only

Disable Domain Reload

Một ví dụ về HelloWorld ECS

Hãy cùng bắt đầu với một ví dụ HelloWorld đơn giản để bạn dễ hình dung cách hoạt động của ECS. Để bắt đầu, chúng ta sẽ cần tạo một component thông qua MonoBehaviour và Baking process.

Định nghĩa Component và Authoring MonoBehaviour

using Unity.Entities;
using Unity.Mathematics;
using UnityEngine;

// File: HelloWorldAuthoring.cs
public class HelloWorldAuthoring : MonoBehaviour
{
    [SerializeField] private float speed = 5f;

    class Baker : Baker<HelloWorldAuthoring>
    {
        public override void Bake(HelloWorldAuthoring authoring)
        {
            var entity = GetEntity(TransformUsageFlags.Dynamic);
            AddComponent(entity, new HelloWorldComponent
            {
                Speed = authoring.speed
            });
        }
    }
}

// Định nghĩa Component
public struct HelloWorldComponent : IComponentData
{
    public float Speed;
}

Baking trong Unity ECS là quá trình chuyển đổi dữ liệu từ GameObject sang Entity trước khi chạy, giúp tối ưu hiệu suất. Như đoạn code ở phía trên. Một GameObject tên HelloWorldAuthoring được tạo và sẽ được chuyển sang HelloWorldComponent thông qua quá trình Baking được tạo trong class Baker.

System Implementation

using Unity.Entities;
using Unity.Mathematics;
using Unity.Transforms;
using Unity.Burst;

// File: HelloWorldSystem.cs
[BurstCompile]
public partial struct HelloWorldSystem : ISystem
{
    public void OnUpdate(ref SystemState state)
    {
        float deltaTime = SystemAPI.Time.DeltaTime;

        foreach (var (transform, helloWorld) in SystemAPI.Query<RefRW<LocalTransform>, RefRO<HelloWorldComponent>>())
        {
            // Di chuyển entity theo trục X
            transform.ValueRW.Position.x += helloWorld.ValueRO.Speed * deltaTime;

            // Reset vị trí khi đi quá xa
            if (transform.ValueRO.Position.x > 10f)
            {
                transform.ValueRW.Position.x = -10f;
            }
        }
    }
}

Đoạn code này là một vòng lặp trong Unity ECS System, dùng để di chuyển các entity có component LocalTransform và HelloWorldComponent theo trục X với tốc độ xác định. Nếu vị trí X vượt quá 10, nó sẽ được reset về -10. Mục đích là minh họa cách xử lý logic di chuyển cho nhiều entity trong ECS.

Test trong SubScene

SubScene là gì? Tại sao nên test trong SubScene?

SubScene là một phần đặc biệt trong Scene chính, dùng để chứa các GameObject được chuyển đổi sang Entity thông qua hệ thống baking process của Unity ECS.

Tại sao cần dùng SubScene khi làm việc với ECS?

  • Chuyển đổi GameObject thành Entity tự động: Khi đặt GameObject có component authoring (ví dụ HelloWorldAuthoring) vào SubScene, Unity sẽ tự động bake nó thành Entity khi bạn enter Play Mode hoặc build.
  • Hiệu năng cao hơn: SubScene có thể được streaming và load theo nhu cầu, phù hợp với game có thế giới lớn hoặc nhiều phần cần quản lý riêng biệt.
  • Không lẫn lộn với MonoBehaviour truyền thống: Giữ rõ ràng giữa phần ECS và phần không ECS trong project.
  • Dễ debug và kiểm tra riêng biệt: Mỗi SubScene có thể test độc lập mà không ảnh hưởng đến logic của Scene chính.

Tóm lại: Nếu bạn đang sử dụng Unity ECS (Entities), bạn nên test entity, component, system trong SubScene, vì đó là môi trường thiết kế riêng cho workflow của DOTS, đảm bảo mọi thứ được chuyển đổi đúng cách và hoạt động như mong đợi.

Tóm tắt

Trong bài này, chúng ta đã tìm hiểu:

  • Giới thiệu tổng quan về kiến trúc ECS (Entity Component System) và DOTS trong Unity, lý do nên dùng thay cho MonoBehaviour truyền thống. Hướng dẫn các bước tạo mới một dự án Unity và cài đặt các package cần thiết để sử dụng ECS/DOTS.
  • Hướng dẫn các bước tạo mới một dự án Unity và cài đặt các package cần thiết để sử dụng ECS/DOTS.
  • Trình bày cách định nghĩa Component, Authoring MonoBehaviour và quá trình Baking chuyển đổi GameObject sang Entity.
  • Minh họa cách xây dựng một System đơn giản để xử lý logic di chuyển cho nhiều entity bằng ECS.
  • Giải thích vai trò của SubScene trong workflow ECS và khuyến nghị nên test entity, component, system trong SubScene để đảm bảo hiệu quả và đúng quy trình DOTS.

Phần tiếp theo

Trong phầm tiếm theo, chúng ta sẽ tìm hiểu sâu hơn về ECS, DOTS và cách ECS tăng cường hiệu năng của hệ thống

Back to Blog