Kiến trúc: Thiết kế Hướng Dữ liệu và ECS

Tags:
Architecture
Optimization
Performance
DOTS
ECS

C# Code

// Đây là snippet mang tính giải thích khái niệm, không phải code chạy trực tiếp.

// --- Thiết kế Hướng Đối tượng (Object-Oriented Design - OOD) thông thường ---
/*
class Enemy : MonoBehaviour {
    // Dữ liệu và hành vi được đóng gói trong cùng một class.
    float health;
    float speed;
    Vector3 position;

    void Move() { ... }
    void Attack() { ... }

    void Update() {
        Move();
        Attack();
    }
}
// -> Vấn đề: Khi có hàng ngàn Enemy, CPU phải nhảy qua lại giữa các vùng nhớ khác nhau
// cho mỗi đối tượng, gây ra cache misses và làm chậm hệ thống.
*/

// --- Thiết kế Hướng Dữ liệu (Data-Oriented Design - DOD) với ECS ---

// 1. Component: Chỉ chứa dữ liệu, không có hành vi (struct).
public struct Position : IComponentData {
    public float3 Value;
}
public struct Velocity : IComponentData {
    public float3 Value;
}
public struct Health : IComponentData {
    public float Value;
}

// 2. System: Chỉ chứa hành vi, xử lý các component.
//    Hệ thống này sẽ chạy trên tất cả các Entity có cả Position và Velocity.
[BurstCompile]
public partial struct MovementSystem : ISystem {
    public void OnUpdate(ref SystemState state) {
        float deltaTime = SystemAPI.Time.DeltaTime;

        // Chạy song song trên nhiều luồng
        new MovementJob { DeltaTime = deltaTime }.ScheduleParallel();
    }
}

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

    // Lấy tất cả Entity có Position và Velocity
    void Execute(ref Position position, in Velocity velocity) {
        position.Value += velocity.Value * DeltaTime;
    }
}

// 3. Entity: Một 'ID' để liên kết các component với nhau.

/*
* Lợi ích của DOD/ECS:
* - Cache-Friendly: Dữ liệu của cùng một loại component (ví dụ: tất cả Position) được lưu trữ
*   liền kề nhau trong bộ nhớ, giúp CPU truy xuất cực nhanh.
* - Parallelism: Các hệ thống có thể xử lý dữ liệu một cách độc lập và song song trên nhiều luồng CPU.
* - Code sạch hơn: Tách biệt rõ ràng giữa dữ liệu (Component) và hành vi (System).
* - Khó khăn: Yêu cầu thay đổi tư duy lập trình và có đường cong học tập dốc hơn so với OOP.
*/

Giới thiệu triết lý Thiết kế Hướng Dữ liệu (Data-Oriented Design) và cách nó được hiện thực hóa qua kiến trúc ECS (Entity Component System) trong DOTS của Unity để đạt được hiệu năng xử lý dữ liệu vượt trội.

Bình luận (0)

Bạn cần đăng nhập để có thể bình luận.

Chưa có bình luận nào. Hãy là người đầu tiên!

Bài viết liên quan

Hiểu cách C# và Unity quản lý hai vùng nhớ Stack và Heap là chìa khóa để tối ưu hiệu năng. Việc sử dụng sai `class` (Heap) thay vì `struct` (Stack) cho các dữ liệu nhỏ có thể tạo ra hàng ngàn 'rác' (garbage), khiến Garbage Collector (GC) phải hoạt động và gây giật, lag game.

Optimization
Performance
C#
Architecture

Hiểu rõ khi nào nên sử dụng `struct` thay cho `class` để giảm áp lực lên bộ nhớ và garbage collector, đặc biệt hữu ích cho các đối tượng dữ liệu nhỏ, bất biến.

Optimization
Performance
Architecture

LINQ rất mạnh mẽ nhưng có thể gây tốn hiệu năng nếu không sử dụng cẩn thận. Snippet này chỉ ra các mẹo và cạm bẫy khi dùng LINQ trong game.

Optimization
Performance
LINQ
Architecture

Giới thiệu về DOTS (Data-Oriented Technology Stack) bằng cách sử dụng Job System để thực hiện các tác vụ nặng song song trên nhiều luồng CPU và Burst Compiler để tối ưu hóa code C# thành mã máy cực nhanh.

Optimization
Performance
DOTS
Job System
Burst

Boxing là quá trình chuyển một Value Type (như int, float) lên Heap bằng cách 'gói' nó trong một object. Unboxing là quá trình ngược lại. Trong Unity, việc này xảy ra âm thầm và thường là nguyên nhân gây ra các vấn đề về Garbage Collection và sụt giảm FPS mà không ai ngờ tới.

Optimization
Performance
C#

So sánh các thuật toán sắp xếp như Bubble Sort, Insertion Sort và Quick Sort và khi nào nên sử dụng chúng trong game (ví dụ: sắp xếp bảng xếp hạng).

Algorithm
Architecture
Optimization

Giới thiệu về mẫu thiết kế Dependency Injection (DI) và tại sao nó giúp code của bạn dễ bảo trì, dễ test và giảm sự phụ thuộc cứng (hard dependencies).

Architecture
Design Pattern
Optimization

Hướng dẫn cài đặt và sử dụng Zenject, một framework Dependency Injection phổ biến cho Unity, để quản lý các phụ thuộc trong dự án một cách hiệu quả.

Architecture
Design Pattern
DI
Zenject
Optimization

Một hệ thống Object Pool đơn giản để tái sử dụng các đối tượng thay vì tạo và hủy liên tục, giúp tối ưu hiệu năng đáng kể, đặc biệt khi cần tạo nhiều đối tượng như đạn, kẻ địch.

Design Pattern
Object Pool
Optimization
Performance

Expression Trees là một tính năng C# nâng cao cho phép bạn biểu diễn code dưới dạng cây dữ liệu. Trong Unity, nó mở ra khả năng xây dựng các hệ thống phức tạp như trình tạo truy vấn động, hệ thống AI có thể sửa đổi hành vi tại runtime, hoặc các công cụ editor tùy chỉnh mà không cần sinh mã code mới.

Architecture
Algorithm
Optimization
C#