Używam Unity3d do opracowania prototypowej gry hybrydowej RTS / TD. Jakie jest najlepsze podejście do „świadomości” między jednostkami a ich wrogami? Czy to normalne, że każda jednostka sprawdza odległość do każdego wroga i atakuje, jeśli znajdzie się w zasięgu?
Podejście, które zamierzam teraz, to mieć kulę wyzwalającą na każdej jednostce. Jeśli wróg wejdzie na spust, jednostka dowiaduje się o nim i rozpoczyna sprawdzanie odległości. Czy to oszczędza trochę niepotrzebnych kontroli?
Jaka jest tutaj najlepsza praktyka?
Odpowiedzi:
Spójrz na graniczne hierarchie woluminów (BVH). Są one najczęściej używane w wykrywaniu kolizji w celu zmniejszenia liczby kontroli potrzebnych podczas obliczania kolizji lub podczas renderowania w celu wykonania wygładzania elementów na obiektach. Ponieważ już używasz kul, sugerowałbym drzewo kuli, chociaż inne woluminy, takie jak AABB, mogą być bardziej wydajne. Nie jestem pewien, jakie wsparcie ma Unity dla takich rzeczy, jakich nigdy nie użyłem, ale prawdopodobnie jest coś w tym już w wykrywaniu kolizji lub renderowaniu części silnika.
Zasadniczo chciałbyś zgrupować wrogów, którzy są blisko siebie, w wielu sferach rodzicielskich. Gdy jednostka zostanie przeniesiona, sprawdzasz, czy jej sfera wyzwalająca jest skierowana na sferę macierzystą, zamiast sprawdzania każdego wroga. Jeśli kula wyzwalająca przecina się ze sferą macierzystą, sprawdziłbyś każdego wroga wewnątrz. Jeśli nie, możesz odrzucić wszystkich znajdujących się w nim wrogów. Chcesz ustawić wiele poziomów kul w oparciu o maksymalny rozmiar kuli lub liczbę wrogów dla każdej kuli i wykonać sprawdzenie na podstawie kuli najwyższego poziomu. Następnie chodzi tylko o zejście z drzewa, aby sprawdzić każdego wroga bez konieczności przeprowadzania kontroli odległości dla każdego z nich.
Wymagane kroki dla każdej ramki:
Może to zmniejszyć liczbę koniecznych kontroli, gdy jest wielu wrogów, ale narzut związany z aktualizacją i przechowywaniem drzewa może nie być tego wart, gdy nie ma ich zbyt wielu. Nie znam Najwyższego Dowódcy, żeby wiedzieć, czego szukasz, więc zakładam, że „setki”. Musisz się profilować w różnych sytuacjach, aby dowiedzieć się, czy narzut będzie dla Ciebie tego wart.
źródło
Nie ma potrzeby implementowania BVH, ponieważ silnik kolizji Unity już to robi.
Wystarczy założyć dużą ograniczający-Sphere spust do każdej jednostki (reprezentującego jego zakres) i obsłużyć
OnCollisionEnter()
iOnCollisionExit()
zwrotnych, aby śledzić, które wrogowie są w zasięgu każdego urządzenia.Zwróć uwagę, że interesuje Cię przypadek, gdy inna jednostka zderza się z kulą, a nie kiedy inna jednostka zderza się z kulą.
źródło
OnTriggerEnter()
iOnTriggerExit()
prawda?Innym rozwiązaniem, które skaluje się bardzo dobrze i które można wykorzystać do wielu innych rzeczy, jest mapa influeunce. Wygeneruj zestaw płytek siatki wokół urządzenia, aby skanować w promieniu X. Zeskanuj te płytki w poszukiwaniu wroga stojącego na jednym z nich. Jeśli chcesz zdobyć najbliższych wrogów, możesz posortować swój zestaw według odległości.
Może to być najskuteczniejsza metoda, szczególnie jeśli planujesz robić inne rzeczy z mapą wpływów, takie jak mgła wojny lub wyszukiwanie ścieżek.
Oto wideo, które nakręciłem, wyjaśniając tę koncepcję: https://www.youtube.com/watch?v=MEd6XV2Pecw .
A oto implementacja: https://www.youtube.com/watch?v=y_ewoxlZlgc
Nie polecam inicjowania kolekcji jednostek kafelków siatki podczas uruchamiania - zamiast tego tylko wtedy, gdy kolekcja jest potrzebna.
Alternatywnie możesz użyć tablicy o długości X, jeśli wiesz, że na kafelku nigdy nie będzie więcej niż X jednostek.
źródło