W tej sekcji zaprezentowano, w jaki sposób określić i dostosować drużyny i klasy dla graczy.
Używane urządzenia:
-
2 x kreator klas
-
2 x wybieracz klas
Ustawienia i ekwipunek drużyny

Użyj urządzeń ustawień i ekwipunku drużyny, aby ustawić nazwy drużyn i kolory do wyświetlania na tablicy wyników.
Umieść po jednym urządzeniu dla każdej drużyny w miejscu niewidocznym dla graczy. Aby skonfigurować drużynę rekwizytów, należy ustawić Opcje użytkownika zgodnie z poniższą tabelą.

Opcja | Wartość | Wyjaśnienie |
---|---|---|
Nazwa drużyny | Rekwizyty | Określa ciąg znaków identyfikujący drużynę na tablicy wyników oraz elementach interfejsu w grze. |
Kolor drużyny | Lazurowy | Przypisuje kolor, którym wybrana drużyna będzie zaznaczana na tablicy wyników, w interfejsie w grze oraz w niektórych urządzeniach. |
Drużyna | Indeks drużyny: 1 | Określa, której drużyny dotyczą ustawienia tego urządzenia. |
Aby skonfigurować drużynę łowców, należy ustawić Opcje użytkownika drugiego urządzenia zgodnie z poniższą tabelą.

Opcja | Wartość | Wyjaśnienie |
---|---|---|
Nazwa drużyny | Łowcy | Określa ciąg znaków identyfikujący drużynę na tablicy wyników oraz elementach interfejsu w grze. |
Kolor drużyny | Pomarańczowy | Przypisuje kolor, którym wybrana drużyna będzie zaznaczana na tablicy wyników, w interfejsie w grze oraz w niektórych urządzeniach. |
Drużyna | Indeks drużyny: 2 | Określa, której drużyny dotyczą ustawienia tego urządzenia. |
Kreator klas

Użyj kreatora klas, aby zmodyfikować utworzone drużyny.
Umieść dwa urządzenia kreatora klas, po jednym dla każdej drużyny, w obszarze niewidocznym dla graczy. Aby dostosować drużynę rekwizytów, skonfiguruj Opcje użytkownika zgodnie z poniższą tabelą.
Opcja | Wartość | Wyjaśnienie |
---|---|---|
Nazwa klasy | Rekwizyt | Określa nazwę tej klasy. |
Opis klasy | Ukryj się przed łowcami. Przetrwaj. | Ustawia opis tej klasy. |
Identyfikator klasy | Slot klasy: 1 | Ustawia unikatowy identyfikator dla tej klasy. |
Maks. zdrowie | 1 | Określa maksymalny poziom zdrowia graczy podczas gry. Rekwizyty będą likwidowane jednym trafieniem. |
Lista przedmiotów | Rekwizytomat | Ustawia listę przedmiotów, które ta klasa będzie posiadać. |
Wyposaż przyznany przedmiot | Pierwszy przedmiot | Określa, który przedmiot z listy zostanie przyznany. |
Aby dostosować drużynę łowców, skonfiguruj Opcje użytkownika dla drugiego urządzenia zgodnie z poniższą tabelą.

Opcja | Wartość | Wyjaśnienie |
---|---|---|
Nazwa klasy | Łowca | Określa nazwę tej klasy. |
Opis klasy | Znajdź rekwizyty. Zlikwiduj ich. | Ustawia opis tej klasy. |
Identyfikator klasy | Slot klasy: 2 | Ustawia unikatowy identyfikator dla tej klasy. |
Lista przedmiotów | Pistolet z latarką | Ustawia listę przedmiotów, które ta klasa będzie posiadać. |
Wyposaż przyznany przedmiot | Pierwszy przedmiot | Określa, który przedmiot z listy zostanie przyznany. |
Wybieracz klas

