Làm thế nào để tránh được Blo Blo-Systems Systems trong một hệ thống thành phần thực thể?


10

Hiện tại tôi đang phải đối mặt với vấn đề sau:

Tôi đang cố gắng viết một bản sao pong bằng cách sử dụng một hệ thống thành phần thực thể (ECS). Tôi đã tự viết "khung". Vì vậy, có một lớp quản lý các thực thể với tất cả các thành phần. Sau đó, có các lớp thành phần chính mình. Và cuối cùng là các hệ thống của tôi chỉ nhận được tất cả các thực thể có các thành phần mà hệ thống cần.

Vì vậy, ví dụ hệ thống chuyển động của tôi tìm kiếm tất cả các thực thể có thành phần vị trí và thành phần chuyển động. Thành phần vị trí chỉ giữ vị trí và thành phần chuyển động giữ tốc độ.

Nhưng vấn đề thực tế là hệ thống va chạm của tôi. Lớp học này giống như một đốm màu logic. Tôi có rất nhiều trường hợp đặc biệt trong lớp này.

Ví dụ: Mái chèo của tôi có thể va chạm với các đường viền. Nếu điều này xảy ra, tốc độ của chúng được đặt thành không. Bóng của tôi cũng có thể va chạm với biên giới. Nhưng trong trường hợp này, tốc độ của nó chỉ được nhân đôi ở mức bình thường của đường viền nên nó được phản ánh. Để làm điều này, tôi đã cho quả bóng một thành phần vật lý bổ sung mà chỉ nói: "Này, thứ này không dừng lại, nó phản ánh." Vì vậy, thực sự, thành phần vật lý không có dữ liệu thực. Đó là một lớp trống chỉ ở đó để báo cho hệ thống nếu một đối tượng phản ánh hoặc dừng lại.

Sau đó là điều này: Tôi muốn kết xuất một số hạt khi quả bóng va chạm với mái chèo hoặc đường viền. Vì vậy, tôi nghĩ rằng quả bóng phải có một thành phần khác nói với hệ thống va chạm để tạo ra hạt khi va chạm.
Sau đó, tôi muốn có sức mạnh có thể va chạm với mái chèo nhưng không phải với biên giới. Nếu điều đó xảy ra, sức mạnh phải biến mất. Vì vậy, tôi sẽ cần nhiều trường hợp và thành phần hơn (để nói với hệ thống rằng một số thực thể chỉ có thể va chạm với một số người khác, bot không phải với tất cả ngay cả khi một số người khác thực sự có thể va chạm, hơn nữa hệ thống va chạm phải áp dụng tăng sức mạnh cho các mái chèo, vv, vv, vv).

Tôi thấy rằng hệ thống thành phần thực thể là một điều tốt bởi vì nó linh hoạt và bạn không gặp vấn đề với sự kế thừa. Nhưng tôi hoàn toàn bị mắc kẹt hiện tại.

Tôi có suy nghĩ quá phức tạp không? Làm thế nào tôi nên đối phó với vấn đề này?

Chắc chắn, tôi phải tạo ra các hệ thống thực sự chịu trách nhiệm cho "hậu va chạm", vì vậy hệ thống va chạm chỉ nói "Có, chúng tôi có va chạm ở khung cuối" và sau đó có một loạt các hệ thống "sau va chạm" tất cả yêu cầu các thành phần (kết hợp) khác nhau và sau đó thay đổi các thành phần. Ví dụ, sẽ có một hệ thống sau va chạm chuyển động ngăn chặn những thứ phải dừng lại khi va chạm xảy ra. Sau đó, một hệ thống vật lý sau va chạm phản ánh sự vật, vv

Nhưng điều này dường như cũng không phải là một giải pháp thích hợp với tôi, vì ví dụ:

  1. Hệ thống sau va chạm chuyển động của tôi sẽ cần các thực thể có thành phần vị trí, thành phần chuyển động và thành phần va chạm. Sau đó, nó sẽ đặt tốc độ của thực thể bằng không.
  2. Hệ thống sau va chạm vật lý sẽ cần các thực thể có thành phần vị trí, thành phần chuyển động, thành phần va chạm và thành phần vật lý. Sau đó, nó sẽ phản ánh vector tốc độ.

Vấn đề là rõ ràng: Chuyển động sau va chạm cần các thực thể là tập hợp con của các thực thể trong hệ thống sau va chạm vật lý. Vì vậy, hai hệ thống sau va chạm sẽ hoạt động trên cùng một dữ liệu, hiệu quả là: Mặc dù một thực thể có thành phần vật lý, tốc độ sẽ bằng không sau một vụ va chạm.

Làm thế nào những vấn đề này được giải quyết nói chung trong một hệ thống thành phần thực thể? Là những vấn đề thậm chí bình thường hoặc tôi đang làm gì đó sai? Nếu có, những gì và làm thế nào nó nên được thực hiện thay thế?

