Tôi hiện đang cố gắng thực hiện một hệ thống thực thể dựa trên thành phần, trong đó một thực thể về cơ bản chỉ là một ID và một số phương thức trợ giúp buộc một loạt các thành phần lại với nhau để tạo thành một đối tượng trò chơi. Một số mục tiêu bao gồm:
- Các thành phần chỉ chứa trạng thái (ví dụ: vị trí, sức khỏe, số lượng đạn) => logic đi vào "các hệ thống", xử lý các thành phần này và trạng thái của chúng (ví dụ: PhysSystem, RenderSystem, v.v.)
- Tôi muốn triển khai các thành phần và hệ thống cả trong C # thuần túy và thông qua kịch bản (Lua). Về cơ bản tôi muốn có thể định nghĩa các thành phần và hệ thống hoàn toàn mới trực tiếp trong Lua mà không phải biên dịch lại nguồn C # của tôi.
Bây giờ tôi đang tìm ý tưởng về cách xử lý vấn đề này một cách hiệu quả một cách nhất quán, vì vậy tôi không cần sử dụng các cú pháp khác nhau để truy cập các thành phần C # hoặc các thành phần Lua chẳng hạn.
Cách tiếp cận hiện tại của tôi sẽ là triển khai các thành phần C # bằng cách sử dụng các thuộc tính công khai, thông thường, có thể được trang trí bằng một số thuộc tính cho trình soạn thảo biết về các giá trị và công cụ mặc định. Sau đó, tôi có một lớp "ScriptComponent" lớp C #, nó chỉ bao bọc một bảng Lua bên trong với bảng này được tạo bởi một tập lệnh và giữ tất cả trạng thái của loại thành phần cụ thể đó. Tôi thực sự không muốn truy cập vào trạng thái đó nhiều từ phía C #, vì tôi không biết vào thời gian biên dịch, ScriptComponents với những thuộc tính nào sẽ có sẵn cho tôi. Tuy nhiên, trình chỉnh sửa sẽ cần truy cập vào đó, nhưng một giao diện đơn giản như sau sẽ đủ:
public ScriptComponent : IComponent
{
public T GetProperty<T>(string propertyName) {..}
public void SetProperty<T>(string propertyName, T value) {..}
}
Điều này chỉ đơn giản là truy cập vào bảng Lua và thiết lập và truy xuất các thuộc tính đó từ Lua và nó cũng có thể dễ dàng được bao gồm trong các thành phần C # thuần túy (nhưng sau đó sử dụng các thuộc tính C # thông thường, thông qua sự phản chiếu hoặc một cái gì đó). Điều này sẽ chỉ được sử dụng trong trình chỉnh sửa, không phải bởi mã trò chơi thông thường, vì vậy hiệu suất không quan trọng ở đây. Nó sẽ khiến bạn cần phải tạo hoặc viết tay một số mô tả thành phần ghi lại các thuộc tính mà một loại thành phần nhất định thực sự cung cấp, nhưng đó sẽ không phải là một vấn đề lớn và có thể được tự động hóa hoàn toàn.
Tuy nhiên, làm thế nào để truy cập các thành phần từ phía Lua? Nếu tôi thực hiện một cuộc gọi đến một cái gì đó như getComponentsFromEntity(ENTITY_ID)
có lẽ tôi sẽ nhận được một loạt các thành phần C # bản địa, bao gồm cả "ScriptComponent", dưới dạng userdata. Truy cập các giá trị từ bảng Lua được bao bọc sẽ dẫn đến việc tôi gọi GetProperty<T>(..)
phương thức thay vì truy cập trực tiếp các thuộc tính, như với các thành phần C # khác.
Có thể viết một getComponentsFromEntity()
phương thức đặc biệt chỉ được gọi từ Lua, trả về tất cả các thành phần C # gốc là userdata, ngoại trừ "ScriptComponent", thay vào đó, nó sẽ trả về bảng được bọc. Nhưng sẽ có các phương thức liên quan đến thành phần khác và tôi thực sự không muốn sao chép tất cả các phương thức này để được gọi từ mã C # hoặc từ tập lệnh Lua.
Mục tiêu cuối cùng sẽ là xử lý tất cả các loại thành phần giống nhau, không có cú pháp trường hợp đặc biệt nào khác biệt giữa các thành phần gốc và các thành phần Lua - đặc biệt là từ phía Lua. Ví dụ: tôi muốn có thể viết một kịch bản Lua như thế:
entity = getEntity(1);
nativeComponent = getComponent(entity, "SomeNativeComponent")
scriptComponent = getComponent(entity, "SomeScriptComponent")
nativeComponent.NativeProperty = 5
scriptComponent.ScriptedProperty = 3
Kịch bản không nên quan tâm loại thành phần nào thực sự có và tôi muốn sử dụng các phương thức tương tự mà tôi sử dụng từ phía C # để truy xuất, thêm hoặc xóa thành phần.
Có lẽ có một số triển khai mẫu tích hợp kịch bản với các hệ thống thực thể như vậy?