Połącz kreator klas z wybieraczem klas, aby zarządzać niestandardowymi klasami i drużynami, które tworzysz.
Wraz z Verse, ustawienia z tego urządzenia powodują, że gracze na slocie klasy 1 są przenoszeni na slot klasy 2 po respawnie.
Umieść dwa wybieracze klas, po jednym dla każdej drużyny, w obszarze niewidocznym dla graczy. Aby zarządzać drużyną rekwizytów, użyj ustawień z poniższej tabeli, aby skonfigurować Opcje użytkownika dla tego urządzenia.

Opcja | Wartość | Wyjaśnienie |
---|---|---|
Zmiana na klasę | Slot klasy: 1 | Określa klasę, którą powinien otrzymać gracz. |
Widoczność podczas gry | False | To urządzenie nie będzie widoczne w trakcie gry. |
Dźwięk strefy | False | Określa, czy wybieracz klas ma odtwarzać efekty dźwiękowe, gdy gracze wchodzą do strefy. |
Zmiana na drużynę | Indeks drużyny: 1 | Określa drużynę, do której trafi gracz. |
Wyczyść przedmioty po zmianie | True | Określa, czy przedmioty mają zostać usunięte z ekwipunku gracza po zmianie. |
Widoczność przestrzeni podczas gry | False | Określa, czy przestrzeń urządzenia ma być widoczna podczas gry. |
Wyświetlaj efekty wizualne przy aktywacji | False | Określa, czy to urządzenie ma tworzyć efekt wizualne przy zmianie klasy lub drużyny gracza. |
Aby zarządzać drużyną łowców, użyj ustawień z poniższej tabeli w celu skonfigurowania Opcji użytkownika dla tego urządzenia.

