Tìm kiếm một số cái nhìn sâu sắc về thiết kế lập trình cho các loại tấn công và tấn công trong một trò chơi


14

Vì vậy, tôi bắt đầu giới thiệu tấn công vào RTS không gian 2D của chúng tôi (Đây là trong Unity, do đó, nó là thành phần được điều khiển). Ban đầu nó đơn giản như "kẻ địch trong phạm vi, sát thương được áp dụng". Tuy nhiên, sẽ có nhiều "loại" vũ khí / tấn công được liên kết với con tàu hoặc cấu trúc cụ thể của chúng. Cũng như các yếu tố khác liên quan đến quá khứ chỉ là thiệt hại thô như loại thiệt hại và có thể là quán tính trong tương lai.

Các bạn có từng loại đơn vị và cấu trúc có loại tấn công riêng không. Có nghĩa là bạn tạo một tập lệnh cho từng đơn vị / cấu trúc xác định loại tấn công, sát thương, hiệu ứng, phạm vi, hạt, họa tiết ... vv và đính kèm nó như một thành phần?

Hoặc tạo một tập lệnh xác định loại tấn công, tập lệnh cho loại đạn được liên kết với điều đó ... vv Và sau đó mở rộng tập lệnh và sửa đổi tập lệnh cho từng đơn vị, gắn từng tập lệnh vào đơn vị / cấu trúc.


Tôi hy vọng tôi có ý nghĩa, tôi đã suy nghĩ điều này quá lâu Tôi không chắc mình đang giải quyết vấn đề hay chỉ tự khắc phục vấn đề của mình và tự đào một cái hố.

Khi bạn có một trò chơi có thể có vô số loại tấn công có thể hoặc không giới hạn ở một đơn vị / cấu trúc cụ thể, làm thế nào để bạn thiết kế khung gắn kết với các đơn vị / cấu trúc cụ thể trong môi trường thiết kế theo thành phần ?

Nếu điều này không đủ rõ ràng cho tôi biết.

Chỉnh sửa: Câu trả lời tuyệt vời, cảm ơn bạn.

Câu hỏi mở rộng:

Các câu trả lời dường như thay đổi từ "mỗi đối tượng có thể có tập lệnh tấn công riêng" thành "Có các kiểu tấn công như tập lệnh riêng của chúng và gán nó cho từng đối tượng để có giải pháp tái sử dụng nhiều hơn". Hãy nói rằng tôi có một cuộc tấn công "blaster", nó bắn một viên đạn màu đỏ ở một tốc độ nhất định. Thiệt hại, tốc độ bắn và kích thước đạn phụ thuộc vào đơn vị bắn nó. Có phải tốt hơn là chỉ tạo một kịch bản tấn công cho đơn vị đó, hoặc thử và sửa đổi một "cuộc tấn công blaster" để phù hợp với mục đích của mỗi đơn vị muốn sử dụng nó?


1
Đối với các ý tưởng lập trình trò chơi nói chung, tôi muốn tham khảo thông số kỹ thuật đầy đủ của RPG FFV - gamefaqs.com/snes/588331-final-fantasy-v/faqs/30040
Code Whisperer

Câu trả lời:


12

Chà, thật lòng tôi không phải là một chuyên gia về vấn đề này nhưng ... tôi nghĩ nó phụ thuộc vào mức độ phức tạp và đa dạng mà bạn nghĩ các cuộc tấn công sẽ trở thành. Vì đó là RTS, tôi đoán bạn sẽ có thể có 10-50 hoặc nhiều đơn vị hoặc cấu trúc khác nhau với các kiểu tấn công của riêng họ.

Tùy chọn 1: Nếu có số lượng đơn vị tương đối thấp sẽ có các cuộc tấn công tương tự nhau, tôi chỉ cần đặt mọi thứ vào một tập lệnh lớn và xác định các tham số được sử dụng trong trình kiểm tra.

