Witajcie, podróżnicy!
Zaktualizowaliśmy nasz stary system walki i animacji, by poprawić wydajność na obszarach z dużą liczbą graczy wraz z premierą Season of the Guardian. Nowy system (który pieszczotliwie nazywamy Slayer Script) ułatwi nam również ulepszanie walki w przyszłości. Bardzo się staraliśmy, by gra pozostała tak samo dobra, ale zdecydowanie chcemy poznać Wasze opinie o tych zmianach. Od procesu rozwoju po wyzwania, jakie napotkano – dołącz do kierownika technicznego Kevina Christensena, aby przyjrzeć się bliżej temu, co ten nowy system oznacza dla przyszłości New World.
Slayer Script
Slayer Script to język skryptowy oparty na C++. Jest on kompilowany natywnie i dynamicznie wczytywany przez New World, aby zapewnić świetną wydajność, jak i aktualizacje skryptów w czasie rzeczywistym. Może wywoływać zdarzenia (spawnować wrogów, odtwarzać dźwięki itd.), reagować na zdarzenia (np. śmierć wroga, wejście gracza do pokoju itd.), odtwarzać animacje, sterować ruchem postaci i nie tylko. Bardzo dużo pracy można zmieścić w kilku linijkach kodu.
Proces rozwoju
New World zawiera ogromną liczbę obiektów, które wymagają częstych aktualizacji, co sprawia, że trudno wykorzystać w nim tradycyjne języki skryptowe. Język skryptowy, na przykład Lua, wymaga interpretacji i nie może skorzystać z optymalizacji sprzętowej. Podczas gdy wydajność wykonywania w Lua jest dobra, w New World język musiałby zostać użyty dla setek obiektów. Wymagania sprzętowe i obciążenie pamięci byłyby zbyt wysokie. Potrzebowaliśmy rozwiązania, które byłoby najszybsze, jak to możliwe, z możliwym do przyjęcia wpływem na proces rozwoju.
Nasz pierwotny system skryptów postaci działał dobrze podczas tworzenia gry, ale z czasem przestał radzić sobie jeżeli chodzi o wydajność, wykorzystanie pamięci i przypisywanie środowiska wykonawczego wraz z rozwojem New World. Doprowadziło to do uruchomienia Slayer Script jako drugoplanowego projektu. Slayer Script zredukował obciążenie do kilku przypisań, a jego natywnie skompilowany kod jest bardzo zwięzły, co znacznie zmniejszyło wykorzystanie pamięci środowiska wykonawczego.
Z początku mieliśmy pomysł, żeby wykorzystać Slayer Script do sterowania postacią gracza. Postać gracza jest zdecydowanie najbardziej obciążającym obiektem w grze New World. Znaczna część projektu poświęcona była odczytywaniu instrukcji gracza oraz kontrolowaniu animacji. Zadanie to zajęło bardzo dużo czasu. Okazało się, że zespół Ekspedycji jako pierwszy wykorzystał skrypt Zabójcy, co nie wymagało obsługi instrukcji gracza ani animacji. Wtedy właśnie Slayer Script przeistoczył się w język skryptowy bardziej ogólnego zastosowania. Dopiero niedawno Slayer Script został wykorzystany do celu, w którym został stworzony.
Cele
Ponad 400 działań zostało ręcznie przekonwertowanych na nowy system, aby zapewnić, że rozgrywka pozostanie niezmieniona. Przyświecały nam następujące cele:
Wykorzystać natywnie skompilowany język programowania C++ tak, aby działał najszybciej, jak to możliwe.
Zmniejszyć obciążenie pamięci poprzez zmniejszenie liczby stanów, które trzeba przechowywać.
Ulepszyć skalowalność poprzez wykorzystanie architektury o mniejszym wpływie na wykonywanie nowych zachowań.
Wczytywanie na gorąco, aby umożliwić rozwój środowiska wykonawczego.
Łatwiejsze debugowanie.
Zmniejszenie obciążenia pamięci okazało się najprostszym problemem do rozwiązania. Slayer Script został zaprojektowany tak, aby przechowywał stan w jednym miejscu, a wszystkie zachowania zostały stworzone w taki sposób, aby można je było dzielić pomiędzy wszystkimi instancjami danego skryptu.
Skalowalność będzie zadaniem ciągłym. Nawet język C++ można wykorzystać w nieefektywny sposób. Należy zachować ostrożność przy wprowadzaniu nowych funkcji, ale C++ zapewnia rozbudowane rozwiązania do śledzenia wydajności i obserwowania wykonywania operacji.
Poprzedni system był trudno do debugowania. Stworzyliśmy narzędzia, które miały w tym pomóc, ale przejście krok po kroku przez wykonanie nie było możliwe. Każdej projektant posiadający dostęp do narzędzia do debuggingu może teraz ustalać punkty przerwania, kontrolować użycie pamięci oraz przejść krok po kroku przez wykonanie skryptu. Debugowanie poprzedniego systemu zajmowało niesamowicie dużo czasu wyłącznie ze względu na to, jak wyglądał ten proces. Debugowanie złożonych skryptów wciąż jest trudne, ale przynajmniej sposób jest prosty.
Wyzwania
Największym wyzwaniem było utrzymanie szybkiego tempa iteracji. Projektanci muszą być w stanie szybko widzieć rezultaty swojej pracy. W przypadku skompilowanego języka, normalnie oznaczałoby to zamknięcie gry, wprowadzanie zmian, kompilację, a następnie ponowne uruchomienie gry, aby zobaczyć rezultaty. Slayer Script został wbudowany w moduł, który można wczytać, podczas gdy gra jest uruchomiona. Dynamiczne ponowne wczytanie modułu może być podchwytliwe, więc wszelkie odniesienia do obiektów wewnątrz modułu muszą zostać wypuszczone zanim moduł zostanie rozładowany i odzyskane po ponownym wczytaniu modułu. Jeżeli nie zostanie to przeprowadzone w odpowiedni sposób, gra lub narzędzia się zawieszą.
Dzięki użyciu C++ wykorzystanie pamięci i wydajność systemu mają duży potencjał. C++ został stworzony z myślą o tworzeniu wysoce wydajnych aplikacji i maksymalnej efektywności. Jest to dojrzały język programowania, który posiada wiele narzędzi pomocnych w tworzeniu oraz pomiarze wydajności.
Kolejnym wyzwaniem było ukrycie złożoności C++ przed osobami, które będą korzystały ze Slayer Script. C++ potrafi być trudnym w użyciu językiem, natomiast jeżeli wykorzystać go jako język skryptowy, nie musi on być bardziej złożony niż inne tego typu języki. W tym zakresie jest jeszcze duże pole do ulepszeń. Będzie to wciąż nasz cel.
Z niecierpliwością czekamy na Wasze opinie w PTR Season of the Guardian. Dziękujemy za Wasze wsparcie i do zobaczenia w Aeternum!