このチュートリアルは 持続的なプレイヤー統計情報 のコンセプトに基づいています。まずはそちらをご確認ください。
ランキングは競争型ゲームに不可欠なものであり、プレイヤーは保有するスキルを示して有名になることができます。 プレイヤーが成長を実感できるだけでなく、ランキングのトップを目指してもう一度プレイしたくなります。
Verse Persistence は、こうしたランキングを作成し、体験に競争力を付加するうえで役立つツールを提供します。 持続的なプレイヤー統計情報のチュートリアルでは、プレイセッション間の持続データを追跡する方法と、さまざまなイベントに基づいてそのデータを変更、更新する方法を確認してきました。 次は、こうした知識を応用して完全なローカルランキングを作成し、プレイヤー統計データをソートして、レースゲームで活用する方法を学習します。
使用する Verse 言語機能
クラス:この例では、プレイヤー単位で統計データのグループを追跡する、永続可能な Verse クラスを作成します。
コンストラクタ:コンストラクタは、関連付けられているクラスのインスタンスを作成する特別な関数である。
weak_map:weak_map は、反復処理できない単純なマップです。 Verse の持続データは weak_map に格納する必要があります。
レベルを設定する
この例では、次の小道具と仕掛けを使用します。
ビルボードの仕掛け x 3:各プレイヤーのライフタイム統計データが表示されます。ライフタイム ポイントに基づいてソートし、ロビー内のベスト プレイヤーを表示することができます。
プレイヤー参照の仕掛け x 3:ビルボードと組み合わせて、プレイヤー参照がトップパフォーマーの名前に顔を付け、他のプレイヤーがゲーム中誰に味方すべきか把握できるようにします。
チェックポイントの仕掛け x 3:プレイヤーがレースを完走するために通過するチェックポイントです。
レース マネージャーの仕掛け x 1:プレイヤーがレースを開始および終了したときに追跡し、最終順位に基づいてポイントを付与します。
ピックアップ トラック スポナーの仕掛け x 1:レース中に使用する乗り物がスポーンされますが、体験に合わせて任意の乗り物に変更できます。
レベルを設定するには、次の手順を実行します。
ビルボードとプレイヤー参照
プレイヤー統計データを表示するには、ビルボードとプレイヤー参照を組み合わせて使用します。 各ビルボードにはプレイヤーのライフタイム統計データが表示され、プレイヤー参照にはそのプレイヤーのビジュアル イメージが表示されます。 これらの要素を追加するには、次の手順を実行します。
3 つの プレイヤー参照 の仕掛けをレベルに追加し、隣り合わせで配置します。
各プレイヤー参照について、アウトライナー で選択します。 ユーザー オプション の下にある [Details] パネルで、ロビーで 1 番目、2 番目、3 番目に優れたプレイヤーを表す色に カスタム カラー を設定します。 この例では、そうした色にゴールド、シルバー、ブロンズを使用しています。
3 つの ビルボード の仕掛けをレベルに追加し、1 つを各プレイヤー参照の前に置きます。 ゲームが始まると、Verse で各プレイヤーの統計データを使用して情報を更新します。
チェックポイント、ピックアップ トラック、レース マネージャー
これはレースであるため、争うものが必要となります。 また、通過するチェックポイントと、ゲーム中にレースを誘導するレース マネージャーも必要となります。 これらの要素を追加するには、次の手順を実行します。
3 つの レース チェックポイント の仕掛けをレベルに追加します。 プレイヤーが通過する順番に仕掛けを配置します。 アウトライナー の各チェックポイントで、チェックポイント番号 とプレイヤーがチェックポイントを通過する順番が一致していることを確認します。
1 つの レース マネージャー の仕掛けをレベルに追加します。 これによってレースの走行を管理し、プレイヤーをチェックポイントに誘導します。 後でこの仕掛けから
RaceCompletedEvent()をリッスンし、プレイヤーがレースを終えた時間を把握します。1 つの ピックアップ トラック スポナー の仕掛けをレベルに追加します。 乗り物はオプションですが、このガイドでは、Speedway Template に合わせてピックアップ トラックを使用しており、プレイヤーに何らかの乗り物を提供します。
統計データテーブルを変更する
この例では、持続的なプレイヤー統計データ の「player_stats_table」ファイル修正版を使用しています。 これは、その例のファイルとよく似たものに見えますが、実装の変更につながる重要な違いがあります。
以下の手順に従って、プレイヤー統計データテーブルを作成します。
player_stats_tableクラス内:Lossesの統計データを削除します。Scoreの統計データをPointsに変更します。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.
ファイル内の
MakePlayerStatsTable()コンストラクタ関数を修正し、更新済みの統計データを反映させます。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.Wins新しい構造体の
player_and_statsを「player_stats_table.verse」ファイルに追加します。 この構造体には、プレイヤーとそのplayer_stats_tableクラスへの参照が含まれており、何度も取得することなく、関数で両方のデータを使用できます。 完成したplayer_and_stats構造体は次のようになります。Verse# Structure for passing a player and their stats as arguments. player_and_stats<public> := struct: Player<public>:player StatsTable<public>:player_stats_table
統計データを管理する
持続的なプレイヤー統計情報 の作業と同様に、マネージャー ファイルを使用して、プレイヤーの統計データ変更の管理と記録を処理します。
以下の手順に従って、修正済みの「player_stats_manager」ファイルをビルドします。
InitializeAllPlayers()およびInitializePlayer()の関数シグネチャをInitializeAllPlayerStats()およびInitializePlayerStat()に変更します。GetPlayerStat()関数との関係をより的確に反映した名前となります。 更新済みの関数は次のようになります。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{}AddScore()の関数シグネチャをAddPoints()に変更します。 次に、player_stats_tableにその値が含まれなくなったため、AddLosses()関数を削除します。 完成した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.verse」という名前の新しい Verse ファイルを作成します。 このファイルには、レベル内ランキングの更新に共通する関数が格納されます。
ビルボードのテキストについては、引数を渡すことができるメッセージを使用します。
CurrentPlayer、Points、Wins、すべての型のメッセージを受け取り、組み合わせたテキストをメッセージとして返す、StatsMessageという名前の新しいメッセージを作成します。Verse# The message to display on the stats billboard. StatsMessage<localizes>(CurrentPlayer:message, Points:message, Wins:message):message= "{CurrentPlayer}:\n{Points}\n{Wins}"さらに 3 つの
メッセージ変数を追加します (StatsMessageへの各インプットに 1 つ)。PlayerTextメッセージはAgent、PointsTextメッセージはそのエージェントのポイント、WinsTextメッセージはそのエージェントの勝利を受け取ります。StatsMessageはこれらすべてからのメッセージを作成し、レベル内のデータを明確に表示します。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"ビルボードを更新するには、プレイヤーの持続的な統計データのチュートリアルから
UpdateStatsBillboard()関数を呼び出します。 この関数は、Verse の仕掛けとは異なるファイルで定義されているため、追加の引数としてStatsBillboardを追加し、更新するビルボードを指定する必要があります。Verse# Updates the given billboard device to display the stats of the given player. UpdateStatsBillboard<public>(Player:agent, StatsBillboard:billboard_device):void=最初に、
GetPlayerStats[]を使用して引数として渡されるプレイヤーの統計データを取得します。 別のクラスではなくなるため、player_stats_managerへの参照は不要です。 次に、プレイヤーと、そのCurrentPlayerStatsのPointsとWinsを使用して、新しいStatsMessageを作成します。 最後に、StatsBillboardのSetText()を呼び出し、レベル内のビルボード テキストを更新します。 完成したUpdateStatsBillboard()関数は次のようになります。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)
ベスト プレイヤーをソートして表示する
次のステップに進む前に、これらのビルボードをどのようにソートするか検討しておくことが重要です。 最も多くのポイントを獲得したプレイヤーと、最も勝利を収めたプレイヤーのどちらをトップにしますか。 異なる統計データでソートする場合はどうしますか。 こうした問題に対処する方法が必要となりますが、その解決策が ソート アルゴリズム です。 ソート アルゴリズムと比較関数を使用することで、ソート条件を指定できます。 次に、ビルボードとプレイヤー参照をソートして、体験内にトップ プレイヤーを表示できます。 この例では マージ ソート アルゴリズムを使用していますが、独自のアルゴリズムを自由に実装できます。
以下の手順に従って比較とソートをビルボードに追加し、レベル内の仕掛けの更新を完了します。
player_stats_tableファイルに戻り、各統計データの比較関数を定義します。 各関数はLeftおよびRight のplayer_and_stats構造体を受け取り、特定の統計データに基づいてそれらを比較します。<decides><transacts>モディファイヤが含まれるため、比較が失敗すると関数も失敗します。 たとえば、LeftがRightよりも少ない場合です。MorePointsComparison()という名前の新しい関数を player_stats_table.verseファイルに追加します。 この関数は、Left.PointsがRight.Pointsよりも多いかどうかを確認し、少ない場合は失敗します。 成功した場合は、Left` を返します。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 Leftこの関数を 3 回コピーします (1 つは少ないポイント数の比較用、2 つは勝利の比較用)。 比較関数は次のようになります。
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 Leftマージ ソート アルゴリズムを追加します。 これを別のファイルまたはモジュールに配置し、指定されたテスト ファイルでアルゴリズムをテストできます。
player_leaderboardsに戻り、「UpdateStatsBillboards()」という新しい関数を追加します。 この関数は、さまざまなエージェントとさまざまなビルボードを受け取り、それらをソートして、UpdateStatsBillboard()を呼び出し、レベル内の各ビルボードを更新します。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=UpdateStatsBillboards()で、PlayerAndStatsArrayと呼ばれる、新しい配列変数のplayer_and_statsを初期化します。for式の結果と等しくなるように設定します。 そのfor式では、エージェントごとに、そのエージェントのプレイヤーを受け取り、GetPlayerStats[]を使用してそのplayer_stats_tableを取得します。 次に、プレイヤーとその統計データ テーブルから作成されたplayer_and_stats構造体を返します。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 := PlayerStatsPlayerAndStatsArrayをソートするには、MergeSort()を呼び出した結果への新しい変数「SortedPlayersAndStats」を初期化し、配列とMorePointsComparisonを渡します。for式でソートした後、SortedPlayerAndStatsで各要素をイテレートし、変数「PlayerIndex」に要素インデックスを格納します。PlayerIndexを使用してStatsBillboards配列にインデックスを作成します。次に、UpdateStatsBillboardを呼び出して、更新するプレイヤーとビルボードを渡します。 完成したUpdateStatsBillboard()関数は次のようになります。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:プレイヤー参照を更新するには、
UpdatePlayerReferences()という名前の非常に類似した関数を使用します。 この関数は、ビルボードの代わりにplayer_reference_deviceの配列を受け取ります。また、最後にUpdateStatsBillboard()を呼び出すのではなく、各プレイヤーのプレイヤー参照の仕掛けでRegister()を呼び出します。UpdateStatsBillboard()のコードを、上記の変更点を含む新しい関数「UpdatePlayerReferences()」にコピーします。 完成したUpdatePlayerReferences()関数は次のようになります。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:
レベル内のプレイヤー ランキング
すべての設定が完了したら、プレイヤーを表示しましょう。 プレイヤーがボタンを操作したときにポイントを付与する仕掛けを作成し、ベスト プレイヤーが前に出るようにプレイヤー参照とビルボードをソートします。 以下の手順に従って、レベル内のランキングをテストする Verse の仕掛けを作成します。
player_leaderboards_example という名前の新しい Verse の仕掛けを作成します。 手順については、「Verse を使用して独自の仕掛けを作成する」を参照してください。
player_leaderboards_example class定義の先頭に、以下のフィールドを追加します。PlayerReferencesという名前のプレイヤー参照の仕掛けの編集可能な配列。 これらは、レースにおける各プレイヤーのビジュアル イメージとなります。Verse# Visual representations of each player. @editable PlayerReferences:[]player_reference_device = array{}Leaderboardsという名前のビルボードの仕掛けの編集可能な配列。 レベル内のビルボードに各プレイヤーの統計データを表示します。Verse# Billboards that display each player's stats. @editable Leaderboards:[]billboard_device = array{}RaceManagerという名前の編集可能なレース マネージャーの仕掛け。 プレイヤーがレースを終えた時間を把握するため、レース マネージャーのイベントをサブスクライブします。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{}PlacementRequiredForWinという名前の編集可能な整数。 これは、プレイヤーが勝利するために獲得しなければならない順位です。Verse# The placement of a player must be at or below to award a win. @editable PlacementRequiredForWin:int = 1PointsPerPlaceという名前の編集可能な整数の配列。 各プレイヤーが順位に基づいて獲得したポイント数です。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}CurrentFinishOrderという名前の整数変数。 これは、最近レースを終えたプレイヤーの順位です。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
順位に基づいた統計データを付与する
プレイヤーがレースを終えたとき、その順位に基づいてプレイヤーの統計データを更新することができます。 良い順位のプレイヤーにより多くのポイントを付与し、最も良い順位のプレイヤーに勝利を付与します。
次の手順に従って、プレイヤーがレースを終えたときに統計データを付与します。
これを処理するため、新しい関数「
RecordPlayerFinish()」をplayer_leaderboards_exampleクラス定義に追加します。 この関数は、プレイヤーをパラメータとして受け取り、統計データを付与します。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=RecordPlayerFinish()では、PlayerFinishOrderと呼ばれる新しい整数でCurrentFinishOrderの最新値を取得することで、このプレイヤーの順位を受け取ります。 次にレースを終えたプレイヤーが同じ順位とならないよう、CurrentFinishOrderを増やしていきます。VerseRecordPlayerFinish(Player:agent):void= PlayerFinishOrder:int = CurrentFinishOrder set CurrentFinishOrder += 1次はいよいよ、統計データの付与です。
if式で、このプレイヤーに付与するポイント数を確認するには、PlayerFinishOrderを使用してPointsPerPlace配列にインデックスを作成します。 次に、AddPoints()を呼び出し、そのプレイヤーにそのポイント数を付与します。Verseset CurrentFinishOrder += 1 if: PointsToAward := PointsPerPlace[PlayerFinishOrder] then: AddPoints(Player, PointsToAward)プレイヤーの順位が勝利の条件を満たしていれば、その統計データ テーブルに勝利を記録する必要があります。 別の
if式で、PlayerFinishOrderがPlacementRequiredToWinよりも良いことを確認します。 その場合、AddWin()を呼び出し、プレイヤーに勝利を付与します。 完成したRecordPlayerFinish()関数は次のようになります。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)
プレイヤーがレースを終えるまで待つ
これで統計データを記録する準備が整いました。次は、プレイヤーがレースを終えた時間を把握し、統計データを更新する必要があります。 そのために、レース マネージャーの RaceCompletedEvent() をリッスンします。 このイベントは、プレイヤーがレースを終えるたびに起動するため、非同期関数で継続的にリッスンする必要があります。
新しい関数「
WaitForPlayerToFinishRace()」をplayer_leaderboards_exampleクラス定義に追加します。 この関数はプレイヤーを受け取り、そのプレイヤーがレースを終えるまで待ちます。Verse# When a player finishes the race, record a finish in their stats table. WaitForPlayerToFinishRace(Player:agent)<suspends>:void=WaitForPlayerToFinishRace()では、レース式で、2 つのループを開始します。 最初のループは、プレイヤーがレースを終えるまで待ちます。次のループは、プレイヤーがレースを終える前にセッションから離脱した場合に発生した状況に対処します。 プレイヤーが離脱した場合、ループを永久に稼働させることを避けるため、そうした状況から抜け出す手段が必要となります。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:最初のループでは、
RaceManager.RaceCompletedEventを待ち、FinishingPlayerという名前の変数にその結果を格納します。 このイベントは、プレイヤーがレースを終えるたびに起動するため、格納したプレイヤーが監視していたプレイヤーであることを確認する必要があります。FinishingPlayerと、このループが監視しているプレイヤーを比較します。 両者が同一であれば、そのプレイヤーをRecordPlayerFinish()に渡して、ループから離脱します。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) break次のループでは、プレイ空間イベント「
PlayerRemovedEvent()」を待ちます。 先ほどと同じように、離脱直後のプレイヤーを受け取り、変数「LeavingPlayer」に格納します。 離脱したプレイヤーが、このループが待っているプレイヤーである場合は、ループから離脱します。 完成したWaitForPlayerToFinishRace()関数は次のようになります。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)
すべてをリンクする
関数の設定が完了したら、仕掛けに接続して、レースを始めましょう。
次の手順に従って、ロジックを仕掛けに接続します。
OnBegin()では、GetPlayers()を使用して、プレイ空間内のすべてのプレイヤーを取得します。 この配列をInitializeAllPlayerStats()に渡して、各プレイヤーのplayer_stats_tablesを設定します。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()を呼び出し、プレイヤーおよびランキング配列を渡して、各プレイヤーの最新データでレベル内ビルボードを更新します。次に、UpdatePlayerReferences()を呼び出し、プレイヤーに合わせてレベル内参照を更新します。 最後に、for式で、各プレイヤーのWaitForPlayerToFinishRace()関数をスポーンします。 完成したOnBegin()関数は次のようになります。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.コードを保存してコンパイルします。
player_leaderboards_example の仕掛けをレベル内にドラッグします。 PlayerReferences 配列にプレイヤー参照を割り当て、順位を記録します。 第 1 インデックスの仕掛けは 1 位のプレイヤーのプレイヤー参照に対応し、第 2 インデックスは 2 位のプレイヤーに対応している必要があります (以下同じ)。 ランキングについても同様に対応し、プレイヤー参照の仕掛けとの整合性を確保します。 レース マネージャーの仕掛けにも忘れずに割り当てます。
永続可能ランキングをテストする
持続データを編集セッションでテストできますが、そのセッションを終了して再起動すると、そのデータはリセットされます。 セッションをまたいでデータを持続させるには、プレイテスト セッション を起動し、島設定 の特定の設定を変更する必要があります。 編集セッションとプレイテスト セッションの両方で持続データをテストできるように島を設定する方法については、「持続データを使用してテストする」を参照のうえ、島設定の一部の設定を変更してください。 編集セッションとプレイテスト セッションの両方で持続データをテストできるように島を設定する方法については、「持続データを使用してテストする」を参照してください。
セッションを設定後、レベルをプレイテストする場合、レースを終了するプレイヤーはその順位に基づいてポイントが与えられる必要があります。 上位のプレイヤーは勝利したものとされ、統計データはプレイ セッションをまたいで持続する必要があります。 プレイヤーとその統計データは、最もポイントが多いプレイヤーが 1 位に表示されるようにソートされる必要があります。
応用編
このガイドを完了し、レベル内での持続型のプレイヤー統計データを表示するランキングを作成する方法を習得しました。 また、ランキングをソートして更新し、ベストプレイヤーが誰なのか、誰もが分かるようにする方法も習得しました。 このチュートリアルを独自の体験に対応させ、最高の体験を披露しましょう。
完全なコード
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.