Thực hiện powerups trong một hệ thống dựa trên thành phần


29

Tôi chỉ mới bắt đầu thực sự tập trung vào thiết kế dựa trên thành phần. Tôi không biết cách "đúng" để làm điều này là gì.

Đây là kịch bản. Người chơi có thể trang bị khiên. Tấm khiên được vẽ dưới dạng bong bóng xung quanh người chơi, nó có hình dạng va chạm riêng biệt và giảm thiệt hại mà người chơi nhận được từ các hiệu ứng khu vực.

Làm thế nào là một lá chắn như vậy được kiến ​​trúc trong một trò chơi dựa trên thành phần?

Nơi tôi bối rối là chiếc khiên rõ ràng có ba thành phần liên quan đến nó.

  • Giảm thiệt hại / lọc
  • Một sprite
  • Một máy va chạm.

Để làm cho nó tệ hơn, các biến thể khiên khác nhau thậm chí có thể có nhiều hành vi hơn, tất cả đều có thể là các thành phần:

  • tăng sức khỏe tối đa cho người chơi
  • regen sức khỏe
  • lệch đạn
  • v.v.

  1. Tôi có lật đổ điều này không? Khiên chỉ nên là một siêu thành phần?
    Tôi thực sự nghĩ rằng đây là câu trả lời sai. Vì vậy, nếu bạn nghĩ rằng đây là cách để đi xin vui lòng giải thích.

  2. Khiên có nên là thực thể riêng của nó theo dõi vị trí của người chơi không?
    Điều đó có thể làm cho nó khó thực hiện việc lọc thiệt hại. Nó cũng làm mờ các dòng giữa các thành phần và thực thể đính kèm.

  3. Khiên có nên là một thành phần chứa các thành phần khác không?
    Tôi chưa bao giờ thấy hoặc nghe thấy bất cứ điều gì như thế này, nhưng có lẽ nó phổ biến và tôi vẫn chưa đủ sâu.

  4. Khiên chỉ nên là một bộ các thành phần được thêm vào người chơi?
    Có thể với một thành phần bổ sung để quản lý các thành phần khác, ví dụ như vậy tất cả chúng có thể được xóa thành một nhóm. (vô tình để lại phía sau thành phần giảm thiệt hại, bây giờ sẽ rất vui).

  5. Một cái gì đó khác rõ ràng với một người có nhiều kinh nghiệm thành phần?


Tôi đã tự do làm cho tiêu đề của bạn cụ thể hơn.
Tetrad

Câu trả lời:


11

Khiên có nên là thực thể riêng của nó theo dõi vị trí của người chơi không? Điều đó có thể làm cho nó khó thực hiện việc lọc thiệt hại. Nó cũng làm mờ các dòng giữa các thành phần và thực thể đính kèm.

Chỉnh sửa: Tôi nghĩ rằng không có đủ "hành vi tự trị" cho một thực thể tách biệt. Trong trường hợp cụ thể này, một lá chắn đi theo mục tiêu, hoạt động cho mục tiêu và không tồn tại lâu hơn mục tiêu. Mặc dù tôi có xu hướng đồng ý rằng không có gì sai với khái niệm "đối tượng lá chắn", nhưng trong trường hợp này chúng ta đang xử lý hành vi, điều này chỉ phù hợp với một thành phần. Nhưng tôi cũng là người ủng hộ các thực thể logic thuần túy (trái ngược với các hệ thống thực thể toàn diện, trong đó bạn có thể tìm thấy các thành phần Biến đổi và Kết xuất).

Khiên có nên là một thành phần chứa các thành phần khác không? Tôi chưa bao giờ thấy hoặc nghe thấy bất cứ điều gì như thế này, nhưng có lẽ nó phổ biến và tôi chưa đủ sâu.

Nhìn nó ở một góc nhìn khác; thêm một thành phần cũng thêm các thành phần khác, và sau khi loại bỏ, các thành phần bổ sung cũng biến mất.

Khiên chỉ nên là một bộ các thành phần được thêm vào người chơi? Có thể với một thành phần bổ sung để quản lý các thành phần khác, ví dụ như vậy tất cả chúng có thể được xóa thành một nhóm. (vô tình để lại phía sau thành phần giảm thiệt hại, bây giờ sẽ rất vui).

Đây có thể là một giải pháp, nó sẽ thúc đẩy việc tái sử dụng, tuy nhiên nó cũng dễ bị lỗi hơn (ví dụ như đối với vấn đề bạn đã đề cập). Nó không hẳn là xấu. Bạn có thể tìm ra các kết hợp chính tả mới với bản dùng thử và lỗi :)