Tùy chọn 2: Nếu, mặt khác, bạn hình dung một số lượng lớn các loại tấn công có hành vi không giống nhau, bạn có thể phá vỡ mọi thứ để mỗi đơn vị và tòa nhà có được kịch bản tấn công riêng. Tôi nghĩ rằng nếu bạn làm điều này, bạn có thể muốn tạo một tập lệnh "người trợ giúp" xác định các đoạn mã được sử dụng phổ biến mà nhiều tập lệnh riêng lẻ có thể lấy từ đó. Bằng cách này, bạn sẽ không phải viết lại mọi thứ và bạn sẽ biết tất cả ở đâu.

Tùy chọn 3: Điều bạn có thể không nên làm là có một số nhóm đơn vị chia sẻ tập lệnh, điều này có thể sẽ khiến bạn bối rối và sẽ trở thành một mớ hỗn độn nếu mã bạn cần cho một cuộc tấn công nằm trong 10 tập lệnh khác nhau.

Ở đây, tôi đã vẽ cho bạn một bức tranh.

nhập mô tả hình ảnh ở đây


2
Cảm ơn bạn rất nhiều cho trả lời. Tôi đã vì một số lý do bắt đầu nghiêng về lựa chọn 3, và tôi đã gặp khó khăn trong việc tìm cách biện minh cho nó. Có lẽ tôi sẽ đi theo con đường thứ 2, mỗi đơn vị sẽ có tập lệnh tấn công tùy chỉnh của riêng mình với mã chung được chia sẻ bằng cách mã chung được tấn công như một thành phần của mỗi đơn vị / tòa nhà. Tôi không chắc mình sẽ đi đâu với chuyến tàu ý nghĩ dẫn tôi đến phương án 3, cảm ơn bạn. Tôi sẽ để nó mở cho đến khi tôi thức dậy vào sáng trong trường hợp có những áp phích khác muốn kêu vang.
Douglas Gaskell

Không có vấn đề, nó không phải là một câu trả lời dứt khoát nhưng hy vọng nó sẽ giúp.
Mir

1
Bạn có thể kết hợp 1 và 2 bằng cách đặt các cuộc tấn công tương tự vào một kịch bản lớn và tách ra các cuộc tấn công khác nhau
ratchet freak

4
Tôi ngạc nhiên # 3 được đề nghị chống lại? Không phải là toàn bộ điểm của các lớp mô-đun / chung để mỗi đơn vị không phải xác định loại riêng của nó? Nếu một trò chơi là RTS và sát thương bao vây (thường là "tầm xa") là loại sát thương, bạn sẽ muốn xác định nó một lần và có nhiều đơn vị kiểu pháo binh tham khảo nó khi thực hiện sát thương của chúng, để nếu Siege gây sát thương Bao giờ cần phải được nerfed (cân bằng lại), bạn chỉ phải cập nhật một lớp?
HC_

1
"Here, I drew you a picture."nhắc nhở tôi về này
FreeAsInBeer

4

Tôi không biết nhiều về Unity và tôi đã không thực hiện phát triển trò chơi trong một thời gian, vì vậy hãy để tôi cung cấp cho bạn câu trả lời lập trình chung cho câu hỏi này. Tôi đã dựa trên câu trả lời của mình về kiến ​​thức tôi có về các hệ thống thành phần thực thể nói chung, trong đó một thực thể là một số được liên kết với N nhiều thành phần, một thành phần chỉ chứa dữ liệu và một hệ thống hoạt động trên các bộ thành phần được liên kết với cùng một thực thể.

Không gian vấn đề của bạn là thế này:

  • Có nhiều cách để tấn công kẻ thù trong toàn bộ trò chơi.
  • Mỗi tàu, cấu trúc, v.v., có thể có nhiều cách tấn công (mỗi cách được xác định theo một cách nào đó)
  • Mỗi cuộc tấn công có thể có hiệu ứng hạt riêng của nó.
  • Cuộc tấn công phải có yếu tố trong một số yếu tố (chẳng hạn như quán tính hoặc áo giáp chẳng hạn), có mặt trên mục tiêu và trên người dùng.

