Dobre techniki synchronizowania akcji w grze z określonymi czasami animacji?

10

Znalazłem więc problem w grze, nad którą pracuję, ale wydaje się, że jest to dość fundamentalna rzecz, która prawdopodobnie pojawia się w wielu grach.

Moja gra wymaga, aby niektóre funkcje gry występowały w bardzo konkretnym momencie podczas animacji postaci. Tak więc, jak mówi tytuł, zastanawiam się, jakie są dobre techniki i podstawowe strategie synchronizacji wydarzeń / funkcji / akcji związanych z rozgrywką do określonych punktów w animacji postaci.

Oto kilka prostych przykładów tego, o czym mówię w różnych typach gier:

  • Twoja postać przeładowuje broń w strzelance . Twoja postać odtwarza swoją animację „przeładowania”, ale ważne jest, aby funkcja, która ustawia zmienną currentAmmo, była wywoływana tylko w tym samym momencie, kiedy magazynek został zamieniony, a pistolet wystrzelił. Może to być punkt w środku animacji przeładowania.

  • W turowej grze RPG twoje postacie stoją w szeregu naprzeciw linii wrogów. Po otrzymaniu rozkazu ataku jedna z twoich postaci biegnie / podskakuje na jednego z wrogów i tnie gigantyczny miecz, po czym biegnie / skacze z powrotem na swoje miejsce. Chcesz się upewnić, że wróg zostanie uszkodzony w tym samym momencie, w którym odtwarzana jest animacja cięcia - w pewnym momencie między podbiegiem a powrotem.

  • W grze typu stealth Twoja postać może podkraść się i wchodzić w interakcje z komputerami i przyciskami na całym świecie. Może jest przycisk, który wyłącza zasilanie świateł placówki, którą infiltrujesz. Kiedy przycisk akcji jest wciśnięty, twoja postać wyciąga rękę i naciska przycisk, a następnie powraca do swojej bezczynności. Chcesz, aby światła wyłączały się dokładnie w punkcie animacji „push_button”, gdy przycisk jest wciśnięty.

Trzeba przyznać, że mój szczególny przypadek jest najbardziej podobny do drugiego przykładu , w którym stworzyłem animację, w której moja postać turowa rzuca się do przodu podczas ataku i chcę, aby obrażenia zostały zastosowane dokładnie w momencie, w którym animacja wydaje się nawiązać kontakt. . Ponieważ moja gra wykorzystuje system turowy (wyobraź sobie coś takiego jak Final Fantasy lub Fire Emblem) chcę obrażeń / leczenia / magii / itp. do zastosowania we właściwym czasie podczas animacji każdej postaci, mimo że tak naprawdę nie używam kolizji / hitboxów.

Należy wspomnieć, że robię moją grę w popularnym silniku gry, a teraz jestem obsługi to za pomocą swoich animacji zdarzenia lub notyfikuje osiągnąć coś zbliżone do pożądanych rezultatów - moje wykonuje charakter pewnego polecenia i wyzwala animacja specyficzna dla komendy (tj. „polecenie_ataku”) i zasoby animacji dla każdego z moich poleceń muszą zawierać zdarzenie animacji / powiadomić „wywołanie zwrotne” w funkcji ExecuteCommand moich postaci. Innymi słowy - postać nakazuje odtworzenie animacji ataku, a następnie animacja ataku emituje zdarzenie / powiadamia oddzwonienie do postaci dokładnie w momencie animacji, kiedy należy zadać obrażenia.

Szczerze mówiąc, na razie to działa, ale wydaje mi się, że jest źle - jakby brakowało mi tutaj części większego obrazu! Jednym z powodów, dla których ta metoda wydaje się niewłaściwa, jest połączenie logiki gry z zasobami animacji; jeśli mój zasób animacji zapomni o dołączeniu zdarzenia / wywołania zwrotnego ExecuteCommand (), polecenie nie wykona się poprawnie i potrzebny jest dodatkowy kod, aby sprawdzić, czy animacja polecenia zakończyła się bez wykonania polecenia. Jest bałagan i oznacza, że ​​moja gra ma dziwną zależność od swoich zasobów. Oczywiście chcę, aby obrażenia wystąpiły w określonym momencie podczas animacji ataku, ale czuję się naprawdę dziwnie, nazywając kod gry wewnątrz zasobów animacji.

Więc co tu przeoczę? Jakie są dobre ogólne techniki radzenia sobie z tego rodzaju sytuacjami, w których chcesz, aby pewne ważne działania rozgrywki miały miejsce w określonych momentach podczas animacji?

Edycja: Aby wyjaśnić, nie jest to pytanie specyficzne dla silnika, ani nie szukam projektów / technik specyficznych dla silnika. Interesują mnie ogólne techniki synchronizacji animacji / rozgrywki, które można wykorzystać w projektach gier niezależnie od zastosowanych technologii.