Câu trả lời:


11

Vâng, bạn đang suy nghĩ quá phức tạp.

Có vẻ như rất nhiều vấn đề của bạn có thể được giải quyết với hệ thống nhắn tin và một số thuộc tính bổ sung cho phép bạn chỉ định một số bộ lọc và cuối cùng không lo lắng về việc quá nghiêm ngặt với các thực thể / thành phần.

Nhắn tin sẽ giúp bạn với một số khía cạnh như kích hoạt các hạt, tăng sức mạnh, v.v. Ví dụ: bạn có thể có một đối tượng thế giới đăng ký các sự kiện hạt và tạo các hạt tại vị trí được mô tả trong sự kiện.

Bộ lọc sẽ giúp bạn rất nhiều trong các va chạm. Các bộ lọc có thể xác định nếu một đối tượng va chạm với một đối tượng khác và nó sẽ có phản ứng gì. Bạn thêm một số thuộc tính vào thành phần vật lý của bạn để xác định loại cơ thể vật lý đó là gì, loại cơ thể vật lý nào khác mà nó va chạm và phản ứng nên là gì. Ví dụ, một đối tượng vật lý bóng va chạm với một đối tượng vật lý mái chèo và phản ứng với sự phản xạ và các hạt.

Cuối cùng, đừng quá khắt khe về việc thực hiện của bạn. Nếu bạn có thể tìm cách làm cho nó hoạt động, nhưng đó không thực sự là hệ thống EC, hãy làm điều đó. Giống như trong ví dụ của tôi ở trên, các hạt không cần phải được quản lý bởi một hệ thống hoặc một phần của hệ thống EC. Điều quan trọng hơn là kết thúc trò chơi hơn là tuân thủ nghiêm ngặt một phương pháp đã được xác định khá kém.


Cảm ơn rât nhiều. Tôi muốn xây dựng một trò chơi bằng cách sử dụng ECS ​​chỉ để xem cách nó chia tỷ lệ và nếu nó thực sự tốt để sử dụng khi tôi đọc trong các bài báo và hướng dẫn. Vấn đề của tôi là tôi đã nghĩ: "Bây giờ tôi có một ECS và mọi thứ phải được quản lý bởi điều này." Vì vậy, tôi đã lên kế hoạch để viết hệ thống hạt liên quan đến ECS. Ngoài ra, tôi đọc trong một số bài viết rằng mọi thành phần thực sự chỉ nên có một số dữ liệu cơ bản và không có gì hơn. Đó thường là vấn đề của tôi ... Tôi nghĩ quá phức tạp.
M0rgenstern

Tôi muốn xây dựng một trò chơi bằng cách sử dụng ECS ​​chỉ để xem cách nó chia tỷ lệ và nếu nó thực sự tốt để sử dụng khi tôi đọc trong các bài báo và hướng dẫn . Nếu đó là mục tiêu của bạn, tôi khuyên bạn nên xem xét các hệ thống Thành phần / Thực thể hiện có thay vì xây dựng hệ thống của riêng bạn. Tải xuống Unity3D, có lẽ là "Thành phần thuần túy nhất có thể" và chơi xung quanh đó. Hiểu biết nhanh hơn nhiều, IMHO.
Imi

3
@lmi: Unity không phải là Hệ thống thành phần thực thể mặc dù nó dựa trên thành phần. ECS có một số hướng dẫn khá chặt chẽ hơn ( không bao giờ nghĩ về một mô hình như các quy tắc) hơn là chỉ đơn giản là có và sử dụng các thành phần đối tượng trò chơi. Do một loạt bài viết, ECS rất phổ biến với một số phân khúc nhà phát triển trò chơi ngay bây giờ nên có rất nhiều câu hỏi về ECS nói riêng thay vì thiết kế dựa trên thành phần nói chung.
Sean Middleditch

12

Bạn đang quá phức tạp mọi thứ. Tôi sẽ đi xa hơn để nói rằng ngay cả việc sử dụng thiết kế dựa trên thành phần cũng chỉ là quá mức cần thiết cho một trò chơi đơn giản như vậy. Làm mọi thứ theo cách làm cho trò chơi của bạn nhanh chóng và dễ dàng phát triển. Các thành phần giúp lặp lại trong các dự án lớn hơn với nhiều hành vi và cấu hình đối tượng trò chơi rất lớn nhưng lợi ích của chúng đối với một trò chơi được xác định rõ ràng đơn giản như vậy là đáng nghi ngờ hơn. Tôi đã có một cuộc nói chuyện vào năm ngoái về điều này: bạn có thể xây dựng các trò chơi nhỏ thú vị trong vài giờ nếu bạn tập trung vào làm một trò chơi thay vì tuân thủ một kiến ​​trúc . Kế thừa bị phá vỡ khi bạn có 100 hoặc thậm chí 20 loại đối tượng khác nhau nhưng nó chỉ hoạt động tốt nếu bạn chỉ có một số ít.