Tôi sẽ cấu trúc giải pháp như sau:

  • Một cuộc tấn công có một định danh - đây có thể là một chuỗi.
  • Một thực thể 'biết' rằng nó có thể sử dụng một cuộc tấn công (dựa trên định danh của cuộc tấn công).
  • Khi cuộc tấn công được sử dụng bởi thực thể, thành phần hiển thị tương ứng được thêm vào cảnh.
  • Bạn có một số logic biết về mục tiêu của cuộc tấn công, kẻ tấn công và cuộc tấn công đang được sử dụng - logic này sẽ quyết định mức độ thiệt hại của bạn (và có quyền truy cập vào quán tính hoặc bất cứ điều gì của cả hai thực thể).

Điều quan trọng là điểm tiếp xúc giữa các cuộc tấn công và các thực thể càng mỏng càng tốt - điều này sẽ giữ cho mã của bạn có thể sử dụng lại và ngăn bạn khỏi phải đưa ra mã trùng lặp cho từng loại thực thể khác nhau sử dụng cùng một loại tấn công . Nói cách khác, đây là một số mã giả JavaScript để cung cấp cho bạn một ý tưởng.

// components
var bulletStrength = { strength: 50 };
var inertia = { inertia: 100 };
var target = { entityId: 0 };
var bullets = {};
var entity = entityManager.create([bulletStrength, inertia, target, bullets]);

var bulletSystem = function() {
  this.update = function(deltaTime, entityId) {
    var bulletStrength = this.getComponentForEntity('bulletStrength', entityId);
    var targetComponent = this.getComponentForEntity('target', entityId);
    // you may instead elect to have the target object contain properties for the target, rather than expose the entity id
    var target = this.getComponentForEntity('inertia', targetComponent.entityId);

    // do some calculations based on the target and the bullet strength to determine what damage to deal
    target.health -= ....;
  }
};

register(bulletSystem).for(entities.with(['bullets']));