MrKatSwordfish
źródło
1
Jestem zmieszany. Mówisz, że chcesz, aby rozgrywka zależała od czasów animacji, ale potem mówisz, że nie chcesz, aby rozgrywka zależała od twoich zasobów, a animacje są rodzajem zasobów. Jak można oczekiwać, że te życzenia będą kompatybilne?
Anko
Chcę, aby niektóre elementy gry były zsynchronizowane z animacją. Jednak synchronizacja między dwiema rzeczami nie zawsze oznacza zależność, prawda? Interesują mnie niektóre techniki, za pomocą których ludzie synchronizują swoje animacje z grą. Powiedziałem, co próbowałem i co obecnie robię, aby to osiągnąć - i moje pytanie brzmi: czy istnieje inna / lepsza / alternatywna technika, której można użyć, czy jest to (zdarzenia animacji / powiadomienia / wywołania zwrotne ułożone w aktywa) w standardowy sposób? Czy tego używasz w swoich projektach?
MrKatSwordfish

Odpowiedzi:

5

W celu synchronizacji musisz zdecydować, kto (Twój kod, animacje lub żadne) jest organem odpowiedzialnym za czas - „pokonać”, do którego wszyscy inni „tańczą”.

Różne układy pasują do różnych gier:

  • Animacje są organem odpowiedzialnym za pomiar czasu (bieżąca konfiguracja)

    Kod gry może wyzwalać animacje. Kiedy animacje osiągają określone punkty, wywołują zdarzenia (np. Zakończone przeładowanie), na które może zareagować kod gry (np. Reset dostępnej amunicji).

    Jeśli dokładny czas animacji (niezależnie od stanu gry) jest ważną częścią gry, lub jeśli chcesz, aby animatorzy kontrolowali taktowanie, rozważ to podejście.

    Narzędzia do animacji Blender (3D) i Kręgosłup (2D) pozwalają animatorowi zdefiniować zdarzenia, które może subskrybować kod gry.

  • Kod jest organem do pomiaru czasu

    Odwrotność powyższego: Zdarzenia mające miejsce w świecie gry (np. Gracz decydujący się na przeładowanie broni) powodują uruchomienie animacji i przekazanie parametrów (np. Czas do zakończenia przeładowania). Każda animacja korzysta z dostarczonych parametrów w celu modyfikacji jej wyglądu (np. Uruchomienie animacji z odpowiednią prędkością, tak aby „przeładowana część” miała miejsce, gdy została określona).

    Animacje mogą także nasłuchiwać zdarzeń w grze (np. Gracz anuluje przeładowanie lub kuca podczas przeładowywania) i odpowiednio modyfikuje ich wygląd.

    Jeśli twoje animacje mogą być elastyczne pod względem czasu, twoja gra w dużym stopniu opiera się na treści generowanej proceduralnie lub chcesz, aby programiści kontrolowali taktowanie, rozważ to podejście.

    Przerost animacje postaci „s są w dużej mierze skonstruowany w ten sposób: David Rosen wyjaśnia to w swojej GDC 14 Dyskusja (patrz konkretnie Ruch i Ruch ciąg dalszy na segmenty).

  • Domniemany czas (organ zewnętrzny)

    W grach rytmicznych lub w innych sytuacjach, w których czas jest kontrolowany z zewnętrznego źródła (w grach rytmicznych rytm ścieżki muzycznej) sensowne może być modelowanie takich rzeczy. Kod i animacje gry mogą odczytywać globalny znacznik czasu i stan gry, a następnie odpowiednio się zachowywać bez komunikacji.

    Jeśli stan gry i animacje są w dużej mierze zależne od zewnętrznego organu mierzącego czas, rozważ to podejście.

Możesz oczywiście zastosować różne podejścia do różnych systemów w swojej grze. (Na przykład gry rytmiczne często używają rytmu utworu jako zewnętrznego autorytetu, ale animacje nadal nasłuchują zdarzeń interakcji gracza, aby anulować lub zmienić wygląd przechowywanych nut.)

Anko
źródło
0

Czytałem gdzieś, że prawie wszystkie problemy obliczeniowe można rozwiązać za pomocą dodatkowej warstwy abstrakcji, i nie widzę, aby twój przypadek był inny.

W przypadku tego wymagania ogólnie widzę warstwę kontrolującą stan postaci. W ten sposób postać będzie miała aktualną animację i aktualny stan. Każdy na własną odpowiedzialność.

Animacja odpowiada tylko za grafikę, a stan obsługuje logikę specyficzną dla gry.

W mojej grze walki stan jest obiektem, który dziedziczy po klasie BaseState i ma metodę Update (). Każda postać ma kolekcję stanów, ale jednocześnie można przypisać tylko jeden. A metoda Update () bieżącego stanu jest wywoływana raz na ramkę.

Jest w Aktualizacji () stanu, w którym robię całą tę logikę: ustaw prędkość postaci w określonej ramce, zwiększanie / zmniejszanie zdrowia itp.

Emir Lima
źródło