Giả sử bạn muốn tiếp tục sử dụng các thành phần cho mục đích học tập, có một số vấn đề rõ ràng với cách tiếp cận của bạn nổi bật.

Đầu tiên, đừng làm cho các thành phần của bạn quá nhỏ. Không có lý do gì để có các thành phần hạt mịn như 'chuyển động'. Không có chuyển động chung trong trò chơi của bạn. Bạn có mái chèo, có chuyển động được gắn chặt với đầu vào hoặc AI (và không thực sự sử dụng vận tốc, gia tốc, phục hồi, v.v.) và bạn có quả bóng, có thuật toán chuyển động được xác định rõ. Chỉ cần có một thành phần PaddleControll và một thành phần BouncingBall hoặc một cái gì đó dọc theo các dòng đó. Nếu / khi bạn nhận được một trò chơi phức tạp hơn thì bạn có thể lo lắng về việc có một thành phần Vật lý chung chung hơn (mà trong các công cụ 'thực' về cơ bản chỉ là một liên kết giữa đối tượng trò chơi và bất kỳ đối tượng API nội bộ nào được Havok / PhysX / Bullet / sử dụng Box2D / vv.) Xử lý nhiều tình huống khác nhau.

Ngay cả một thành phần 'vị trí' cũng có thể nghi ngờ mặc dù chắc chắn không phải là hiếm. Các công cụ vật lý thường có ý tưởng bên trong của riêng chúng về vị trí của một vật thể, đồ họa có thể có biểu diễn nội suy và AI có thể có một biểu diễn khác của cùng một dữ liệu ở trạng thái khác. Có thể thuận lợi khi chỉ cho phép mỗi hệ thống quản lý ý tưởng riêng của mình về biến đổi trong các thành phần của chính hệ thống và sau đó đảm bảo có sự giao tiếp suôn sẻ giữa hệ thống. Xem bài đăng trên blog của BitSquid trên các luồng sự kiện .

Đối với các công cụ vật lý tùy chỉnh, hãy nhớ rằng bạn được phép có dữ liệu trên các thành phần của mình. Có thể một thành phần vật lý chung chung có dữ liệu cho biết nó có thể di chuyển theo trục nào (giả sử vec2(0,1)là số nhân cho các mái chèo chỉ có thể di chuyển trên trục Y và vec2(1,1)cho bóng có thể di chuyển tuy nhiên), cờ hoặc phao biểu thị độ nảy ( bóng thường sẽ ở 1.0và mái chèo tại0.0), đặc điểm gia tốc, vận tốc, v.v. Việc cố gắng phân chia phần này thành một phần nhỏ các thành phần vi mô khác nhau cho mỗi phần dữ liệu có liên quan cao là đối nghịch với những gì ECS ban đầu dự định làm. Giữ những thứ được sử dụng cùng nhau trong cùng một thành phần nếu có thể và chỉ tách chúng ra khi có sự khác biệt lớn trong cách mỗi đối tượng trò chơi sử dụng dữ liệu đó. Có một lập luận để làm cho Pông vật lý giữa bóng và mái chèo đủ khác nhau để trở thành các thành phần riêng biệt, nhưng đối với một trò chơi lớn hơn, có rất ít lý do để cố gắng tạo ra 20 thành phần để làm những gì hoạt động tốt trong 1-3.

Hãy nhớ rằng, nếu / khi phiên bản ECS của bạn cản trở, hãy làm những gì bạn cần để thực sự tạo ra trò chơi của bạn và quên tuân thủ một mô hình / kiến ​​trúc thiết kế.


1
Chân thanh cảm ơn bạn! Tôi biết rằng ECS ​​không có quy mô tốt cho một trò chơi nhỏ như pong. Nhưng tôi đã sử dụng nó chỉ để xem cách một thứ như vậy thực sự được thực hiện và cách nó hoạt động. Tôi đã làm cho các thành phần rất nhỏ, bởi vì đó là những gì tôi đọc chủ yếu trong một số bài viết. Để có nhiều thành phần và mỗi thành phần chỉ chứa dữ liệu cơ bản. Vì vậy, tôi có hiểu bạn đúng không, rằng bạn đề nghị sử dụng kết hợp giữa thừa kế và ECS? Như bạn nói "bóng và mái chèo đủ khác nhau để trở thành các thành phần riêng biệt". Vì vậy, ví dụ tôi cung cấp cho họ cả thành phần Chuyển động / Vị trí (có thể là một thành phần) và
M0rgenstern