Một cái gì đó khác rõ ràng với một người có nhiều kinh nghiệm thành phần?

Tôi sẽ giải thích một chút.

Tôi tin rằng bạn nhận thấy một số thành phần nên được ưu tiên như thế nào khi chúng được thêm vào một thực thể (điều này cũng sẽ trả lời câu hỏi khác của bạn).

Tôi cũng sẽ giả định rằng chúng tôi đang sử dụng giao tiếp dựa trên tin nhắn (vì mục đích thảo luận, đây chỉ là một sự trừu tượng đối với một cuộc gọi phương thức trong thời điểm này).

Bất cứ khi nào một thành phần khiên được "cài đặt", các trình xử lý thông báo thành phần khiên sẽ được nối với một thứ tự cụ thể (cao hơn).

Handler Stage    Handler Level     Handler Priority
In               Pre               System High
Out              Invariant         High
                 Post              AboveNormal
                                   Normal
                                   BelowNormal
                                   Low
                                   System Low

In - incoming messages
Out - outgoing messages
Index = ((int)Level | (int)Priority)

Thành phần "thống kê" cài đặt trình xử lý thông báo "thiệt hại" ở chỉ mục In / Invariant / Normal. Mỗi khi nhận được thông báo "thiệt hại", hãy giảm HP theo lượng "giá trị" của nó.

Hành vi tiêu chuẩn khá (đưa vào một số khả năng chống sát thương tự nhiên và / hoặc đặc điểm chủng tộc, bất cứ điều gì).

Thành phần lá chắn cài đặt trình xử lý thông báo "thiệt hại" ở chỉ số In / Pre / High.

Every time a "damage" message is received, deplete the shield energy and substract
the shield energy from the damage value, so that the damage down the message
handler pipeline is reduced.

damage -> stats
    stats
        stats.hp -= damage.value

damage -> shield -> stats
    shield
        if(shield.energy) {
            remove_me();
            return;
        }
        damage.value -= shield.energyquantum
        shield.energy -= shield.energyquantum;

     stats
        stats.hp -= damage.value

Bạn có thể thấy điều này khá linh hoạt, mặc dù nó sẽ yêu cầu lập kế hoạch cẩn thận khi thiết kế tương tác thành phần, vì bạn sẽ phải xác định phần nào của trình xử lý sự kiện thông báo thành phần xử lý thông báo được cài đặt.

Có ý nghĩa? Hãy cho tôi biết nếu tôi có thể thêm chi tiết.

Chỉnh sửa: liên quan đến nhiều trường hợp thành phần (hai thành phần áo giáp). Bạn có thể theo dõi tổng số thể hiện chỉ trong một thể hiện thực thể (tuy nhiên, trạng thái này sẽ giết chết từng thành phần) và chỉ cần tiếp tục thêm các trình xử lý sự kiện thông báo hoặc đảm bảo các bộ chứa thành phần của bạn cho phép các loại thành phần trùng lặp trước.


Bạn đã trả lời "Không" cho câu hỏi đầu tiên mà không đưa ra bất kỳ lý do nào. Dạy người khác là giúp họ hiểu lý do đằng sau bất kỳ quyết định nào. IMO, thực tế là trong RL, một trường lực sẽ là một "thực thể vật lý" riêng biệt với cơ thể của bạn là đủ để cho nó trở thành một thực thể riêng biệt trong mã. Bạn có thể đề xuất những lý do tốt để đề xuất tại sao đi tuyến đường này là xấu?
Kỹ sư

@Nick, tôi không bao giờ cố gắng dạy bất cứ điều gì cho bất cứ ai, thay vì chia sẻ những gì tôi biết về chủ đề này. Tuy nhiên tôi sẽ thêm một lý do đằng sau chữ "không" đó với hy vọng sẽ loại bỏ được nhược điểm khó chịu đó :(
Raine

Điểm tự chủ của bạn làm cho ý nghĩa tốt. Nhưng bạn lưu ý: "trong trường hợp này chúng ta đang xử lý hành vi". Đúng - hành vi liên quan đến một đối tượng vật lý hoàn toàn riêng biệt (hình dạng va chạm lá chắn). Đối với tôi, một thực thể liên kết với một cơ thể vật lý (hoặc tập hợp các cơ thể được kết nối, ví dụ như bằng khớp). Làm thế nào để bạn hòa giải này? Về phần tôi, tôi sẽ cảm thấy không thoải mái khi thêm một vật cố định "giả" chỉ kích hoạt nếu người chơi tình cờ sử dụng khiên. IMO không linh hoạt, khó duy trì trên tất cả các thực thể. Cũng nên xem xét, một trò chơi trong đó đai khiên giữ khiên ngay cả sau khi chết (Dune).
Kỹ sư

@Nick, phần lớn các hệ thống thực thể có cả các thành phần logic và đồ họa giống nhau, vì vậy, trong trường hợp này, có một thực thể cho một lá chắn là hoàn toàn hợp lý. Trong các hệ thống thực thể logic thuần túy, "tự chủ" là sản phẩm của mức độ phức tạp của một đối tượng, sự phụ thuộc và tuổi thọ của nó. Cuối cùng, yêu cầu là vua - và xem xét rằng không có sự đồng thuận thực sự về hệ thống thực thể là gì, có rất nhiều chỗ cho các giải pháp phù hợp với dự án :)
Raine

