Hôm qua, tôi đã đọc một bài thuyết trình từ GDC Canada về hệ thống thực thể Thuộc tính / Hành vi và tôi nghĩ nó khá tuyệt. Tuy nhiên, tôi không chắc chắn làm thế nào để sử dụng nó một cách thiết thực, không chỉ trong lý thuyết. Trước hết, tôi sẽ nhanh chóng giải thích cho bạn cách hệ thống này hoạt động.
Mỗi thực thể trò chơi (đối tượng trò chơi) bao gồm các thuộc tính (= dữ liệu, có thể được truy cập bằng các hành vi, nhưng cũng bằng 'mã bên ngoài') và hành vi (= logic, có chứa OnUpdate()
và OnMessage()
). Vì vậy, ví dụ, trong một bản sao đột phá, mỗi viên gạch sẽ bao gồm (ví dụ!): PositionAttribution , ColorAttribution , HealthAttribution , RenderableBehaviour , HitBehaviour . Cái cuối cùng có thể trông như thế này (nó chỉ là một ví dụ không hoạt động được viết bằng C #):
void OnMessage(Message m)
{
if (m is CollisionMessage) // CollisionMessage is inherited from Message
{
Entity otherEntity = m.CollidedWith; // Entity CollisionMessage.CollidedWith
if (otherEntity.Type = EntityType.Ball) // Collided with ball
{
int brickHealth = GetAttribute<int>(Attribute.Health); // owner's attribute
brickHealth -= otherEntity.GetAttribute<int>(Attribute.DamageImpact);
SetAttribute<int>(Attribute.Health, brickHealth); // owner's attribute
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
else if (m is AttributeChangedMessage) // Some attribute has been changed 'externally'
{
if (m.Attribute == Attribute.Health)
{
// If health is <= 0, "destroy" the brick
if (brickHealth <= 0)
SetAttribute<bool>(Attribute.Alive, false);
}
}
}
Nếu bạn quan tâm đến hệ thống này, bạn có thể đọc thêm tại đây (.ppt).
Câu hỏi của tôi liên quan đến hệ thống này, nhưng nói chung là mọi hệ thống thực thể dựa trên thành phần. Tôi chưa bao giờ thấy bất kỳ cái nào trong số này thực sự hoạt động trong các trò chơi máy tính thực sự, bởi vì tôi không thể tìm thấy bất kỳ ví dụ hay nào và nếu tôi tìm thấy nó, nó không được ghi lại, không có bình luận nào và vì vậy tôi không hiểu nó.
Vì vậy, tôi muốn hỏi gì? Làm thế nào để thiết kế các hành vi (thành phần). Tôi đã đọc ở đây, trên GameDev SE, rằng lỗi phổ biến nhất là tạo ra nhiều thành phần và đơn giản là "biến mọi thứ thành một thành phần". Tôi đã đọc rằng đề nghị không thực hiện kết xuất trong một thành phần, nhưng thực hiện nó bên ngoài nó (vì vậy thay vì RenderableBehaviour , nó có thể là RenderableAttribution và nếu một thực thể có RenderableAttribution được đặt thành true, thì Renderer
(lớp không liên quan đến các thành phần, nhưng với chính động cơ) nên vẽ nó trên màn hình?).
Nhưng, làm thế nào về các hành vi / thành phần? Hãy nói rằng tôi đã có một cấp độ, và ở cấp độ, có một Entity button
, Entity doors
và Entity player
. Khi người chơi va chạm với nút (đó là nút sàn, bị thay đổi bởi áp lực), nó sẽ bị nhấn. Khi nhấn nút, nó sẽ mở cửa. Vâng, bây giờ làm thế nào để làm điều đó?
Tôi đã nghĩ ra một thứ như thế này: người chơi đã có CollisionBehaviour , để kiểm tra xem người chơi có va chạm với thứ gì đó không. Nếu anh ta va chạm với một nút, nó sẽ gửi một CollisionMessage
đến button
thực thể. Tin nhắn sẽ chứa tất cả các thông tin cần thiết: người đã va chạm với nút. Nút đã có TogglizableBehaviour , sẽ nhận được CollisionMessage
. Nó sẽ kiểm tra xem ai đã va chạm với nó và nếu trọng lượng của thực thể đó đủ lớn để bật nút, nút sẽ được bật. Bây giờ, nó đặt ToggledAttribution của nút thành true. Được rồi, nhưng bây giờ thì sao?
Nút có nên gửi một tin nhắn khác cho tất cả các đối tượng khác để nói với họ rằng nó đã được bật? Tôi nghĩ rằng nếu tôi làm mọi thứ như thế này, tôi sẽ có hàng ngàn tin nhắn và nó sẽ trở nên khá lộn xộn. Vì vậy, có lẽ điều này là tốt hơn: các cửa liên tục kiểm tra xem nút được liên kết với chúng có được nhấn hay không và thay đổi OpenedAttribution của nó cho phù hợp. Nhưng sau đó, điều đó có nghĩa là phương pháp của các cánh cửa OnUpdate()
sẽ liên tục làm một cái gì đó (nó có thực sự là một vấn đề không?).
Và vấn đề thứ hai: nếu tôi có nhiều loại nút hơn. Người ta bị ép bởi áp lực, người thứ hai bị quấy rối bằng cách bắn vào nó, người thứ ba bị bật nếu nước đổ vào nó, v.v. Điều này có nghĩa là tôi sẽ phải có những hành vi khác nhau, đại loại như thế này:
Behaviour -> ToggleableBehaviour -> ToggleOnPressureBehaviour
-> ToggleOnShotBehaviour
-> ToggleOnWaterBehaviour
Đây là cách trò chơi thực sự hoạt động hay tôi chỉ là ngu ngốc? Có lẽ tôi chỉ có thể có một TogglizableBehaviour và nó sẽ hoạt động theo NútTypeAttribution . Vì vậy, nếu nó là ButtonType.Pressure
, nó làm điều này, nếu nó là ButtonType.Shot
, nó làm một cái gì đó khác ...
Vậy tôi muốn gì? Tôi muốn hỏi bạn rằng tôi đang làm đúng hay tôi chỉ ngu ngốc và tôi không hiểu điểm của các thành phần. Tôi không tìm thấy bất kỳ ví dụ hay nào về cách các thành phần thực sự hoạt động trong các trò chơi, tôi chỉ tìm thấy một số hướng dẫn mô tả cách tạo hệ thống thành phần, nhưng không sử dụng nó.