1
Dù làm việc gì. Tập trung vào làm cho trò chơi. Tôi thực sự sẽ chỉ có một thành phần được gọi là Ballchứa tất cả logic cho quả bóng như chuyển động, nảy, v.v. và một Paddlethành phần nhận đầu vào, nhưng đó là tôi. Bất cứ điều gì có ý nghĩa nhất đối với bạn và tránh xa bạn và cho phép bạn biến trò chơi thành "cách chính xác" để làm mọi việc.
Sean Middleditch

3
Tôi thực sự sẽ chỉ có một thành phần gọi là Bóng chứa tất cả logic cho quả bóng như chuyển động, nảy, v.v. và một thành phần Paddle nhận đầu vào, nhưng đó là tôi. Và đó là lý do tại sao có một ý kiến ​​cho mỗi lập trình viên về "hệ thống thành phần là gì". Tôi khuyên KHÔNG nên thực hiện như đề xuất này, ngoại trừ bạn hoàn toàn suy nghĩ trong các hệ thống Thực thể cổ điển và buộc phải sử dụng hệ thống Thành phần nhưng không muốn xem sự khác biệt thực sự là gì.
Imi

2
@lmi: đã làm việc trên một vài trò chơi / động cơ lớn với các thành phần và tận mắt thấy lý do tại sao chúng tôi sử dụng các thành phần, không, các thành phần quá nhỏ chỉ gây rắc rối hơn giá trị của chúng. Các thành phần không phải là một viên đạn ma thuật; chúng là một trong nhiều công cụ trong hộp công cụ của nhà phát triển trò chơi. Sử dụng chúng theo cách và địa điểm mà chúng giúp đỡ chứ không phải theo cách mà chúng chỉ cần thêm chi phí tinh thần và thời gian chạy cho hệ thống. Nếu thứ duy nhất có vật lý bóng là bóng, thì không có lợi thế nào để tách nó ra khỏi các thuộc tính bóng khác. Nếu và khi điều đó thay đổi, hãy tách nó ra và sau đó chỉ.
Sean Middleditch

1
Tôi đồng ý nguyên tắc thực dụng và không để một người đặc biệt nào đó vướng vào họ. NHƯNG nếu ECS không thể xử lý trò chơi tầm thường này mà không bị lệch, thì hy vọng gì cho một trò chơi lớn. Tôi cũng đang cố gắng học cách sử dụng ECS ​​một cách hiệu quả, nhưng tôi đang cố gắng theo sát triết lý ECS nhất có thể, nếu không, một khi tôi bắt đầu tạo ra ngoại lệ và các trường hợp đặc biệt, tôi biết tôi sẽ kết thúc với một mớ hỗn độn không thể nhầm lẫn.
Ken

-2

Theo ý kiến ​​của tôi *), vấn đề lớn nhất của bạn với Thành phần là: Các thành phần KHÔNG ở đây để nói cho bất kỳ ai khác phải làm gì. Các thành phần ở đây để làm những điều. Bạn không có một thành phần chỉ để giữ bộ nhớ của một số thứ và sau đó có các thành phần khác hoạt động trên này. Bạn muốn các thành phần thực hiện công cụ với dữ liệu họ có.

Nếu bạn thấy mình đang kiểm tra sự hiện diện của các thành phần khác (và sau đó gọi các hàm ở đó), thì đây là một dấu hiệu rõ ràng, rằng một trong hai điều là đúng:

  • Bạn thực sự muốn đảo ngược sự phụ thuộc: Thành phần khác nên lắng nghe các sự kiện / tin nhắn / chương trình phát sóng / hook / butyounamethem để thực hiện logic của chúng để đáp ứng thành phần hiện tại của bạn. Thành phần hiện tại thậm chí không phải biết rằng có một thành phần "khác". Đây thường là trường hợp, nếu bạn thấy mình gọi các thành phần khác nhau (ngay cả trong các khối / trường hợp khác) với chức năng không thực sự được kết nối với phương thức hiện tại của bạn. Hãy nghĩ về tất cả những điều này Invalidate()hoặc SetDirty()gọi đến các thành phần khác.
  • Bạn có thể có quá nhiều thành phần. Nếu hai thành phần không thể sống thiếu nhau và liên tục cần truy xuất dữ liệu và gọi các phương thức cho nhau, thì chỉ cần hợp nhất chúng. Rõ ràng, chức năng họ cung cấp rất vướng mắc, rằng nó thực sự chỉ là một thứ.

Nhân tiện, những điều này áp dụng cho tất cả các loại hệ thống, không chỉ các hệ thống Thực thể / Thành phần, mà cả đối với kế thừa cổ điển với các "GameObject" đơn giản hoặc thậm chí các chức năng thư viện.

*) Thực sự chỉ có tôi . Ý kiến ​​rất khác nhau về Whats Da Real System Systemz (TM)

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.