@deft_code, vui lòng cho tôi biết nếu tôi có thể cải thiện câu trả lời của mình.
Raine

4

1) Tôi có lật đổ điều này không? Khiên chỉ nên là một siêu thành phần?

Có thể, phụ thuộc vào mức độ bạn có thể sử dụng lại mã của mình và nếu nó có ý nghĩa.

2) Khiên có nên là thực thể riêng theo dõi vị trí của người chơi không?

Không, trừ khi chiếc khiên này là một loại sinh vật có thể đi lại độc lập ở một số giai đoạn.

3) Khiên có nên là một thành phần chứa các thành phần khác không?

Điều này nghe có vẻ giống như thực thể, vì vậy câu trả lời là không.

4) Khiên có nên là một bộ các thành phần được thêm vào người chơi không?

Có khả năng.

"Giảm sát thương / lọc"

  • chức năng thành phần lá chắn lõi.

"Một sprite"

  • Có lý do gì bạn không thể thêm SpriteComponent khác vào thực thể nhân vật của mình (nói cách khác là nhiều hơn một thành phần của loại nhất định cho mỗi thực thể)?

"Máy va chạm"

  • bạn có chắc bạn cần một cái khác không? Điều này phụ thuộc vào động cơ vật lý của bạn. Bạn có thể gửi tin nhắn đến ColliderComponent của thực thể nhân vật và yêu cầu nó thay đổi hình dạng không?

"Tăng cường sức khỏe tối đa cho người chơi, hồi phục sức khỏe, làm lệch hướng v.v."

  • các đồ tạo tác khác có thể có thể làm điều này (kiếm, ủng, nhẫn, bùa chú / bình thuốc / đền thờ v.v.) vì vậy đây phải là những thành phần.

3

Một chiếc khiên, như một thực thể vật lý , không khác với bất kỳ thực thể vật lý nào khác , ví dụ như một máy bay không người lái vòng quanh bạn (và trên thực tế, bản thân nó có thể là một loại khiên!). Vì vậy, làm cho lá chắn trở thành một thực thể logic riêng biệt (do đó cho phép nó giữ các thành phần riêng của nó).

Cung cấp cho khiên của bạn một vài thành phần: thành phần Vật lý / Không gian để thể hiện hình thức va chạm của nó và thành phần DamageAffector chứa tham chiếu đến một số thực thể mà nó sẽ áp dụng sát thương tăng hoặc giảm (ví dụ: nhân vật người chơi của bạn) mỗi khi thực thể đó giữ DamageAffector nhận sát thương. Do đó, người chơi của bạn đang nhận sát thương "bằng proxy".

Đặt vị trí của thực thể khiên cho vị trí của người chơi mỗi tích tắc. (Viết một lớp thành phần có thể tái sử dụng thực hiện điều này: viết một lần, sử dụng nhiều lần.)

Bạn sẽ cần phải tạo thực thể lá chắn, ví dụ. về việc thu thập một powerup. Tôi sử dụng một khái niệm chung gọi là Emitter, đây là một loại thành phần thực thể sinh ra các thực thể mới (thường thông qua việc sử dụng EntityFactory mà nó tham chiếu). Nơi bạn quyết định xác định vị trí bộ phát tùy thuộc vào bạn - vd. đặt nó lên powerup và kích hoạt nó khi powerup được thu thập.


Khiên có nên là thực thể riêng của nó theo dõi vị trí của người chơi không? Điều đó có thể làm cho nó khó thực hiện việc lọc thiệt hại. Nó cũng làm mờ các dòng giữa các thành phần và thực thể đính kèm.

Có một ranh giới giữa các thành phần phụ logic (Không gian, AI, khe vũ khí, Xử lý đầu vào, v.v.) và các thành phần phụ vật lý. Bạn cần phải quyết định bạn đứng về phía nào, vì điều này xác định mạnh mẽ loại hệ thống thực thể bạn có. Đối với tôi, thành phần vật lý của Thực thể của tôi xử lý các mối quan hệ phân cấp vật lý (chẳng hạn như các chi trong cơ thể - nghĩ các nút phối cảnh), trong khi các bộ điều khiển logic được lưu ý ở trên thường là những gì được biểu thị bởi các thành phần thực thể của bạn - thay vì các đại diện này "đồ đạc" vật lý cá nhân.