Opcja | Wartość | Wyjaśnienie |
---|---|---|
Zmiana na klasę | Slot klasy: 2 | Określa klasę, którą powinien otrzymać gracz. |
Zmiana na drużynę | Indeks drużyny: 2 | Określa drużynę, do której trafi gracz. |
Tworzenie funkcjonalności drużyny za pomocą Verse
W grze Chowany-przebierany udział biorą dwie drużyny: Łowcy i rekwizyty. Musisz być w stanie robić niektóre z tych samych rzeczy dla obu drużyn, aby gra działała. Na przykład:
-
dodawanie gracza do drużyny
-
usuwanie gracza z drużyny
-
wyświetlanie graczom informacji o ich drużynie
Aby stworzyć tę funkcjonalność dla obu drużyn bez powielania kodu, należy utworzyć klasę ze specyfikatorem <abstract>
. Klasy ze specyfikatorem abstract
są przeznaczone do posiadania częściowej funkcjonalności, którą ich podklasy dziedziczą i na której bazują. Najpierw należy utworzyć klasę abstrakcyjną o nazwie base_team
i nadać jej funkcjonalność, którą będą współdzielić drużyny rekwizytów i łowców.
Ten dokument zawiera fragmenty Verse, które pokazują, jak wykonać mechanikę rozgrywki wymaganą w tej rozgrywce. Wykonaj poniższe instrukcje i skopiuj pełny skrypt w kroku 6 tego samouczka.
Utwórz nowy plik Verse w swoim projekcie o nazwie base_team.verse. Nie będzie to urządzenie Verse, więc można je utworzyć jako pusty plik Verse.
using { /Fortnite.com/Characters }
using { /Fortnite.com/Devices }
using { /Fortnite.com/UI }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { /UnrealEngine.com/Temporary/SpatialMath }
using { /UnrealEngine.com/Temporary/UI }
using { /Verse.org/Colors }
using { /Verse.org/Simulation }
log_team := class(log_channel){}
# Ta klasa definiuje urządzenia potrzebne różnym drużynom podczas rozgrywki.
# Ta klasa jest abstrakcyjna, więc nie może być używana samodzielnie. Musi być dziedziczona przez inną klasę.
base_team := class<abstract>:
Logger:log = log{Channel:=log_team}
@editable # Używane do przypisania gracza do drużyny.
ClassSelector:class_and_team_selector_device = class_and_team_selector_device{}
@editable # Używane do przyznawania punktów agentom w drużynie.
ScoreManager:score_manager_device = score_manager_device{}
@editable # Używane do wyświetlania tytułu zadania drużyny.
TeamTitle:hud_message_device = hud_message_device{}
@editable # Używane do wyświetlania opisu zadania drużyny.
TeamDescription:hud_message_device = hud_message_device{}
@editable # Używane do subskrybowania zdarzeń likwidacji członków drużyny (drużyna rekwizytów) lub wrogów (drużyna łowców).
TeamManager:team_settings_and_inventory_device = team_settings_and_inventory_device{}
# Jest to tablica agentów w drużynie.
var TeamAgents<private>:[]agent = array{}
# To zdarzenie jest sygnalizowane, gdy tablica TeamAgents staje się pusta (sygnalizując koniec rundy).
TeamEmptyEvent:event() = event(){}
# Zwraca bieżącą tablicę TeamAgents.
# Jest to wymagane, ponieważ tablica TeamAgents jest prywatna, więc inne klasy nie mogą uzyskać do niej bezpośredniego dostępu.
GetAgents()<decides><transacts>:[]agent =
TeamAgents
# Zwraca rozmiar tablicy TeamAgents
# Wymaga to funkcji, ponieważ tablica TeamAgents jest prywatna, więc inne klasy nie mogą uzyskać do niej bezpośredniego dostępu.
Count()<transacts>:int =
TeamAgents.Length
# Zwraca indeks agenta w tablicy TeamAgents, w przeciwnym razie zawodzi.
FindOnTeam(Agent:agent)<decides><transacts>: int =
Index := TeamAgents.Find[Agent]
# Ustaw agenta w drużynie i powiadom o tym gracza.
InitializeAgent(Agent:agent):void =
AddAgentToTeam(Agent)
ClassSelector.ChangeTeamAndClass(Agent)
DisplayTeamInformation(Agent)
# Dodaj agenta do TeamAgents.
AddAgentToTeam(AgentToAdd:agent):void =
if (not FindOnTeam[AgentToAdd]):
Logger.Print("Dodawanie agenta do drużyny.")
set TeamAgents += array{AgentToAdd}
# Aktywuje urządzenia komunikatów w interfejsie, aby pokazać graczowi, w której drużynie się znajduje
DisplayTeamInformation(Agent:agent):void =
TeamTitle.Show(Agent)
TeamDescription.Show(Agent)
# Gdy agent opuści mecz, usuń go z tablicy TeamAgents i sprawdź, czy runda dobiegła końca.
EliminateAgent(Agent:agent)<suspends>:void =
Sleep(0.0) # Opóźnienie o 1 tyknięcie gry, aby upewnić się, że gracz respawnował się przed kontynuowaniem.
RemoveAgentFromTeam(Agent)
# Usuń agenta z TeamAgents.
# Jeśli usunięty agent był ostatnim, zasygnalizuj TeamEmptyEvent.
RemoveAgentFromTeam(AgentToRemove:agent):void =
set TeamAgents = TeamAgents.RemoveAllElements(AgentToRemove)
Logger.Print("Pozostała liczba agentów w drużynie: {Count()}.")
if (Count() < 1):
Logger.Print("Brak agentów w drużynie. Kończenie rundy.")
TeamEmptyEvent.Signal()
Teraz, gdy ta klasa jest już gotowa, można utworzyć klasy dla drużyny rekwizytów i drużyny łowców. Ponieważ każda z nich dziedziczy po base_team
, ma to kilka zalet:
-
Kod do implementacji każdej drużyny jest znacznie krótszy, ponieważ mają one już swoje wspólne funkcje i dane zdefiniowane w
base_team
. -
Łatwiej jest zrozumieć, który kod jest specyficzny dla drużyny rekwizytów i łowców, ponieważ znajdują się one w swoich własnych klasach, zamiast być wymieszane ze wspólnym kodem.
-
Dodanie większej liczby drużyn do trybu gry jest znacznie łatwiejsze. Każda nowa drużyna dziedziczy po
base_team
, a kod, który sprawia, że nowa drużyna jest inna, znajduje się w jej własnej klasie.
Należy pamiętać, że nie można utworzyć instancji klasy ze specyfikatorem <abstract>
. Należy utworzyć klasę dziedziczącą po klasie abstrakcyjnej i utworzyć jej instancję.
Drużyna łowców
Najpierw utwórz klasę dla drużyny łowców. W swoim projekcie utwórz nowy plik Verse o nazwie hunter_team.verse. Nie będzie to urządzenie Verse, więc można je utworzyć jako pusty plik Verse.
Zadeklaruj klasę o nazwie hunter_team
. Powinna ona być <concrete>
i dziedziczyć po base_team
.
hunter_team := class<concrete>(base_team):
Utworzenie klasy <concrete>
oznacza, że wszystkie pola tej klasy muszą mieć wartość domyślną. Patrz Specyfikatory i atrybuty, aby dowiedzieć się więcej.
Poniżej znajduje się pełny kod skryptu hunter_team.verse.
Klasa hunter_team
posiada dwie funkcje o takich samych nazwach jak funkcje w klasie base_team
. Jest to dozwolone, ponieważ obie mają specyfikator <override>
. Oznacza to, że gdy te funkcje są wywoływane na instancji hunter_team
, używana jest wersja z klasy hunter_team
.
Na przykład, w poniższym kodzie użyta zostanie wersja InitializeAgent()
zdefiniowana w hunter_team
, ponieważ zastępuje ona funkcję o tej samej nazwie w base_team
. Porównaj to z wywołaniem Count()
, które użyje wersji zdefiniowanej w base_team
, ponieważ nie ma funkcji nadpisującej.
HunterTeam:hunter_team = hunter_team{}
# Używa funkcji z hunter_team
HunterTeam.InitializeAgent(StartingHunterAgent)
# Używa funkcji z base_team
HunterTeam.Count()
Dwie nadpisane funkcje również używają (super:)
. Pozwala im to na wywołanie wersji funkcji zdefiniowanych w base_team
, ponieważ base_team
jest nadklasą hunter_team
. W przypadku InitializeAgent()
i EliminateAgent()
, oba używają Logger.Print()
by wydrukować coś w dzienniku. Następnie wywołują odpowiednie funkcje z base_team
. Oznacza to, że funkcje działają dokładnie tak samo, jak wersje w base_team
, z wyjątkiem wywołań Logger.Print()
.
Patrz podklasa, aby dowiedzieć się więcej o <override>
i (super:)
Drużyna rekwizytów
Teraz należy utworzyć klasę dla drużyny rekwizytów. W projekcie utwórz nowy plik Verse o nazwie prop_team.verse. Nie będzie to urządzenie Verse, więc można je utworzyć jako pusty plik Verse.
Musisz zarządzać więcej dla członków drużyny rekwizytów. Mają efekty bicia serca, które muszą być uruchamiane i zatrzymywane w oparciu o licznik czasu i to, jak daleko się poruszają. Muszą również zostać przeniesieni do drużyny łowców, gdy zostaną zlikwidowani.
Aby zarządzać członkami drużyny rekwizytów, użyj metody RunPropGameLoop()
. Metodę tę można traktować jako menadżera całej podróży rekwizytu przez grę. Od momentu spawnu do momentu likwidacji lub opuszczenia gry, metoda ta będzie działać dla każdego członka drużyny rekwizytów.
# Jeśli agent rekwizytów przestanie się poruszać, użyj wyrażenia race, aby sprawdzić, czy agent rekwizytów poruszy się poza MinimumMoveDistance, licznik czasu bicia serca zostanie zakończony lub agent rekwizytów zostanie zlikwidowany.
RunPropGameLoop(PropAgent:agent)<suspends>:void =
Logger.Print("Uruchamianie pętli gry agenta rekwizytów.")
# Wykonuj pętlę w nieskończoność przez zachowanie rekwizytów, aż agent rekwizytów zostanie zlikwidowany lub gracz opuści sesję.
race:
PropAgent.AwaitNoLongerAProp()
loop:
# Poczekaj, aż agent rekwizytów przemieści się na odległość mniejszą niż minimalna, a następnie przejdź dalej.
PropAgent.AwaitStopMoving(MinimumMoveDistance)
# Dopóki agent rekwizytów nie przesunie się poza minimalną odległość, odliczaj do bicia serca, a następnie odtwarzaj bicie serca w nieskończoność.
race:
PropAgent.AwaitStartMoving(MinimumMoveDistance)
block:
CountdownTimer(PropAgent)
PropAgent.StartHeartbeat()
Sleep(0.0) # Gdy wyścig dobiegnie końca (agent rekwizytów poruszy się), uruchom pętlę ponownie.
RunPropGameLoop()
ma jeden parametr, PropAgent
. Jest to stała reprezentująca gracza w drużynie rekwizytów. Posiada również specyfikator <suspends>
, co oznacza, że ukończenie wymaga czasu. W tym przypadku nie zakończy się, dopóki przekazany PropAgent
nie przestanie być w drużynie rekwizytów.
Cała funkcjonalność tej metody jest zawarta w wyrażeniu race. Oznacza to, że metoda nie zostanie ukończona, dopóki jedno z wyrażeń w ramach tego wyrażenia race nie zostanie ukończone. Te wyrażenia to:
-
PropAgent.AwaitNoLongerAProp()
-
loop
Wyrażenie loop w tym wyrażeniu race nigdy się nie kończy. Celowo jest nieskończone. Oznacza to, że AwaitNoLongerAProp()
jest metodą, która zawsze wygra wyścig i ukończy metodę. Używanie wyrażenia race w ten sposób jest jak mówienie programowi, aby uruchamiał określony zestaw kodu w kółko, aż coś się stanie. Patrz race, aby dowiedzieć się więcej o tym potężnym wyrażeniu.
Z tym kodem, AwaitNoLongerAProp()
wygrywa wyścig.
# Wykonuj pętlę do momentu, gdy agent rekwizytów przestanie być częścią tablicy PropAgents. Usunięcie następuje, gdy agent rekwizytów zostanie zlikwidowany i zamieniony w łowcę lub gdy gracz opuści sesję.
(PropAgent:agent).AwaitNoLongerAProp()<suspends>:void =
loop:
if (not FindOnTeam[PropAgent]):
Logger.Print("Usuwanie zachowania agenta rekwizytów.")
break
Sleep(0.0) # Przejdź do następnego tyknięcia gry.
Ta metoda stale sprawdza, czy PropAgent
jest w drużynie rekwizytów. Zaczyna się od pętli, która działa do momentu, aż not FindOnTeam[PropAgent]
się powiedzie, a następnie przerywa, kończąc metodę. Zobacz Pętla i przerwa, aby dowiedzieć się więcej na ich temat.
FindOnTeam[]
jest funkcją z możliwością niepowodzenia, która jest zadeklarowana w base_team
. Zakończy się powodzeniem, jeśli PropAgent
zostanie znaleziony w drużynie rekwizytów. Ale musisz użyć operatora not
, ponieważ chcesz wyjść z pętli tylko wtedy, gdy PropAgent
nie zostanie znaleziony w drużynie rekwizytów. Zobacz Operatory, aby dowiedzieć się więcej o operatorze not
.
Ostatnim krokiem jest dodanie Sleep(0.0)
na końcu pętli. Gwarantuje to, że pętla zostanie uruchomiona raz, a następnie przejdzie do następnej aktualizacji symulacji. Nie trzeba uruchamiać tego sprawdzenia częściej, więc dodano Sleep(0.0)
, aby zwiększyć wydajność. Więcej informacji można znaleźć na stronie przewodnika po interfejsie API Verse dla funkcji Sleep.
Teraz, gdy wiesz już jak działa AwaitNoLongerAProp()
, możesz napisać nieskończoną pętlę, która ściga się z nią w RunPropGameLoop()
.