Wiele gier korzysta ze statystyk graczy, aby śledzić dane dotyczące ich doświadczeń w miarę upływu czasu. Takie statystyki jak najwyższy wynik, całkowita liczba zwycięstw, całkowity czas gry i zebrane przedmioty dają graczom poczucie dokonania postępu w grze i są świetnym sposobem na zachęcenie ich do ponownego zagrania.
Verse Persistence (Persystencja Verse) to potężne narzędzie umożliwiające dodawanie trwałych danych do skryptów Verse. Dane możliwe do utrwalenia są zapisywane osobno dla każdego gracza i każdej wyspy i pozostają takie same pomiędzy sesjami gry. Dane możliwe do utrwalenia pozwolą ci śledzić postępy gracza pomiędzy sesjami gry i otworzą przed tobą szereg wyjątkowych i interesujących możliwości rozgrywki, które dotąd nie były dostępne w UEFN.
Z tego samouczka dowiesz się, jak śledzić niestandardowe statystyki graczy w Verse i jak je skonfigurować w taki sposób, aby były możliwe do utrwalenia podczas wielu rund rozgrywki w twojej przygodzie. Po ukończeniu tego samouczka przeczytaj artykuł Tworzenie własnej tablicy rankingowej gry w Verse, aby dowiedzieć się, jak wykorzystać persystencję do tworzenia tablic rankingowych w grze!
Używane funkcje języka Verse
Klasa: W tym przykładzie tworzona jest klasa Verse, która zarządza pojedynczą statystyką, a także klasa persystentna, która śledzi grupę statystyk pojedynczego gracza.
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:
2 x urządzenie przycisku: Kiedy gracz wejdzie w interakcję z urządzeniem, doda punkt do swojego aktualnego wyniku. Za pomocą kolejnego urządzenia z przyciskami będziesz symulować zakończenie gry, dodając zwycięstwa lub porażki gracza w zależności od jego aktualnego wyniku.
1 x urządzenie billboardu: Często istotne jest, aby dane możliwe do persystencji były wyświetlane graczowi. Czasami wykonuje się to w celach testowych, a innym razem, aby zwiększyć zaangażowanie graczy lub pokazać im poczynione postępy. Chociaż wymagania dotyczące tego, kiedy i jakie dane wyświetlać, będą się różnić w zależności od przygody (gry), w tym przykładzie wyświetlone będą dane statystyczne dotyczące wyniku, najwyższego wyniku, liczby wygranych i przegranych na urządzeniu billboardu.
Śledzenie persystentnych statystyk gracza
Po pierwsze, istotne jest, aby określić, jakie statystyki chcesz śledzić dla każdego gracza. Na przykład, możesz chcieć śledzić wynik wszech czasów gracza, jego aktualną rangę lub najlepszy czas okrążenia. W tym przykładzie będziesz śledzić wyniki, zwycięstwa i porażki w tabeli wartości statystyk dla każdego gracza. Zrobisz to za pomocą nowej klasy player_stats_table, która będzie twoją główną klasą możliwą do utrwalenia.
Wykonaj poniższe kroki, aby utworzyć swoją klasę player_stats_table.
Przy użyciu Eksploratora Verse utwórz nowy plik Verse o nazwie
player_stats_table.verse.W swoim nowym pliku Verse utwórz nową klasę o nazwie
player_stats_table. Dodaj modyfikatory<persistable>i<final>do swojej klasy. Modyfikator<persistable>pozwala na persystencję danych w klasie i wymaga modyfikatora<final>, ponieważ nie można zastąpić ani „podklasować” danych możliwych do utrwalenia.Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Tracks different persistable stats for each player. player_stats_table := class<final><persistable>:Do tabeli
player_stats_tabledodaj trzy wartościinto nazwachScore,WinsiLosses. Śledzą one odpowiednio: najlepszy wynik życiowy, liczbę zwycięstw i liczbę porażek każdego gracza. Ponadto możesz dodaćinto nazwieVersion, aby śledzić aktualną wersję swojejplayer_stats_table.Verse# Tracks different persistable stats for each player. player_stats_table := class<final><persistable>: # The version of the current stats table. Version<public>:int = 0 # The score of a player. Score<public>:int = 0 # The number of wins for a player. Wins<public>:int = 0Aby utworzyć instancję klasy
player_stats_table, należy użyć funkcji<constructor>. Ten konstruktor jest wymagany, ponieważ zasady persystencji Verse nie pozwalają na persystencję klas zawierających pola zmiennych. Użycie konstruktora umożliwi aktualizację persystentnych wartości klasy poprzez utworzenie kopii istniejącej persystentnej statystyki, która jest zmienną, zaktualizowanie kopii, a następnie zastąpienie oryginalnej instancji klasy zmienionymi wartościami. Dodaj nową funkcję konstruktoraMakePlayerStatsTable()do pliku. Ten konstruktor przyjmie początkową (poprzednią) instancję klasyplayer_stats_tablei utworzy nową na podstawie podanych wartości oryginalnych.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 Score := OldTable.Score Wins := OldTable.Wins Losses := OldTable.LossesAby śledzić wszystkie swoje
player_stats_tables, użyj trwałejweak_mapinstancjiplayerdoplayer_stats_table. Dodaj tę słabą mapę do swojego pliku.Verse# Maps players to a table of their player stats. var PlayerStatsMap:weak_map(player, player_stats_table) = map{}Ukończona klasa
player_stats_tablepowinna wyglądać następująco:Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Tracks different persistable stats for each player. player_stats_table := class<final><persistable>: # The version of the current stats table. Version<public>:int = 0 # The score of a player.
Zarządzanie statystykami gracza dla wszystkich graczy
Twoja klasa player_stats_table umożliwia śledzenie statystyk pojedynczego gracza, ale nie masz jeszcze możliwości, aby nimi zarządzać. Musisz zaktualizować tabele statystyk dla każdego gracza za każdym razem, gdy zdobędzie on jakiś punkt. W zależności od konfiguracji twojej gry może to być wielu graczy na raz.
Aby to rozwiązać, użyjesz innej klasy do zarządzania statystykami wszystkich graczy i będziesz rejestrować zmiany statystyk za każdym razem, gdy gracz odniesie zwycięstwo, dozna porażki lub zdobędzie punkty. Wykonaj poniższe kroki, aby skonfigurować klasę menedżera.
Przy użyciu Eksploratora Verse utwórz nowy plik Verse o nazwie
player_stats_manager. W tym pliku utwórz nową klasęplayer_stats_manager.Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Manages and updates player_stat_tables for each player. player_stats_manager := class():Twój
player_stats_managermusi wykonywać kilka rzeczy. Musi utworzyć tabelęplayer_stats_tabledla gracza, aktualizowaćScore,WinsiLossesdla każdego gracza i zwrócić tabelęplayer_stats_tabledla gracza. Każda z powyższych będzie obsługiwana w osobnych funkcjach. Dodaj nową funkcjęInitializePlayer()do definicji klasyplayer_stats_manager. Funkcja ta zainicjuje statystyki dla danego gracza.Verse# Initialize stats for the given player. InitializePlayer(Player:player):void=W
InitializePlayer()sprawdź, czy dany gracz już istnieje wPlayerStatsMap. Jeśli nie, ustaw wartość tego gracza na mapie na nowąplayer_stats_table. Gotowa funkcjaInitializePlayer()powinna wyglądać następująco:Verse# Initialize stats for the given player. InitializePlayer(Player:player):void= if: not PlayerStatsMap[Player] set PlayerStatsMap[Player] = player_stats_table{} else: Print("Unable to initialize player stats")Dodaj nową funkcję
InitializeAllPlayers()do definicji klasyplayer_stats_manager. Funkcja ta przyjmuje tablicę graczy i wywołujeInitializePlayer()dla każdego z nich. Gotowa funkcjaInitializeAllPlayers()powinna wyglądać następująco:Verse# Initialize stats for all current players. InitializeAllPlayers(Players:[]player):void = for (Player : Players): InitializePlayer(Player)Aby zwrócić statystyki konkretnego gracza, potrzebna jest funkcja, która zwraca
player_stats_tabletego gracza. Dodaj nową funkcjęGetPlayerStats()do definicji klasyplayer_stats_manager, która przyjmuje agenta. Dodaj modyfikator<decides><transacts>, aby umożliwić tej funkcji niepowodzenie i cofnięcie w przypadku, gdy tabela statystyk gracza nie istnieje. WGetPlayerStats()utwórz nowePlayerStatszmiennejplayer_stats_table.Verse# Return the player_stats_table for the provided Agent. GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{}W wyrażeniu
ifrzutujagentaprzekazanego do tej funkcji dogracza, a następnie pobierzplayer_stats_tabledla tego gracza zPlayerStatsMap. Następnie ustawPlayerStatsna tę tabelę, wywołując funkcjęMakePlayerStatsTable(). Na końcu zwróćPlayerStats. Gotowa funkcjaGetPlayerStats()powinna wyglądać następująco:Verse# Return the player_stats_table for the provided Agent. GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{} if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] set PlayerStats = MakePlayerStatsTable(PlayerStatsTable) PlayerStatsAby zaktualizować statystyki wyników, zwycięstw i porażek, należy utworzyć funkcje dla każdej z nich. Dodaj nową funkcję
AddScore()do plikuplayer_stats_manager. Funkcja ta pobiera agenta w celu przyznania wyniku, po czym przyznaje mu liczbę punktów wyrażoną wartościąint.Verse# Adds to the given Agent's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore<public>(Agent:agent, NewScore:int):void=Dane są aktualizowane poprzez weryfikację, czy gracz ma prawidłowe dane w możliwym do utrwalenia obiekcie
weak_map, a następnie poprzez zastąpienie tych danych zaktualizowaną kopią klasy. Aby obsłużyć to dla wyniku, pobierz wynik gracza zPlayerStatsTable, a następnie ustaw tabelę wPlayerStatsMapna wynik skonstruowania nowejplayer_stats_tableza pomocąMakePlayerStatsTable(), przekazując aktualny wynik wraz z nowym wynikiem. Kiedy pracujesz z klasą, która zawiera kilka pól, konstruktor klasy pozwala na łatwą aktualizację pojedynczego pola bez jawnego kopiowania wszystkich pól za każdym razem, gdy chcesz dokonać aktualizacji. Otrzymana funkcjaAddScore()powinna wyglądać następująco:Verse# Adds to the given Agent's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore<public>(Agent:agent, NewScore:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentScore := PlayerStatsTable.Score set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Score := CurrentScore + NewScorePowtórz ten proces dla wygranych i przegranych, dodając
NewWinsiNewLossesdo wygranych lub przegranych gracza odpowiednio podczas wywoływaniaMakePlayerStatsTable().Verse# Adds to the given Agent's wins and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddWin<public>(Agent:agent, NewWins:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentWins := PlayerStatsTable.Wins set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Wins := CurrentWins + NewWinsGotowy plik
player_stats_managerpowinien wyglądać jak poniżej.Verseusing { /Fortnite.com/Devices } using { /Verse.org/Simulation } using { /UnrealEngine.com/Temporary/Diagnostics } # Manages and updates player_stat_tables for each player. player_stats_manager := class(): # Return the player_stats_table for the provided Agent. GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{}
Testowanie persystencji z urządzeniami
Po skonfigurowaniu klas możliwych do persystencji, czas przetestować je na swoim poziomie.
Utwórz nowe urządzenie Verse o nazwie player_stats_example. Aby uzyskać informacje na ten temat, patrz: Tworzenie własnego urządzenia przy użyciu Verse.
Na początku definicji klasy
player_stats_exampledodaj następujące pola:Edytowalny
button_deviceo nazwieScorePointsButton. Ten przycisk dodaje do wyniku gracza za każdym razem, gdy zostanie aktywowany.Verse# Adds to the activating player's score. @editable ScorePointsButton:button_device = button_device{}Edytowalne
billboard_deviceo nazwieStatsBillboard. Wyświetli się wynik gracza, jego najlepszy wynik, liczba zwycięstw i porażek.Verse# Displays the player's Score, High Score, Wins, and Losses @editable StatsBillboard:billboard_device = billboard_device{}Edytowalne button_device o nazwie
CheckWinButton. Ten przycisk resetuje wynik każdego gracza i przyznaje mu zwycięstwo lub porażkę w zależności od uzyskanego wyniku.Verse# Resets the player's score and award them a win or a loss # depending if their current score is greater than WinScore. @editable CheckWinButton:button_device = button_device{}Edytowalna wartość
into nazwieWinScore. Jest to wynik, jaki gracze muszą osiągnąć, aby uzyskać zwycięstwo po aktywacji przyciskuCheckWinButton.Verse# The score players need to reach to be awarded a win after # the CheckWinButton is activated. @editable WinScore:int = 10Edytowalna wartość
into nazwieAwardScore. Jest to wynik przyznawany graczom za interakcję z przyciskiem.Verse# The amount of score to award per button press. @editable AwardScore:int = 1player_stats_managero nazwiePlayerStatsManager. Ta funkcja umożliwia zarządzanie statystykami wszystkich graczy i ich aktualizowanie.Verse# Manages and updates stats for each player. PlayerStatsManager:player_stats_manager = player_stats_manager{}Wiadomość o nazwie StatsMessage przyjmująca od agenta cztery liczby całkowite: Score, MaxScore, Wins i Losses. Za pomocą tego komunikatu możesz wyświetlić statystyki gracza na billboardzie.
Verse# Displays a player's stats on a billboard. StatsMessage<localizes>(Player:agent, Score:int, Wins:int, Losses:int):message = "{Player}, Stats:\n Score: {Score}\n Wins: {Wins}\n Losses: {Losses}"
Skompiluj swój kod, a następnie przeciągnij urządzenie utworzone w Verse na wyspę. Aby uzyskać informacje na ten temat, patrz: Dodawanie urządzenia Verse do poziomu.
W panelu szczegółów swojego urządzenia przypisz urządzenie przycisku na swoim poziomie do ScorePointsButton, a urządzenie billboardu do StatsBillboard.
Aby wyświetlić statystyki danego gracza na StatsBillboard, dodaj nową funkcję
UpdateStatsBillboard()do definicji klasyplayer_stats_example. Funkcja ta pobiera agenta, którego statystyki będą wyświetlane.Verse# Retrieves the stats of the given player and displays their stats # on the StatsBillboard. UpdateStatsBillboard(Agent:agent):void=W
UpdateStatsBillboard()pobierz aktualne statystyki danego agenta, wywołując funkcjęGetPlayerStats[]menedżera statystyk. Następnie wywołajSetText()na StatsBillboard, przekazując nowyStatsMessage(). Aby utworzyć ten komunikatStatsMessage(), należy uzyskać wynik, zwycięstwa i porażki agenta, uzyskując do nich dostęp z poziomu bieżących statystyk agenta. Gotowa funkcjaUpdateStatsBillboard()powinna wyglądać następująco:Verse# Retrieves the stats of the given player and displays their stats # on the StatsBillboard. UpdateStatsBillboard(Agent:agent):void= if: # Get the current stats of the given agent. CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent] then: StatsBillboard.SetText( StatsMessage( Player := Agent,Dodaj nową funkcję
AddScore()do definicji klasyplayer_stats_example. Ta funkcja przyjmuje agenta i dodaje do jego wyniku, gdy tylko aktywowany zostanie przycisk ScorePointsButton.Verse# Adds to the given player's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore(Agent:agent):void=W
AddScore()pobierz aktualne statystyki danego agenta, a także jego aktualny wynik. Następnie wywołajAddScore()zPlayerStatsManager, przekazując agenta orazAwardScore, aby przyznać mu nowy wynik. Na koniec wywołajUpdateStatsBillboard(), przekazując podanego agenta. Otrzymana funkcjaAddScore()powinna wyglądać następująco:Verse# Adds to the given player's score and updates both their stats table # in PlayerStatsManager and the billboard in the level. AddScore(Agent:agent):void= if: CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent] CurrentScore := CurrentPlayerStats.Score then: Print("Current Score is: {CurrentScore}") PlayerStatsManager.AddScore(Agent, AwardScore) UpdateStatsBillboard(Agent)Aby przyznawać graczowi zwycięstwo lub porażkę po aktywowaniu przycisku CheckWin, należy dodać nową funkcję
CheckWin()do definicji klasy player_stats_manager.Verse# Awards a player a win or a loss when they interact # with the CheckWinButton. CheckWin(Agent:agent):void=W pierwszej kolejności zdefiniuj zmienną
CurrentScore, aby śledziła aktualny wynik agenta. Następnie, podobnie jak w przypadku funkcjiAddScore(), pobierz aktualny wynik z tabeli statystyk gracza.Verse# Awards a player a win or a loss when they interact # with the CheckWinButton. CheckWin(Agent:agent):void= var CurrentScore:int = 0 if: PlayerStats := PlayerStatsManager.GetPlayerStats[Agent] set CurrentScore = PlayerStats.ScoreJeśli aktualny wynik agenta jest wyższy niż
WinScore, konieczne jest zapisanie zwycięstwa wPlayerStatsManager. W przeciwnym wypadku zapisywana jest porażka. Na koniec zresetuj wynik agenta, wywołującAddScore()z ujemnymCurrentScore, a następnie wyświetl statystyki agenta na billboardzie statystyk. Otrzymana funkcjaCheckWin()powinna wyglądać następująco:Verse# Awards a player a win or a loss when they interact # with the CheckWinButton. CheckWin(Agent:agent):void= var CurrentScore:int = 0 if: PlayerStats := PlayerStatsManager.GetPlayerStats[Agent] set CurrentScore = PlayerStats.Score then: Print("Current Score is: {CurrentScore}") if:W
OnBegin()zasubskrybujScorePointsButton.InteractedWithEventdoAddScore()iCheckWinButton.InteractedWithEventdoCheckWin(). Następnie pobierz tablice wszystkich graczy w grze, wywołującGetPlayers()i zainicjuj je wszystkie za pomocą funkcjiInitializeAllPlayers()menedżera statystyk.Verse# Runs when the device is started in a running game OnBegin<override>()<suspends>:void= # Register Button Events ScorePointsButton.InteractedWithEvent.Subscribe(AddScore) CheckWinButton.InteractedWithEvent.Subscribe(CheckWin) Players := GetPlayspace().GetPlayers() # Initialize player stats PlayerStatsManager.InitializeAllPlayers(Players)Zapisz kod i skompiluj go.
Testowanie persystencji na twoim poziomie
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. Informacje na temat konfigurowania wyspy w celu testowania danych możliwych do utrwalenia zarówno w sesjach edycji, jak i testów gry można znaleźć w artykule Testowanie z persystencją danych na stronie poświęconej danym możliwym do utrwalenia.
Po skonfigurowaniu sesji, gdy testujesz swój poziom, aktywowanie przycisku ScorePoints powinno podwyższyć wynik gracza i wyświetlić zaktualizowany wynik na billboardzie. Aktywowanie przycisku CheckWin powinno zwiększyć liczbę zwycięstw lub porażek gracza, w zależności od jego wyniku. Po powrocie do lobby i ponownym wejściu na wyspę statystyki gracza powinny zostać zachowane, a jego łączna liczba zwycięstw/porażek i najwyższy wynik powinny być wyświetlane na billboardzie po każdej aktualizacji.
Praca własna
Po ukończeniu tego przewodnika dowiedziałeś się, jak używać Verse do tworzenia danych możliwych do utrwalenia śledzonych dla każdego gracza, które będą zachowywane podczas kolejnych sesji gry. Teraz sprawdź, jak możesz dostosować persystencję, aby podnieść poziom swojego doświadczenia
Czy możesz stworzyć system plików zapisu, w którym będzie zapisywany ostatni punkt kontrolny, do którego dotarł gracz?
Co powiesz na system, który będzie zapamiętywać, z którymi postaciami gracz rozmawiał i jakie są jego obecne stosunki z nimi?
Co powiesz na system, który daje graczom tylko ograniczoną ilość czasu w trakcie sesji gry na osiągnięcie celów i resetuje postępy, jeśli nie uda im się tego wykonać?
Gotowy kod
Oto kompletny kod utworzony w tej sekcji samouczka.
player_stats_table.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Tracks different persistable stats for each player.
player_stats_table := class<final><persistable>:
# The version of the current stats table.
Version<public>:int = 0
# The score of a player.
player_stats_manager.verse
using { /Fortnite.com/Devices }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# Manages and updates player_stat_tables for each player.
player_stats_manager := class():
# Return the player_stats_table for the provided Agent.
GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table=
var PlayerStats:player_stats_table = player_stats_table{}
player_stats_example.verse
using { /Fortnite.com/Devices }
using { /Fortnite.com/Game }
using { /Verse.org/Simulation }
using { /UnrealEngine.com/Temporary/Diagnostics }
# A Verse-authored creative device that can be placed in a level
player_stats_example := class(creative_device):
# Adds to the activating player's score.
@editable