3

Khiên có nên là một thành phần chứa các thành phần khác không?

Có thể không chứa các thành phần khác, nhưng kiểm soát tuổi thọ của các thành phần phụ. Vì vậy, trong một số mã giả thô, mã máy khách của bạn sẽ thêm thành phần "lá chắn" này.

class Shield : Component
{
    void Start() // happens when the component is added
    {
        sprite = entity.add_component<Sprite>( "shield" );
        collider = entity.add_component<Collider>( whatever );
        //etc
    }

    void OnDestroy() // when the component is removed
    {
        entity.remove_component( sprite );
        entity.remove_component( collider );
    }

    void Update() // every tick
    {
        if( ShouldRemoveSelf() ) // probably time based or something
            entity.remove_component( this );
    }
}

Nó không rõ thisnghĩa là gì trong câu trả lời của bạn. Là thisnói đến thành phần Khiên hay ý bạn là thực thể đang sử dụng khiên, cha mẹ của nó? Sự nhầm lẫn có thể là lỗi của tôi. "Thành phần dựa" là mơ hồ. Trong phiên bản của tôi về các thực thể dựa trên thành phần, một thực thể chỉ đơn giản là một thùng chứa thành phần với một số chức năng tối thiểu của chính nó (tên đối tượng, thẻ, tin nhắn, v.v.).
deft_code

Nó sẽ ít gây nhầm lẫn nếu tôi sử dụng gameObjecthoặc một cái gì đó. Đây là một tham chiếu đến đối tượng / thực thể trò chơi hiện tại / bất cứ thứ gì sở hữu các thành phần.
Tetrad

0

Nếu hệ thống thành phần của bạn cho phép tạo kịch bản, thành phần khiên có thể gần như là một siêu thành phần chỉ gọi một tập lệnh cho tham số "hiệu ứng" của nó. Bằng cách đó, bạn duy trì tính đơn giản của một thành phần duy nhất cho các khiên và giảm tải tất cả logic của những gì nó thực sự làm cho các tệp tập lệnh tùy chỉnh được cung cấp cho các khiên theo định nghĩa thực thể của bạn.

Tôi làm một cái gì đó tương tự cho thành phần Di chuyển của tôi, nó chứa một trường thuộc tập lệnh keyreaction (một lớp con của tập lệnh trong công cụ của tôi) tập lệnh này xác định một phương thức theo thông điệp đầu vào của tôi. như vậy tôi chỉ có thể làm một cái gì đó như thế này trong tệp định nghĩa tempalte của tôi

camera template
    moveable
    {
        keyreaction = "scriptforcameramoves"

    }  

player template
    moveable
    {
        keyreaction = "scriptfroplayerkeypress"

    }  

sau đó trong thành phần có thể di chuyển của tôi trong khi đăng ký tin nhắn, tôi đăng ký tập lệnh Do phương thức (mã trong C #)

Owner.RegisterHandler<InputStateInformation>(MessageType.InputUpdate, kScript.Do);

tất nhiên điều này phụ thuộc vào phương thức Do của tôi theo mô hình các hàm mà RegisterHandler của tôi đảm nhận. Trong trường hợp này (người gửi IComponent, đối số kiểu ref)

vì vậy "tập lệnh" của tôi (trong trường hợp của tôi cũng là C # vừa được biên dịch) đã định nghĩa

 public class CameraMoveScript : KeyReactionScript
{
 public override void Do(IComponent pSender, ref InputStateInformation inputState)
 {
    //code here
 }
}

và lớp cơ sở KeyReactionScript của tôi

public class KeyReactionScript : Script
{
      public virtual void Do(IComponent pSender, ref InputStateInformation inputState);
}

sau đó khi một thành phần đầu vào gửi một tin nhắn thuộc loại MessageTypes.InputUpdate với kiểu như vậy

 InputStateInformation myInputState = InputSystem.GetInputState();
 SendMessage<InputStateInformation>(MessageTypes.InputUpdate, ref myInputState);

Phương thức trong tập lệnh được liên kết với thông điệp và kiểu dữ liệu đó sẽ được kích hoạt và xử lý tất cả logic.

Mã này khá cụ thể cho công cụ của tôi, nhưng logic phải hoạt động trong mọi trường hợp. Tôi làm điều này cho nhiều loại để giữ cho cấu trúc thành phần đơn giản và linh hoạt.

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.