Tôi có thể sử dụng loại hành vi lái hoặc logic nào để có được điện thoại di động để bao quanh người khác?


10

Tôi đang sử dụng tính năng tìm đường trong trò chơi của mình để dẫn mob đến một người chơi khác (để theo đuổi họ). Điều này hoạt động để khiến họ vượt lên trên trình phát, nhưng tôi muốn họ dừng lại một chút trước khi đến đích (vì vậy chọn nút áp chót hoạt động tốt).

Tuy nhiên, khi nhiều mob đang theo đuổi điện thoại di động, đôi khi họ "chồng chất lên nhau". Cách tốt nhất để tránh điều này là gì? Tôi không muốn coi mob là mờ đục và bị chặn (vì chúng không phải, bạn có thể đi qua chúng) nhưng tôi muốn mob có một số ý nghĩa về cấu trúc.

Thí dụ:

Hãy tưởng tượng rằng mỗi con rắn tự hướng dẫn cho tôi và nên bao quanh "Setsuna". Để ý làm thế nào cả hai con rắn đã chọn để prong tôi? Đây không phải là một yêu cầu nghiêm ngặt; thậm chí được bù đắp một chút là được. Nhưng họ nên "bao vây" Setsuna.

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


1
Việc xếp chồng chỉ là một mối quan tâm tại điểm đến hoặc cũng trong khi quá cảnh? Tôi đoán sau.
SpartanDovy

Đó là cái thứ hai, @SpartanDovy
Vaughan Hilts

@KromStern Tôi đã thêm một hình ảnh, hy vọng nó sẽ giúp.
Vaughan Hilts

Câu trả lời:


15

Cung cấp cho các đặc vụ của bạn một "điện tĩnh" yếu để khiến chúng đẩy nhau, theo các định luật của Coulomb .

Giả sử đơn giản là các mob nên đẩy nhau ra với cường độ tương đương, thì cũng đủ để tác dụng một lực giữa mọi cặp mob với cường độ some_constant / distance^2, trong đó some_constantcường độ đẩy có thể định cấu hình vàdistance là khoảng cách ngăn cách chúng.

Các lực đẩy sau đó rơi ra với hình vuông của khoảng cách.

Bản chất của Code có một ví dụ tuyệt vời (với bản demo trực tiếp) tại đây . Nó trông như thế này:

kết hợp theo và hành vi riêng biệt

Kết hợp mọi phần tử với nhau là một phép toán bậc hai ( O(n^2)). Nếu bạn thực sựnhiều tác nhân, bạn có thể muốn tối ưu hóa các tính toán lực bằng phép tính xấp xỉ Barnes-Hut , đưa nó xuống log-linear ( O(n log n)) nhưng yêu cầu một góc phần tư .


Liên kết tuyệt vời, Anko. Nhiều đánh giá cao! Tôi chắc chắn sẽ phải đọc toàn bộ trang web này.
Vaughan Hilts

Starcraft (ít nhất là 1) làm điều gì đó tương tự với các đơn vị bay của nó. Nhưng nó chỉ làm điều đó khi chúng ngừng di chuyển, tức là khi chúng đang di chuyển, chúng co cụm lên nhau (hoàn toàn bỏ qua nhau như chướng ngại vật), nhưng khi chúng dừng lại, tất cả bắt đầu lan ra từ những gì trông giống như trung tâm địa phương của một số khu vực thông thường (hình vuông / hình tròn, có lẽ) bao gồm chúng. Điều này trông không đẹp như ví dụ trong câu trả lời, nhưng có lẽ nó sử dụng ít tài nguyên CPU hơn và cũng có thể dễ dàng viết mã hơn ...
Shivan Dragon

@ShivanDragon SC2 thể hiện hành vi tương tự, tất cả chúng đều hội tụ đến đích trong một đám đông, sau đó tạo khoảng trống cho vẻ ngoài thực tế và đẹp mắt (vì vậy các bộ phận của chúng không quay xung quanh).
Kroltan

2
Một số loại lực đẩy có thể là một ý tưởng tốt, nhưng các chi tiết là khó khăn. Tôi đã thử nghiệm những thứ này trong một RTS theo chủ đề không gian và khuyên không nên theo dõi vật lý quá chặt chẽ và thay vào đó mô hình hóa nó để nó hoạt động độc đáo. Một số quan sát: 1) Vì đây không phải là mô phỏng vật lý nên tôi chỉ áp dụng lực trong khoảng cách ngắn. 2) Điều này không thể ngăn các vật thể hữu hạn chồng lên nhau 3) Thế năng cứng dễ gây ra các lỗi số, chẳng hạn như các hạt bị khúc xạ ở vận tốc cao. 4) Một khi bạn có một số lượng đáng kể các hạt và áp lực ở giữa tăng lên, mọi thứ có xu hướng trở nên xấu xí.
CodeInChaos

1

Cách tiếp cận của tôi tương tự như của @ Anko, nhưng dựa trên công trình của Millington và Funge từ Trí tuệ nhân tạo cho các trò chơi .

Đây là hành vi Tách rời sẽ như thế nào, nhưng bạn cần xem xét rằng vận tốc này phải được tính với tốc độ của tác nhân trong chức năng Cập nhật của nó.

public Vector3 GetSeparationVel (float threshold, float decayCoefficient)
{
    threshold = threshold * threshold;
    Vector3 separationVelocity = Vector3.Zero;
    for (int i = 0; i < enemies.Length; i++) {
        if (enemies[i] == this) {
            continue;
        }
        Vector3 direction = this.position - enemies[i].position;
        float distance = direction.LengthSquared();
        float strenght = 0.0f;
        if (distance < (threshold)) {
            strenght = Math.Min(decayCoefficient / distance, this.maxAccel);
            direction.Normalize();
            separationVelocity += strenght * direction;
        }
    }
}
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.