Ten samouczek bazuje na koncepcjach opisanych w artykule Persystencja danych statystyk graczy, więc najpierw się z nim zapoznaj!
Tablice rankingowe stanowią tradycyjny element gier rywalizacyjnych, umożliwiając graczom pochwalenie się swoimi umiejętnościami i zyskanie sławy wśród innych. Pomagają one graczom zyskać poczucie postępu i zachęcają do wracania do gry, aby móc obserwować, własną drogę po szczeblach rankingu.
Persystencja Verse oferuje narzędzie, które umożliwia tworzenie takich tablic rankingowych w celu wzbogacenia swojej przygody o element rywalizacji. Z samouczka dotyczącego persystencji danych statystyk graczy wiesz już, w jaki sposób możesz śledzić możliwe do persystencji dane między sesjami gry i jak modyfikować oraz aktualizować te dane w oparciu o różne zdarzenia. Teraz wykorzystasz tę wiedzę, aby nauczyć się tworzenia kompletnych lokalnych tablic rankingowych, sortowania statystyk graczy oraz łączenia tych wszystkich elementów w grze wyścigowej!
Używane funkcje języka Verse
Klasa: W tym przykładzie utworzysz możliwą do persystencji klasę Verse, która będzie śledzić grupę statystyk dla poszczególnych graczy.
Konstruktor: Konstruktor to specjalna funkcja, która tworzy instancję klasy, z którą jest związana.
Weak_map: weak_map to prosta mapa, w przypadku której nie można wykonywać iteracji. Możliwe do persystencji dane Verse muszą być przechowywane w weak_map.
Ustawianie poziomu
W tym przykładzie wykorzystano następujące rekwizyty i urządzenia:
3 x urządzenie billboardu: Te urządzenia będą wyświetlać statystyki poszczególnych graczy z całego czasu życia i będziesz je sortować w zależności od punktów czasu życia, aby zaprezentować w lobby wykaz najlepszych graczy.
3 x urządzenie odwołania do gracza: W połączeniu z billboardami odwołania do gracza pozwolą spersonalizować najlepszych graczy, aby inni wiedzieli, na kogo uważać podczas gry.
3 x urządzenie punktu kontrolnego: Są to punkty kontrolne, które gracze muszą zaliczyć, aby ukończyć wyścig.
1 x urządzenie menadżera wyścigu: Śledzi, kiedy gracze rozpoczynają i kończą wyścig, a następnie przyznaje im punkty w zależności od lokaty na mecie.
1 x urządzenie generatora pickupów: Spawnuje pojazd, który będzie używany podczas wyścigu, jednak możesz go zastąpić dowolnym pojazdem pasującym do przygody.
Postępuj zgodnie z poniższą instrukcją, aby skonfigurować poziom:
Billboardy i odwołania do graczy
Do wyświetlenia statystyk graczy potrzebna jest kombinacja billboardów i odwołań do graczy. Każdy billboard będzie wyświetlał statystyki czasu życia gracza, natomiast odwołanie do gracza pozwoli utworzyć wizualną reprezentację danego gracza. Postępuj zgodnie z poniższą instrukcją, aby dodać te elementy:
Dodaj do swojego poziomu trzy urządzenia odwołania do gracza, umieszczając je obok siebie.
Wybierz je w Outlinerze dla każdego odwołania do gracza. W panelu szczegółów w sekcji Opcje użytkownika ustaw w pozycji Kolor niestandardowy kolor, który chcesz zastosować do oznaczenia w lobby graczy zajmujących pierwsze, drugie i trzecie miejsce. W tym przykładzie zastosowane kolory to złoto, srebro i brąz.
Dodaj do swojego poziomu trzy urządzenia billboardu, umieszczając je przed poszczególnymi odwołaniami do graczy. Gdy rozpocznie się gra, będą one aktualizowane o statystyki każdego z graczy przy użyciu Verse.
Punkty kontrolne, pickup i menadżer wyścigu
Tworzysz wyścig, więc potrzebujesz czegoś, czym można się ścigać! Musisz dodać również punkty kontrolne do zaliczenia oraz menadżera wyścigu, który pokieruje wyścigiem podczas gry. Postępuj zgodnie z poniższą instrukcją, aby dodać te elementy:
Dodaj do swojego poziomu trzy urządzenia punktu kontrolnego wyścigu. Ustaw je w takiej kolejności, w jakiej gracze powinni przez nie przejechać. Dla każdego punktu kontrolnego upewnij się w Outlinerze, że wartość Numer punktu kontrolnego odpowiada kolejności, w jakiej gracze będą przejeżdżali przez punkty kontrolne.
Dodaj jedno urządzenie menadżera wyścigu do poziomu. Jego zadaniem będzie uruchomienie wyścigu i pokierowanie graczy w kierunku punktów kontrolnych. Później będziesz nasłuchiwać zdarzenia
RaceCompletedEvent()z tego urządzenia, aby wiedzieć, kiedy gracz ukończy wyścig.Dodaj jedno urządzenie generatora pickupów do swojego poziomu. Pojazd jest opcjonalny, jednak w tym przewodniku wykorzystano pickup pasujący do szablonu szosy, aby gracze mieli się czym poruszać.
Modyfikowanie tabeli statystyk
W tym przykładzie wykorzystano zmodyfikowaną wersję pliku player_stats_table z artykułu Persystencja danych statystyk graczy. Plik będzie wyglądał podobnie, jak w tamtym przykładzie, jednak zawiera ważne różnice, które zmieniają sposób implementacji.
Aby utworzyć tabelę statystyk graczy, wykonaj następującą procedurę:
W swojej klasie
player_stats_table:Usuń statystykę
Losses.Zmień statystykę
ScorenaPoints.Verse# Tracks different persistable stats for each player. player_stats_table<public>:= class<final><persistable>: # The version of the current stats table. Version<public>:int = 0 # The Points of a player. Points<public>:int = 0 # The number of Wins for a player.
Zmodyfikuj funkcję konstruktora
MakePlayerStatsTable()w swoim pliku, aby odzwierciedlała zaktualizowane statystyki.Verse# Creates a new player_stats_table with the same values as the previous player_stats_table. MakePlayerStatsTable<constructor>(OldTable:player_stats_table)<transacts> := player_stats_table: Version := OldTable.Version Points := OldTable.Points Wins := OldTable.WinsDodaj nową strukturę
player_and_statsdo pliku player_stats_table.verse. Struktura ta zawiera odwołanie doplayeroraz jego klasęplayer_stats_table, umożliwiając wykorzystanie obydwu danych w funkcji bez konieczności ich wielokrotnego pobierania. Gotowa strukturaplayer_and_statspowinna wyglądać następująco:Verse# Structure for passing a player and their stats as arguments. player_and_stats<public> := struct: Player<public>:player StatsTable<public>:player_stats_table
Zarządzanie statystykami
Podobnie jak w przypadku persystencji danych statystyk graczy, wykorzystasz plik menadżera do zarządzania i rejestrowania zmian w statystykach dla graczy.
Aby utworzyć zmodyfikowany plik player_stats_manager, wykonaj poniższe kroki.
Zmodyfikuj sygnaturę funkcji
InitializeAllPlayers()orazInitializePlayer()naInitializeAllPlayerStats()iInitializePlayerStat(). Nazwy te lepiej odzwierciedlają ich relację względem funkcjiGetPlayerStat(). Zaktualizowana funkcja powinna wyglądać następująco:Verse# Initialize stats for all current players. InitializeAllPlayerStats<public>(Players:[]player):void = for (Player : Players): InitializePlayerStat(Player) # Initialize stats for the given player. InitializePlayerStat<public>(Player:player):void= if: not PlayerStatsMap[Player] set PlayerStatsMap[Player] = player_stats_table{}Zmodyfikuj sygnaturę funkcji
AddScore()naAddPoints(). Następnie usuń funkcjęAddLosses(), ponieważplayer_stats_tablenie zawiera już tej wartości. Gotowy plikplayer_stats_managerpowinien wyglądać następująco:Verse# This file handles the code for initializing, updating, and returning player_stats_tables # for each player. It also defines an abstract stat_type class to use for updating stats, and the # StatType module to use when displaying stats. using { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Return the player_stats_table for the provided Agent. GetPlayerStats<public>(Agent:agent)<decides><transacts>:player_stats_table=
Tworzenie tablic rankingowych graczy
Aby wyświetlić dane graczy na tablicy rankingowej, potrzebujesz kilku rzeczy. Musisz znaleźć sposób na aktualizowanie tekstu na billboardach oraz graczy w urządzeniach odwołania do gracza. Potrzebujesz również sposobu sortowania tych urządzeń, aby najlepsi gracze zajmowali szczytowe miejsca na tablicy rankingowej. Funkcje te mają podobny cel polegający na modyfikowaniu urządzeń w poziomie, dlatego dobrym rozwiązaniem jest zgrupowanie ich we wspólnym pliku.
Aby utworzyć funkcje, które będą aktualizowały urządzenia w poziomie, wykonaj poniższą procedurę:
Utwórz nowy plik Verse o nazwie player_leaderboards.verse. W tym pliku będą przechowywane funkcje stosowane wspólnie do aktualizacji tablic rankingowych w poziomie.
Do skonfigurowania tekstu na billboardzie użyjesz komunikatu, do którego można przekazywać argumenty. Utwórz nowy komunikat o nazwie
StatsMessage, który będzie pobierałCurrentPlayer,PointsiWinstypumessage, a następnie zwracał połączony tekst jakomessage.Verse# The message to display on the stats billboard. StatsMessage<localizes>(CurrentPlayer:message, Points:message, Wins:message):message= "{CurrentPlayer}:\n{Points}\n{Wins}"Dodaj jeszcze trzy zmienne
message, po jednej dla każdej z danych wejściowych doStatsMessage. KomunikatPlayerTextpobieraAgent, komunikatPointsTextpobiera punkty tego agenta, a komunikatWinsTextpobiera zwycięstwa tego agenta. ObiektStatsMessageutworzy komunikat na podstawie wszystkich tych danych, aby czytelnie zaprezentować dane w poziomie.Verse# The message to display on the stats billboard. StatsMessage<localizes>(CurrentPlayer:message, Points:message, Wins:message):message= "{CurrentPlayer}:\n{Points}\n{Wins}" PlayerText<localizes>(CurrentPlayer:agent):message = "Player {CurrentPlayer}" PointsText<localizes>(Points:int):message = "Total Points {Points}" WinsText<localizes>(Wins:int):message = "{Wins} Total Wins"Aby zaktualizować billboard, wywołasz funkcję
UpdateStatsBillboard()z samouczka dotyczącego persystencji danych statystyk graczy. Funkcja ta jest zdefiniowana w pliku odrębnym od pliku urządzenia Verse, dlatego musisz dodaćStatsBillboardjako dodatkowy argument, aby wskazać, który billboard będzie aktualizowany.Verse# Updates the given billboard device to display the stats of the given player. UpdateStatsBillboard<public>(Player:agent, StatsBillboard:billboard_device):void=Najpierw pobierz statystyki gracza przekazane jako argument przy użyciu
GetPlayerStats[]. Nie musisz się odwoływać doplayer_stats_manager, ponieważ nie jest to już odrębna klasa. Następnie utwórz nowyStatsMessageprzy użyciu gracza oraz wartościPointsiWinsz jegoCurrentPlayerStats. Na końcu wywołajSetText()dlaStatsBillboard, aby zaktualizować tekst na billboardzie w poziomie. Gotowa funkcjaUpdateStatsBillboard()powinna wyglądać następująco:Verse# Updates the given billboard device to display the stats of the given player. UpdateStatsBillboard<public>(Player:agent, StatsBillboard:billboard_device):void= if: CurrentPlayerStats := GetPlayerStats[Player] then: PlayerStatsText := StatsMessage( PlayerText(Player), PointsText(CurrentPlayerStats.Points), WinsText(CurrentPlayerStats.Wins)) StatsBillboard.SetText(PlayerStatsText)
Sortowanie i wyświetlanie najlepszego gracza
Zanim przejdziesz dalej, zastanów się, w jaki sposób chcesz posortować te billboardy. Czy chcesz, aby na szczycie znalazł się gracz, który ma najwięcej punktów czy ten, który ma najwięcej zwycięstw? A może chcesz posortować graczy według innych statystyk? W każdym z tych przypadków potrzebujesz odpowiedniej metody, a odpowiedzią jest algorytm sortowania. Wykorzystując algorytm sortowania oraz funkcję porównawczą, możesz zdefiniować kryteria, według których będzie odbywać się sortowanie. Następnie posortuj billboardy i odwołania do graczy, aby wyświetlić najlepszych graczy ze swojej przygody. W tym przykładzie wykorzystano algorytm sortowania przez scalanie, ale możesz zaimplementować własny.
Wykonaj poniższą procedurę, aby dodać porównanie i sortowanie do swoich billboardów oraz zakończyć aktualizowanie urządzeń w poziomie.
W pliku
player_stats_tablezdefiniujesz funkcje porównania dla każdej ze statystyk. Każda z nich pobiera strukturęLeftiRightplayer_and_statsi porównuje je w oparciu o konkretną statystykę. Funkcje te mają modyfikatory<decides><transacts>, więc jeśli porównanie się nie powiedzie, funkcja również się nie powiedzie. Otrzymasz na przykład informację, żeLeftjest mniejsze niżRight. Dodaj nową funkcję o nazwieMorePointsComparison()do pliku player_stats_table.verse. Ta funkcja sprawdza, czy wartośćLeft.Pointsjest większa niżRight.Points, a jeśli nie jest, kończy się niepowodzeniem. W przypadku powodzenia zwracaLeft`.Verse# Returns Left if Left has greater Points than Right. MorePointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:Left= Left.StatsTable.Points > Right.StatsTable.Points LeftSkopiuj tę funkcję trzy razy, raz dla porównania mniejszej liczby punktów i dwa razy dla porównania zwycięstw. Otrzymane funkcje powinny wyglądać następująco:
Verse# Returns Left if Left has greater Points than Right. MorePointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats= Left.StatsTable.Points > Right.StatsTable.Points Left # Returns Left if Left has less Points than Right. LessPointsComparison<public>(Left:player_and_stats, Right:player_and_stats)<decides><transacts>:player_and_stats= Left.StatsTable.Points < Right.StatsTable.Points LeftDodaj algorytm sortowania przez scalanie. Możesz umieścić kod w osobnym pliku lub module i przetestować algorytm na dostarczonym pliku testowym.
Wróć do
player_leaderboardsi dodaj nową funkcjęUpdateStatsBillboards(). Ta funkcja pobiera tablicę agentów i tablicę billboardów, sortuje je i wywołujeUpdateStatsBillboard(), aby zaktualizować każdy billboard w poziomie.Verse# Update the stats billboards by sorting them based on the amount of lifetime points # each player has. UpdateStatsBillboards<public>(Players:[]agent, StatsBillboards:[]billboard_device):void=W
UpdateStatsBillboards()zainicjuj nową zmienną tablicyplayer_and_statso nazwiePlayerAndStatsArray. Ustaw wartość równą wynikowi wyrażeniafor. W tym wyrażeniufordla każdegoagentpobierzplayerdla tegoagenti pobierz jegoplayer_stats_table, używającGetPlayerStats[]. Następnie zwróć strukturęplayer_and_statszbudowaną zplayeri jego tabeli statystyk.VerseUpdateStatsBillboards<public>(Players:[]agent, StatsBillboards:[]billboard_device):void= var PlayerAndStatsArray:[]player_and_stats = for: Agent:Players Player := player[Agent] PlayerStats := GetPlayerStats[Player] do: player_and_stats: Player := Player StatsTable := PlayerStatsAby posortować
PlayerAndStatsArray, zainicjuj nową zmiennąSortedPlayersAndStatsz zastosowaniem wyniku wywołaniaMergeSort(), przekazując tablicę iMorePointsComparison. Po posortowaniu w wyrażeniufor, wykonaj iterację przez każdy element wSortedPlayerAndStats, przechowując indeks elementu w zmiennejPlayerIndex. UżyjPlayerIndexdo indeksowania do tablicyStatsBillboards, a następnie wywołajUpdateStatsBillboard, przekazując gracza i billboard do aktualizacji. Gotowa funkcjaUpdateStatsBillboards()powinna wyglądać następująco:Verse# Update the stats billboards by sorting them based on the amount of lifetime points # each player has. UpdateStatsBillboards<public>(Players:[]agent, StatsBillboards:[]billboard_device):void= var PlayerAndStatsArray:[]player_and_stats = for: Agent:Players Player := player[Agent] PlayerStats := GetPlayerStats[Player] do: player_and_stats:Aby zaktualizować odwołania do gracza, użyjesz bardzo podobnej funkcji o nazwie
UpdatePlayerReferences(). Ta funkcja pobiera tablicęplayer_reference_devicezamiast billboardów, a zamiast wywoływaćUpdateStatsBillboard()na końcu, wywołujeRegister()na urządzeniu odwołania do gracza dla każdego gracza. Skopiuj kodUpdateStatsBillboard()do nowej funkcjiUpdatePlayerReferences()z zastosowaniem powyższych zmian. Gotowa funkcjaUpdatePlayerReferences()powinna wyglądać następująco:Verse# Update the player references devices by sorting them based on the amount # of lifetime points each player has. UpdatePlayerReferences<public>(Players:[]player, PlayerReferences:[]player_reference_device):void= var PlayerAndStatsArray:[]player_and_stats = for: Agent:Players Player := player[Agent] PlayerStats := GetPlayerStats[Player] do: player_and_stats:
Tablice rankingowe graczy w twoim poziomie
Wszystko gotowe, więc czas zaprezentować swoich graczy! Utworzysz urządzenie do przyznawania punktów graczom za interakcję z przyciskiem oraz posortujesz odwołania do graczy i billboardy tak, aby najlepsi gracze byli z przodu i na środku. Aby utworzyć urządzenie Verse do testowania rankingów w poziomie, wykonaj poniższe kroki:
Utwórz nowe urządzenie Verse o nazwie player_leaderboards_example. Aby uzyskać informacje na ten temat, patrz: Tworzenie własnego urządzenia przy użyciu Verse.
Na początku definicji klasy
player_leaderboards_example classdodaj następujące pola:Edytowalna tablica urządzeń odwołania do graczy o nazwie
PlayerReferences. Zapewniają one wizualną reprezentację każdego gracza w wyścigu.Verse# Visual representations of each player. @editable PlayerReferences:[]player_reference_device = array{}Edytowalna tablica urządzeń billboardu o nazwie
Leaderboards. Wyświetlają one statystyki każdego gracza na billboardzie w poziomie.Verse# Billboards that display each player's stats. @editable Leaderboards:[]billboard_device = array{}Edytowalne urządzenie menedżera wyścigu o nazwie
RaceManager. Będziesz subskrybować zdarzenia z menedżera wyścigu, aby wiedzieć, kiedy gracz ukończy wyścig.Verse# Tracks when players complete a race, with the players in the first spot being awarded a win. @editable RaceManager:race_manager_device = race_manager_device{}Edytowalna liczba całkowita o nazwie
PlacementRequiredForWin. Jest to miejsce, na którym gracz musi się znaleźć, aby odnieść zwycięstwo.Verse# The placement of a player must be at or below to award a win. @editable PlacementRequiredForWin:int = 1Edytowalna tablica liczb całkowitych o nazwie
PointsPerPlace. Jest to liczba punktów, które każdy gracz zdobywa na podstawie zajętego miejsca.Verse# The number of points a player in each place earns. # Adjust this to award your players the desired amount of score # based on their placement. @editable PointsPerPlace:[]int = array{5, 3, 1}Zmienna z liczbą całkowitą o nazwie
CurrentFinishOrder. Jest to miejsce gracza, który ostatnio ukończył wyścig.Verse# The spot of the player who just finished the race. # The first three players to finish the race will be awarded a win. var CurrentFinishOrder:int = 0
Przyznawanie statystyk na podstawie zajętego miejsca
Gdy gracz ukończy wyścig, zaktualizujesz jego statystyki w oparciu o zajęte miejsce. Gracze, którzy zajęli wysokie miejsca, powinni otrzymać większą liczbę punktów, a gracze, którzy zajęli najlepsze miejsca, powinni odnieść zwycięstwo.
Postępuj zgodnie z poniższą instrukcją, aby przyznać graczom statystyki po ukończeniu wyścigu:
Aby to zrobić, dodaj nową funkcję
RecordPlayerFinish()do definicji klasyplayer_leaderboards_example. Ta funkcja przyjmuje jako parametr gracza, któremu chcesz przyznać statystyki.Verse# When a player finishes the race, award them points based on their placement, and award them a win if # their placement was better than the PlacementRequiredForWin. RecordPlayerFinish(Player:agent):void=W
RecordPlayerFinish()pobierz miejsce tego gracza, pobierając bieżącą wartośćCurrentFinishOrderw nowejinto nazwiePlayerFinishOrder. Następnie zastosuj przyrost doCurrentFinishOrder, aby następny gracz, który ukończy wyścig, nie ukończył go na tym samym miejscu.VerseRecordPlayerFinish(Player:agent):void= PlayerFinishOrder:int = CurrentFinishOrder set CurrentFinishOrder += 1Teraz czas na przyznanie statystyk. Aby określić, ile punktów przyznać temu graczowi, w wyrażeniu
ifprzeprowadź indeksację do tablicyPointsPerPlace, używającPlayerFinishOrder. Następnie wywołaj funkcjęAddPoints(), aby przyznać graczowi taką liczbę punktów.Verseset CurrentFinishOrder += 1 if: PointsToAward := PointsPerPlace[PlayerFinishOrder] then: AddPoints(Player, PointsToAward)Jeśli gracz zajął wystarczająco wysokie miejsce, aby wygrać, musisz odnotować wygraną w jego tabeli statystyk. W kolejnym wyrażeniu
ifsprawdź, czyPlayerFinishOrderbyło mniejsze niżPlacementRequiredToWin. Jeśli tak, wywołajAddWin(), przekazując gracza i wygraną, aby mu ją przyznać. Gotowa funkcjaRecordPlayerFinish()powinna wyglądać następująco:Verse# When a player finishes the race, award them points based on their placement, and award them a win if # their placement was better than the PlacementRequiredForWin. RecordPlayerFinish(Player:agent):void= PlayerFinishOrder:int = CurrentFinishOrder set CurrentFinishOrder += 1 if: PointsToAward := PointsPerPlace[PlayerFinishOrder] then: AddPoints(Player, PointsToAward)
Oczekiwanie na zakończenie wyścigu przez graczy
Teraz, gdy masz już gotowe rejestrowanie statystyk, musisz wiedzieć, kiedy gracz ukończy wyścig, aby zaktualizować jego statystyki. W tym celu będziesz nasłuchiwać komunikatów menadżera wyścigu RaceCompletedEvent(). To zdarzenie jest uruchamiane za każdym razem, gdy którykolwiek z graczy ukończy wyścig, więc musisz stale nasłuchiwać go w funkcji asynchronicznej.
Dodaj nową funkcję
WaitForPlayerToFinishRace()do definicji klasyplayer_leaderboards_example. Ta funkcja pobiera gracza i czeka, aż ten gracz ukończy wyścig.Verse# When a player finishes the race, record a finish in their stats table. WaitForPlayerToFinishRace(Player:agent)<suspends>:void=W
WaitForPlayerToFinishRace(), w wyrażeniuracerozpocznij dwie pętle. Pierwsza z nich będzie czekać, aż gracz ukończy wyścig, a druga zajmie się tym, co się wydarzy, jeśli gracz opuści sesję przed ukończeniem wyścigu. Jeśli gracz opuści grę, nie chcesz, aby pętla działała w nieskończoność, więc potrzebujesz sposobu na przerwanie jej w takiej sytuacji.Verse# When a player finishes the race, record a finish in their stats table. WaitForPlayerToFinishRace(Player:agent)<suspends>:void= race: # Waiting for this player to finish the race and then record the finish. loop: # Waiting for this player to leave the game. loop:W pierwszej pętli oczekuj na
RaceManager.RaceCompletedEventi zapisz wynik w zmiennej o nazwieFinishingPlayer. Zdarzenie to jest uruchamiane za każdym razem, gdy dowolny gracz ukończy wyścig, dlatego musisz się upewnić, że zapisany gracz jest tym, którego monitorujesz. PorównajFinishingPlayerz graczem, którego monitoruje ta pętla. Jeśli oba elementy są równe, przekaż gracza doRecordPlayerFinish()i przerwij pętlę.Verse# Waiting for this player to finish the race and then record the finish. loop: FinishingPlayer := RaceManager.RaceCompletedEvent.Await() if: FinishingPlayer = Player then: RecordPlayerFinish(Player) breakW drugiej pętli zaczekaj na zdarzenie przestrzeni gry
PlayerRemovedEvent(). Tak jak poprzednio, pobierz gracza, który właśnie opuścił grę, i zapisz go w zmiennejLeavingPlayer. Jeśli gracz, który właśnie opuścił grę, jest graczem, na którego czeka ta pętla, przerwij ją. Gotowa funkcjaWaitForPlayerToFinishRace()powinna wyglądać następująco:Verse# When a player finishes the race, record a finish in their stats table. WaitForPlayerToFinishRace(Player:agent)<suspends>:void= race: # Waiting for this player to finish the race and then record the finish. loop: FinishingPlayer := RaceManager.RaceCompletedEvent.Await() if: FinishingPlayer = Player then: RecordPlayerFinish(Player)
Łączenie wszystkiego razem
Po skonfigurowaniu funkcji nadszedł czas, aby połączyć je z urządzeniami i rozpocząć wyścig!
Postępuj zgodnie z poniższą instrukcją, aby połączyć logikę z urządzeniami:
W
OnBegin()pobierz wszystkich graczy w przestrzeni gry za pomocąGetPlayers(). Przekaż tę tablicę doInitializeAllPlayerStats(), aby skonfigurowaćplayer_stats_tablesdla każdego z nich.Verse# Runs when the device is started in a running game OnBegin<override>()<suspends>:void= # Get the players in the current race and create a player_stat_table # for each of them. Players := GetPlayspace().GetPlayers() InitializeAllPlayerStats(Players)Wywołaj
UpdateStatsBillboards(), przekazując tablicePlayersiLeaderboards, aby zaktualizować billboardy w poziomie o aktualne dane każdego gracza. Następnie wywołajUpdatePlayerReferences(), aby zaktualizować odwołania do graczy w poziomie. Na koniec w wyrażeniuforzespawnuj funkcjęWaitForPlayerToFinishRace()dla każdego gracza. Gotowa funkcjaOnBegin()powinna wyglądać następująco:Verse# Runs when the device is started in a running game OnBegin<override>()<suspends>:void= # Get the players in the current race and create a player_stat_table # for each of them. Players := GetPlayspace().GetPlayers() InitializeAllPlayerStats(Players) UpdateStatsBillboards(Players, Leaderboards) UpdatePlayerReferences(Players, PlayerReferences) # Wait for all players to finish the race.Zapisz kod i go skompiluj.
Przeciągnij urządzenie player_leaderboards_example do swojego poziomu. Przypisz odwołania do graczy do tablicy PlayerReferences, zwracając uwagę na kolejność. Urządzenie w pierwszym indeksie powinno odpowiadać odwołaniu do gracza dla najlepszego gracza, drugi indeks powinien być powiązany z drugim z kolei najlepszym graczem itd. Zrób to samo z rankingami, upewniając się, że są one zsynchronizowane z urządzeniami odwołań do graczy. Nie zapomnij również przypisać swojego urządzenia menedżera wyścigu!
Testowanie persystentnych tablic rankingowych
Możesz przetestować trwałe dane w sesji edycji, ale dane te zostaną zresetowane po wyjściu i ponownym uruchomieniu sesji. Aby dane były zachowywane w różnych sesjach, musisz uruchomić sesję testową i zmienić określone ustawienia w Ustawieniach wyspy. Aby uzyskać informacje na temat konfigurowania wyspy w celu testowania persystentnych danych zarówno w sesjach edycji, jak i testów gry, zapoznaj się z artykułem Testowanie z persystencją danych i zmień niektóre ustawienia wyspy. Aby uzyskać informacje na temat konfigurowania wyspy w celu testowania persystentnych danych zarówno w sesjach edycji, jak i testów gry, zapoznaj się z artykułem Testowanie z persystencją danych.
Po skonfigurowaniu sesji, podczas testowania twojego poziomu w grze, gracze kończący wyścig powinni otrzymywać punkty w zależności od zajętego miejsca. Powinni oni zdobyć zwycięstwo, jeśli zajmą wystarczająco wysokie miejsce, a statystyki te powinny być zachowywane przy kolejnych sesjach gry. Gracze i ich statystyki powinny być posortowane, a gracz z największą liczbą punktów powinien znajdować się na pierwszym miejscu.
Praca własna
Dzięki tej instrukcji wiesz już, jak stworzyć tablice rankingowe, które wyświetlają trwałe statystyki graczy w poziomie. Wiesz także, jak sortować i aktualizować tablice rankingowe, aby każdy wiedział, kto jest najlepszym graczem. Spróbuj dostosować ten samouczek do własnych przygód i pochwal się najlepszymi graczami!
Complete Code
player_stats_table.verse
# This file defines a player_stats_table, a collection of persistable player statistics.
# It also contains functions to compare stats tables by each of the stats to order players
# when sorting.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Structure for passing a player and their stats as arguments.
player_and_stats<public> := struct:
player_leaderboards.verse
# This file contains the code that updates the billboards, player references, and UI on the island
# to display a player's stats from their player stats table. It also handles adding wins and points to a
# player's stats table.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation}
# The message to display on the stats billboard.
StatsMessage<localizes>(CurrentPlayer:message, Points:message, Wins:message):message=
"{CurrentPlayer}:\n{Points}\n{Wins}"
player_stats_manager.verse
# This file handles the code for initializing, updating, and returning player_stats_tables
# for each player. It also defines an abstract stat_type class to use for updating stats, and the
# StatType module to use when displaying stats.
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Return the player_stats_table for the provided Agent.
GetPlayerStats<public>(Agent:agent)<decides><transacts>:player_stats_table=
player_leaderboards_example.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
using { PlayerLeaderboard }
# See https://dev.epicgames.com/documentation/en-us/uefn/create-your-own-device-in-verse for how to create a verse device.
# A Verse-authored creative device that can be placed in a level
player_leaderboards_example := class(creative_device):
# Visual representations of each player.