Xin lỗi câu trả lời này là một chút 'nước'. Tôi chỉ có nửa giờ nghỉ trưa và thật khó để nghĩ ra điều gì mà không biết đầy đủ về Unity :(


3

Khi một đơn vị / cấu trúc / vũ khí tấn công, tôi có thể sẽ tạo ra một Tấn công (được phân lớp với tất cả các chi tiết thú vị của bạn) để tấn công kẻ tấn công và người phòng thủ (hoặc người bảo vệ). Tấn công sau đó có thể tương tác với mục tiêu / người phòng thủ (chậm, độc, sát thương, thay đổi trạng thái), tự rút ra (tia, tia, đạn) và tự xử lý khi hoàn thành. Tôi có thể thấy trước một số vấn đề như nhiều cuộc tấn công độc hại, vì vậy có thể các mục tiêu của bạn sẽ thực hiện giao diện Có thể phá hủy mà Tấn công tương tác, nhưng tôi nghĩ đó là một cách tiếp cận khả thi, có thể thay đổi theo mô-đun và linh hoạt.

Trả lời mở rộng
Đây là cách tôi tiếp cận cuộc tấn công chớp nhoáng bằng cách tiếp cận này . Tôi sẽ để người khác tự trả lời.

Tôi sẽ cho các đơn vị của mình thực hiện giao diện hoặc lớp IAttacker với các chỉ số / phương thức tấn công cơ bản. Khi IAttacker tấn công IDamagizable, nó sẽ tạo ra đòn tấn công cụ thể của chính nó và mục tiêu của nó (IAttacker và IDamagizable, hoặc có lẽ là một bộ sưu tập IDamageable). Tấn công lấy các chỉ số cần thiết từ IAttacker (để tránh thay đổi trong quá trình nâng cấp hoặc bất cứ điều gì tương tự - chúng tôi không muốn Tấn công thay đổi chỉ số sau khi đã được tung ra) và nếu cần chỉ số chuyên biệt, hãy sử dụng IAttacker để loại cần thiết của nó (ví dụ: IBlasterAttacker) và có được các số liệu thống kê chuyên ngành theo cách đó.

Theo cách tiếp cận này, BlasterAttacker chỉ cần tạo BlasterAttack và BlasterAttack sẽ lo phần còn lại. Bạn có thể phân lớp BlasterAttack hoặc tạo FastBlasterAttacker, MegaBlasterAttacker, SniperBlasterAttacker, v.v. và mã tấn công cho từng loại giống nhau (và có thể được kế thừa từ BlasterAttack) .


Về cơ bản, đơn vị kế thừa từ giao diện IAttacker (tôi đã có cái này rồi) và có một giao diện IDamagizable cho "kẻ thù" (cũng có cái này). Khi kẻ tấn công tấn công, một BlasterAttack (hoặc lớp dẫn xuất) được gọi. "Cuộc tấn công" này sẽ lấy dữ liệu cần thiết từ IAttacker và áp dụng nó trên IDamagizable khi đạn bắn trúng? Bản thân đạn có chứa lớp BlasterAttack hay không, do đó, khi nó được bắn, nó không còn bị ảnh hưởng bởi các thay đổi đối với IAttacker và chỉ có thể áp dụng sát thương / hiệu ứng của nó lên IDamagizable nếu nó thực sự bắn trúng.
Douglas Gaskell

Khi bạn nói "một BlasterAttack (hoặc lớp dẫn xuất) được gọi" Tôi sẽ nói BlasterAttack được tạo. Ví dụ mới được tạo ra này của BlasterAttack đại diện cho chùm tia (hoặc viên đạn hoặc tia hoặc bất cứ thứ gì), vì vậy nó đạn. BlasterAttack sao chép bất kỳ chỉ số nào cần thiết từ các đối tượng IAttacker và IDamagizable: vị trí, chỉ số kẻ tấn công, v.v. BlasterAttack sau đó theo dõi vị trí của chính nó và, nếu có thể, sẽ gây sát thương lên "tiếp xúc". Bạn sẽ cần phải biết phải làm gì nếu nó bỏ lỡ hoặc đến đích (vị trí cũ của mục tiêu). Đốt đất? Biến mất? Cuộc gọi của bạn.
ricksmt

Đối với Tấn công có hiệu lực trong khu vực, bạn có thể muốn truy cập vào bộ sưu tập các đơn vị (kẻ thù) toàn cầu vì những người ở trong phạm vi và những người ngoài phạm vi có thể thay đổi giữa hỏa lực và tác động. Tất nhiên, một lập luận tương tự có thể được đưa ra cho BlasterAttack: bạn bỏ lỡ mục tiêu ban đầu của mình, nhưng đánh vào kẻ đứng sau anh ta. Mối quan tâm duy nhất của tôi là bạn có thể có rất nhiều Tấn công lặp đi lặp lại qua rất nhiều Kẻ thù đang cố gắng tìm hiểu xem và những gì chúng đánh trúng. Đó là một mối quan tâm về hiệu suất.
ricksmt

Ah, điều đó có ý nghĩa. Đối với một cuộc tấn công bị bỏ lỡ, đạn sẽ có phạm vi / vòng đời được cài đặt sẵn. Nếu nó va vào thứ khác trước khi kết thúc quãng đời đó, nó sẽ nhận được một tham chiếu đến bất kỳ vật thể nào sở hữu vật cứng mà nó va chạm, và thiệt hại sẽ được áp dụng theo cách đó. Trên thực tế, đó là cách tất cả các tên lửa sẽ hoạt động, chúng không biết "chúng" đang đi về phía nào, chỉ là chúng đang di chuyển (không bao gồm các tên lửa giống như tên lửa). Hiệu ứng AEO chỉ có thể kích hoạt máy va chạm hình cầu khi đến đích và lấy tất cả các vật thể bên trong nó. Cảm ơn đã giúp đỡ.
Douglas Gaskell

Không vấn đề gì. Vui mừng tôi có thể. Quên rằng Unity làm cho tất cả các công cụ va chạm này dễ dàng hơn.
ricksmt
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.