Thực Thể (Entity) Trong Kiến Trúc ECS - nói dối e blog

Thực Thể (Entity) Trong Kiến Trúc ECS

Tôi cho rằng mô hình ECS (Entity-Component-System) ra đời nhằm giải quyết những hạn chế tồn tại trong các mô hình hướng đối tượng truyền thống. Trong các hệ thống truyền thống, khi số lượng đối tượng lớn và các thuộc tính của chúng trở nên phức tạp, việc xử lý logic cho từng khía cạnh (aspect) của đối tượng đòi hỏi phải lọc ra các tập hợp con phù hợp từ tập hợp lớn các đối tượng. Điều này vừa làm giảm hiệu năng, vừa khiến các thuộc tính không liên quan trở nên phụ thuộc chặt chẽ vào nhau.

Mô hình ECS đã thay đổi cách tổ chức dữ liệu bằng cách tập hợp các dữ liệu cùng loại lại với nhau và thiết kế các hệ thống xử lý chuyên biệt chỉ làm việc trên những tập dữ liệu cụ thể. Trong đó:

  • Component đại diện cho tập hợp dữ liệu mô tả một khía cạnh cụ thể của đối tượng
  • System là hệ thống xử lý logic dành riêng cho một hoặc một nhóm khía cạnh nhất định

Vậy Entity trong kiến trúc này đóng vai trò gì? Theo quan điểm của tôi, Entity giải quyết ba vấn đề cốt lõi:

1. Quản lý vòng đời đối tượng
Khi các khía cạnh của đối tượng được tách thành các Component khác nhau và được lưu tập trung theo loại, điều này giúp giảm sự phụ thuộc giữa các System. Tuy nhiên, các Component này vẫn cần được quản lý như một thực thể thống nhất. Entity chính là chiếc cầu kết nối vòng đời của các Component liên quan. Việc xóa một Entity sẽ đồng nghĩa với việc loại bỏ toàn bộ Component liên quan đến nó khỏi hệ thống.

2. Thiết lập quan hệ giữa các thành phần
Một số hệ thống có thể chỉ cần làm việc với một loại Component duy nhất. Tuy nhiên, trong nhiều trường hợp, các hệ thống cần xử lý đồng thời nhiều khía cạnh của cùng một đối tượng. Ví dụ: Kết quả tính toán từ hệ thống vật lý về va chạm (Component A) cần được phản ánh vào thông tin vị trí không gian (Component B). Entity đóng vai trò liên kết các Component A và B cụ thể để tạo thành một đối tượng hoàn chỉnh trong môi trường ảo.

3. Đồng bộ hóa đối tượng giữa các thế giới ảo
Đây là nhu cầu phổ biến trong các game trực tuyến kiến trúc client-server. Khi server và client đều có môi trường ảo riêng nhưng cần phản ánh trạng thái của nhau, Entity đóng vai trò như bản ghi nhận dạng duy nhất để xác định các đối tượng liên kết giữa hai thế giới. Mỗi Entity tồn tại độc lập trong từng hệ thống nhưng dùng chung một định danh để biểu thị đây là cùng một thực thể.


Vấn đề thiết kế và cách tiếp cận thực tiễn

Ban đầu khi xây dựng mô hình ECS, chúng tôi giới hạn mỗi Entity chỉ chứa một Component của mỗi loại duy nhất. Tuy nhiên thực tế phát triển game lại phức tạp hơn nhiều. Ví dụ:

  • Một nhân vật có thể mang nhiều hiệu ứng trạng thái (buff)
  • Một vật thể trong game có thể cần nhiều hình khối để mô tả chính xác va chạm

Unity đã giải quyết vấn đề này bằng cách cho phép một Entity chứa nhiều Component cùng loại. Mặc dù vậy, tôi cho rằng cách tiếp cận này vẫn tồn tại một số hạn chế:

  • Khó khăn trong việc truy xuất Component cụ thể từ một Entity
  • Vi phạm nguyên tắc “một Component một loại” giúp tối ưu hiệu năng truy cập dữ liệu
  • Bắt buộc gộp nhiều thuộc tính không liên quan vào cùng một loại Component (ví dụ: gộp thông tin hình học và màu sắc vào Component va chạm)

Giải pháp thay thế: Subset và Owner

Để giải quyết những hạn chế trên, tôi đề xuất bổ sung hai loại Component đặc biệt:

1. Subset
Là tập hợp các Entity ID biểu thị mối quan hệ “phần - toàn thể”. Subset có thể được triển khai dưới dạng:

  • Bảng dữ liệu đơn giản cho các cấu trúc phẳng
  • Cây phân cấp (hierarchy) cho các đối tượng có quan hệ cha-con

2. Owner
Là liên kết một chiều từ Entity con đến Entity cha, biểu thị mối quan hệ quản lý. Cả hai loại này đều có thể linh hoạt thêm vào bất kỳ Entity nào khi cần thiết.

Ví dụ minh họa:
Khi thiết kế hệ thống va chạm:

  • Mỗi vật thể có thể chứa nhiều Component va chạm
  • Các Component này được nhóm vào một Subset có cấu trúc cây phân cấp
  • Khi vị trí của Entity cha thay đổi, một System chuyên biệt sẽ tự động cập nhật vị trí của toàn bộ Component va chạm con
  • Hệ thống vật lý vẫn làm việc hiệu quả nhờ truy cập các Component va chạm đồng nhất mà không bị ảnh hưởng bởi các thuộc tính không liên quan

Cách tiếp cận này không chỉ duy trì nguyên tắc tách biệt dữ liệu của ECS mà còn mở ra khả năng thiết kế các hệ thống phức tạp với cấu trúc linh hoạt và hiệu năng tối ưu.

0%