多くの体験では、プレイヤー統計データを使用してプレイヤーの体験データを時間経過とともに追跡しています。ハイスコア、勝利した総ゲーム数、合計プレイ時間、回収したアイテム数などの統計データによって、進行状況の感覚がプレイヤーに与えられ、プレイヤーがその体験に戻るように仕向けるための素晴らしい方法です。
Verse の持続機能は、Verse スクリプトに持続可能データを付加できるようにする強力なツールです。持続可能データはプレイヤーごとで島ごとに保存され、ゲームプレイ セッション間で同じ状態が保たれます。持続可能データを使用すると、プレイセッション間でプレイヤーの進行状況を追跡できるようになり、以前の UEFN では利用できなかったユニークで興味を引くさまざまなプレイ体験を切り開くことができます。
このチュートリアルでは、Verse でプレイヤー統計データのカスタム テーブルを作成し、その統計データが複数のプレイ体験にわたって持続するようにセットアップする方法を示します。このチュートリアルの終了後、永続性を使用してゲーム内リーダーボードを作成する方法については、「Verse で独自のゲーム内ランキングを作成する」を確認してください。
使用する Verse 言語機能
-
クラス:下記の例では、単一の統計データを管理する Verse クラス、および単一のプレイヤーの統計データのグループを追跡する持続可能クラスを作成します。
-
コンストラクタ:コンストラクタは、関連付けられているクラスのインスタンスを作成する特別な関数です。
-
weak_map:weak_map は、反復処理できない単純なマップです。Verse の持続データは weak_map に格納する必要があります。
レベルを設定する
この例では、次の小道具と仕掛けを使用しています。
-
2 x ボタンの仕掛け:プレイヤーが仕掛けとインタラクトすると、プレイヤーの現在のスコアにポイントが加算されます。ボタンの仕掛けをもう一つ使用して、ゲームの終了をシミュレートし、現在のスコアに応じてプレイヤーの勝利数と敗北数を加算します。
-
1 x ビルボードの仕掛け:多くの場合、持続データをプレイヤーに見せることが重要です。これはテスト用に使用されることもあれば、プレイヤーのエンゲージメントを高めるためや進行状況を示すために使用されることもあります。データを表示するタイミングとどのデータを表示するかの要件は体験ごとに異なりますが、下記の例では、スコア、ハイスコア、勝利数、敗北数の統計データをビルボードの仕掛けに表示します。
持続型のプレイヤー統計データを追跡する
まず、どの統計データをプレイヤーごとに追跡するかを定義することが重要です。たとえば、プレーヤーのこれまでのスコア、現在のランク、ラップのベストタイムを追跡したい場合があります。この例では、各プレイヤーの統計値のテーブルでスコア、勝利数、敗北数を追跡します。そうするために、新規クラス player_stats_table
を作成し、これがメインの持続可能クラスになります。
以下の手順に従って、player_stats_table
を作成します。
-
Verse Explorer を使用して、
player_stats_table.verse
という新規 Verse ファイルを作成します。 -
その新規 Verse ファイル内で、「
player_stats_table
」という新規クラスを作成します。<persistable>
モディファイアおよび<final>
モディファイアの両方をクラスに追加します。<persistable>
モディファイアは、クラス内データを持続できるようにし、持続可能データはオーバーライドもサブクラス化もできないため、<final>
モディファイアが必要です。using { /Fortnite.com/Devices} using { /Verse.org/Simulation} using { /UnrealEngine.com/Temporary/Diagnostics} # プレイヤーごとに異なる持続可能な統計データを追跡します。 player_stats_table := class<final><persistable>:
-
player_stats_table
にScore
、Wins
、Losses
という名前の 3 つのint
値を追加します。これらはそれぞれ、各プレイヤーの存続期間中のスコア、勝利数、敗北数を追跡します。また、player_stats_table
の現在のバージョンを追跡するために、Version
というint
変数を追加します。# プレイヤーごとに異なる持続可能な統計データを追跡します。 player_stats_table := class<final><persistable>: # 最新の統計データ テーブルのバージョン。 Version<public>:int = 0 # プレイヤーのスコア。 Score<public>:int = 0 # プレイヤーの勝利数。 勝利<public>:int = 0 # プレイヤーの敗北数。 Losses<public>:int = 0
-
player_stats_table class
のインスタンスを作成するには、<constructor>
関数を使用します。 Verse の持続機能では、持続可能になる変数フィールドをクラスに含めることが許可されていないため、このコンストラクタが必要です。 コンストラクタを使用すると、変数である既存の持続可能統計データのコピーを作成し、そのコピーを更新してから、クラスの元のインスタンスを変更後の値で置き換えることで、持続可能クラスの値を更新できるようになります。 新しいコンストラクタ関数MakePlayerStatsTable()
をファイルに追加します。 このコンストラクタは、元 (以前) のplayer_stats_table
のインスタンスを受け取り、指定された元の値から新しいテーブルを作成します。# 前回の player_stats_table と同じ値を使用して、新しい player_stats_table を作成します。 MakePlayerStatsTable<constructor>(OldTable:player_stats_table)<transacts> := player_stats_table: Version := OldTable.Version Score := OldTable.Score Wins := OldTable.Wins Losses := OldTable.Losses
-
player_stats_tables
のすべてを追跡するために、持続可能である、player
のweak_map
をplayer_stats_table
インスタンスに使用します。このウイーク マップをファイルに追加します。# プレイヤーをそれぞれのプレイヤー統計データのテーブルにマッピングします。 var PlayerStatsMap:weak_map(player, player_stats_table) = map{}
-
完成した
player_stats_table
クラスは次のようになります。using { /Fortnite.com/Devices} using { /Verse.org/Simulation} using { /UnrealEngine.com/Temporary/Diagnostics} # プレイヤーごとに異なる持続可能な統計データを追跡します。 player_stats_table := class<final><persistable>: # 最新の統計データ テーブルのバージョン。 Version<public>:int = 0 # プレイヤーのスコア。 Score<public>:int = 0 # プレイヤーの勝利数。 勝利<public>:int = 0 # プレイヤーの敗北数。 Losses<public>:int = 0 # 前回の player_stats_table と同じ値を使用して、新しい player_stats_table を作成します。 MakePlayerStatsTable<constructor>(OldTable:player_stats_table)<transacts> := player_stats_table: Version := OldTable.Version Score := OldTable.Score Wins := OldTable.Wins Losses := OldTable.Losses # プレイヤーをそれぞれのプレイヤー統計データのテーブルにマッピングします。 var PlayerStatsMap:weak_map(player, player_stats_table) = map{}
全プレイヤーのプレイヤー統計データを管理する
player_stats_table
クラスでは、個々のプレイヤーの統計データを追跡できますが、それらを管理する手段がまだありません。各プレイヤーがスコアを獲得するごとに、そのプレイヤーの統計データ テーブルを更新する必要があり、ゲームの設計によっては多数のプレイヤーが同時にプレイする場合があります。
それを解決するために、もう一つのクラスを使用して、全プレイヤーの統計データを管理し、プレイヤーが勝利、敗北、スコアを獲得するごとに統計データの変化を記録します。以下の手順に従って、マネージャー クラスをセットアップします。
-
Verse Explorer を使用して、
player_stats_manager
という新規 Verse ファイルを作成します。その新規ファイル内で、新規クラスplayer_stats_manager
を作成します。using { /Fortnite.com/Devices} using { /Verse.org/Simulation} using { /UnrealEngine.com/Temporary/Diagnostics} # 各プレイヤーの player_stat_tables を管理および更新します。 player_stats_manager := class():
-
player_stats_manager
では、いくつかのことを行う必要があります。プレイヤーのplayer_stats_table
を設定し、プレイヤーごとのScore
、Wins
、Losses
を更新して、プレイヤーのplayer_stats_table
を返します。これらのそれぞれを別の関数で処理します。新しい関数InitializePlayer()
をplayer_stats_manager
クラス定義に追加します。この関数は、指定されたプレイヤーの統計データを初期化します。# 指定されたプレイヤーの統計データを初期化します。 InitializePlayer(Player:player):void=
-
InitializePlayer()
内で、指定されたプレイヤーがPlayerStatsMap
内にすでに存在するかどうかをチェックします。存在しなければ、マップにあるそのプレイヤーの値を新しいplayer_stats_table
に設定します。完成したInitializePlayer()
関数は次のようになります。# 指定されたプレイヤーの統計データを初期化します。 InitializePlayer(Player:player):void= if: not PlayerStatsMap[Player] set PlayerStatsMap[Player] = player_stats_table{} else: Print("Unable to initialize player stats")
-
新しい関数
InitializePlayer()
をplayer_stats_manager
クラス定義に追加します。この関数は、プレイヤーの配列を受け取り、その中のすべてのプレイヤーに対してInitializePlayer()
を呼び出します。完成したInitializeAllPlayers()
関数は次のようになっています。# 現在の全プレイヤーの統計データを初期化します。 InitializeAllPlayers(Players:[]player):void = for (Player : Players): InitializePlayer(Player)
-
特定のプレイヤーの統計データを返すために、指定されたプレイヤーの
player_stats_table
を返す関数が必要です。 新しい関数GetPlayerStats()
をplayer_stats_manager
クラスに追加します。この関数はエージェントを受け取ります。さらに<decides><transacts>
モディファイアを付加して、プレイヤーの統計データ テーブルが存在しない場合に、この関数が失敗してロールバックできるようにします。GetPlayerStats()
で、新しいplayer_stats_table
変数PlayerStats
を作成します。# 指定されたエージェントの player_stats_table を返します。 GetPlayerStats(Agent:agent)<decides><transacts>:player_stats_table= var PlayerStats:player_stats_table = player_stats_table{}
-
if
式内で、この関数に渡されたAgent
をPlayer
にキャストし、そのプレイヤーのplayer_stats_table
をPlayerStatsMap
から取得します。そして、MakePlayerStatsTable()
を呼び出して、PlayerStats
をそのテーブルに設定します。最後にPlayerStats
を返します。完成したGetPlayerStats()
関数は次のようになっています。# 指定されたエージェントの player_stats_table を返します。 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) PlayerStats
-
スコア、勝利数、敗北数の各統計データを更新するには、統計データごとに関数を作成します。「
player_stats_manager
」ファイルにAddScore()
という名前の新しい関数を追加します。この関数は、スコアを付与するエージェントと、付与するint
数のポイントを受け取ります。# 指定されたエージェントのスコアに加算し、両方の統計データ テーブルを更新します。 # レベルにあるビルボードの両方を更新します。 AddScore<public>(Agent:agent, NewScore:int):void=
-
データを更新するには、持続可能な
weak_map
にそのプレイヤーの有効なデータがあることを確認してから、クラスの更新済みコピーでそのデータを置き換えます。この処理をスコアに対して行うには、プレイヤーのスコアをPlayerStatsTable
から取得し、MakePlayerStatsTable()
を使用して新しいplayer_stats_table
を構築した結果にPlayerStatsMap
内のテーブルを設定し、現在のスコアと新しいスコアを渡します。複数のフィールドがあるクラスを操作する場合は、クラス コンストラクタを使用して、更新を行うたびにすべてのフィールドを明示的にコピーすることなく、1 つのフィールドを簡単に更新できます。AddScore()
関数は次のようになるはずです。# 指定されたエージェントのスコアに加算し、両方の統計データ テーブルを更新します。 # レベルにあるビルボードの両方を更新します。 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 + NewScore else: Print("Unable to record player Score")
-
この処理を勝利数と敗北数に対しても繰り返し、
MakePlayerStatsTable()
の呼び出し時に、プレイヤーの勝利数または敗北数にそれぞれNewWins
とNewLosses
を加算します。# 指定されたエージェントの勝利数に加算し、両方の統計テーブルを更新します。 # レベルにあるビルボードの両方を更新します。 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 + NewWins else: Print("Unable to record player Wins") # 指定されたエージェントの敗北数に加算し、両方の統計テーブルを更新します。 # レベルにあるビルボードの両方を更新します。 AddLoss<public>(Agent:agent, NewLosses:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentLosses := PlayerStatsTable.Losses set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Losses := CurrentLosses + NewLosses else: Print("Unable to record player Loss")
-
最終的な
player_stats_manager
ファイルは次のようになっています。using { /Fortnite.com/Devices} using { /Verse.org/Simulation} using { /UnrealEngine.com/Temporary/Diagnostics} # 各プレイヤーの player_stat_tables を管理および更新します。 player_stats_manager := class(): # 指定されたエージェントの player_stats_table を返します。 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) PlayerStats # 現在の全プレイヤーの統計データを初期化します。 InitializeAllPlayers(Players:[]player):void = for (Player : Players): InitializePlayer(Player) # 指定されたプレイヤーの統計データを初期化します。 InitializePlayer(Player:player):void= if: not PlayerStatsMap[Player] set PlayerStatsMap[Player] = player_stats_table{} else: Print("Unable to initialize player stats") # 指定されたエージェントのスコアに加算し、両方の統計データ テーブルを更新します。 # レベルにあるビルボードの両方を更新します。 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 + NewScore else: Print("Unable to record player Score") # 指定されたエージェントの勝利数に加算し、両方の統計テーブルを更新します。 # レベルにあるビルボードの両方を更新します。 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 + NewWins else: Print("Unable to record player Wins") # 指定されたエージェントの敗北数に加算し、両方の統計テーブルを更新します。 # レベルにあるビルボードの両方を更新します。 AddLoss<public>(Agent:agent, NewLosses:int):void= if: Player := player[Agent] PlayerStatsTable := PlayerStatsMap[Player] CurrentLosses := PlayerStatsTable.Losses set PlayerStatsMap[Player] = player_stats_table: MakePlayerStatsTable<constructor>(PlayerStatsTable) Losses := CurrentLosses + NewLosses else: Print("Unable to record player Loss")
持続機能を仕掛けでテストする
ここまでで持続クラスをセットアップしたので、それらをレベルでテストします。
-
player_stats_example という新しい Verse の仕掛けを作成します。手順については、「Verse を使用して独自の仕掛けを作成する」を参照してください。
-
player_stats_example
クラス定義の先頭に以下のフィールドを追加します。-
ScorePointsButton
という名前の編集可能なbutton_device
。このボタンがアクティブ化されると、プレイヤーのスコアに加算されます。# アクティブ化したプレイヤーのスコアに加算します。 @editable ScorePointsButton:button_device = button_device{}
-
StatsBillboard
という名前の編集可能なbillboard_device
。これはプレイヤーの Score、HighScore、Wins、Losses を表示します。# プレイヤーの Score、HighScore、Wins、Losses を表示します。 @editable StatsBillboard:billboard_device = billboard_device{}
-
CheckWinButton
という編集可能な button_device。このボタンは、各プレイヤーのスコアを設定し直し、プレイヤーのスコアに応じてプレイヤーに勝利または敗北を与えます。# プレイヤーのスコアを設定し直し、プレイヤーの現在のスコアが WinScore # より大きいかどうかに応じてプレイヤーに勝利または敗北を与えます。 @editable CheckWinButton:button_device = button_device{}
-
WinScore
という名前の、編集可能なint
。CheckWinButton
がアクティブ化された後にこのスコアに達していれば、プレイヤーに勝利が与えられます。# CheckWinButton がアクティブ化された後にこのスコアに達していれば、 # プレイヤーに勝利が与えられます。 @editable WinScore:int = 10
-
AwardScore
という名前の、編集可能なint
。これは、ボタンを操作したときにプレイヤーに付与されるスコアです。# ボタンを押すたびに付与されるスコアの量。 @editable AwardScore:int = 1
-
PlayerStatsManager
という名前のplayer_stats_manager
。これは全プレイヤーの統計データを管理および更新します。# 各プレイヤーの統計データを管理および更新します。 PlayerStatsManager:player_stats_manager = player_stats_manager{}
-
エージェントに 4 つの整数 Score、MaxScore、Wins、Losses を受け取る、StatsMessage というメッセージ。このメッセージを使用して、プレイヤーの統計データをビルボードに表示します。
# プレイヤーの統計データをビルボードに表示します。 StatsMessage<localizes>(Player:agent, Score:int, Wins:int, Losses:int):message = "{Player}, Stats:\n Score: {Score}\n Wins: {Wins}\n Losses: {Losses}"
-
-
コードをコンパイルして、Verse で作成した仕掛けを島にドラッグします。手順については、「Verse の仕掛けをレベルに追加する」を参照してください。
-
仕掛けの [Details (詳細)] パネルで、レベルにあるボタンの仕掛けを ScorePointsButton に割り当て、ビルボードの仕掛けを StatsBillboard に割り当てます。
-
指定されたプレイヤーの統計データを StatsBillboard に表示するために、新しい関数
UpdateStatsBillboard()
をplayer_stats_example
クラス定義に追加します。この関数は、受け取ったエージェントの統計データを表示します。# 指定されたプレイヤーの統計データを取得し、その統計データを # StatsBillboard に表示します。 UpdateStatsBillboard(Agent:agent):void=
-
UpdateStatsBillboard()
内で、統計データ マネージャーのGetPlayerStats[]
関数を呼び出して、指定されたエージェントの現在の統計データを取得します。そして、StatsMessage()
を渡して StatsBillboard のSetText()
を呼び出します。このStatsMessage()
を構築するために、エージェントの現在の統計データからエージェントの Score、Wins、Losses にアクセスして、それらの値を取得します。完成したUpdateStatsBillboard()
関数は次のようになっています。# 指定されたプレイヤーの統計データを取得し、その統計データを # StatsBillboard に表示します。 UpdateStatsBillboard(Agent:agent):void= if: # 指定されたエージェントの現在の統計データを取得します。 CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent] then: StatsBillboard.SetText( StatsMessage( Player := Agent, Score:=CurrentPlayerStats.Score.CurrentValue, Wins:=CurrentPlayerStats.Wins.CurrentValue, Losses:=CurrentPlayerStats.Losses.CurrentValue ) )
-
新しい関数
AddScore()
をplayer_stats_example
クラス定義に追加します。この関数はエージェントを受け取り、ScorePointsButton とインタラクトするごとに、そのエージェントのスコアを加算します。# 指定されたプレイヤーのスコアに加算し、PlayerStatsManager 内の統計データ テーブルと # レベルにあるビルボードの両方を更新します。 AddScore(Agent:agent):void=
-
AddScore()
内で、指定されたエージェントの現在の統計データと現在のスコアを取得します。次に、PlayerStatsManager
からAddScore()
を呼び出し、エージェントとAwardScore
を渡して新しいスコアを付与します。最後に、指定されたエージェントを渡してUpdateStatsBillboard()
を呼び出します。完成したAddScore()
関数は次のようになっています。# 指定されたプレイヤーのスコアに加算し、PlayerStatsManager 内の統計データ テーブルと # レベルにあるビルボードの両方を更新します。 AddScore(Agent:agent):void= if: CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent] CurrentScore := CurrentPlayerStats.Score then: Print("Current Score is: {CurrentScore}") PlayerStatsManager.AddScore(Agent, AwardScore) UpdateStatsBillboard(Agent)
-
CheckWin がインタラクトされたときにプレイヤーに勝利または敗北を与えるために、新しい関数
CheckWin()
を player_stats_manager クラス定義に追加します。# CheckWin がインタラクトされたときにプレイヤーに # 勝利または敗北を与えます。 CheckWin(Agent:agent):void=
-
まず、エージェントの現在のスコアを追跡するための変数
CurrentScore
を定義します。次に、AddScore()
関数と同様に、プレーヤーの統計データ テーブルから現在のスコアを取得します。# CheckWin がインタラクトされたときにプレイヤーに # 勝利または敗北を与えます。 CheckWin(Agent:agent):void= var CurrentScore:int = 0 if: PlayerStats := PlayerStatsManager.GetPlayerStats[Agent] set CurrentScore = PlayerStats.Score
-
エージェントの現在のスコアが
WinScore
より大きければ勝利を、そうでなければ敗北をPlayerStatsManager
に 記録する必要があります。最後に、負のCurrentScore
を渡してAddScore()
を呼び出してエージェントのスコアを設定し直し、エージェントの統計データを統計データのビルボードに表示します。完成したCheckWin()
関数は次のようになっています。# CheckWin がインタラクトされたときにプレイヤーに # 勝利または敗北を与えます。 CheckWin(Agent:agent):void= var CurrentScore:int = 0 if: PlayerStats := PlayerStatsManager.GetPlayerStats[Agent] set CurrentScore = PlayerStats.Score then: Print("Current Score is: {CurrentScore}") if: CurrentScore > WinScore then: PlayerStatsManager.AddWin(Agent, 1) # プレイヤーのスコアの統計データを 0 と記録することで、プレイヤーのスコアをリセットします。 PlayerStatsManager.AddScore(Agent, -CurrentScore) else: PlayerStatsManager.AddLoss(Agent, 1) # プレイヤーのスコアの統計データを 0 と記録することで、プレイヤーのスコアをリセットします。 PlayerStatsManager.AddScore(Agent, -CurrentScore) UpdateStatsBillboard(Agent)
-
OnBegin()
で、ScorePointsButton.InteractedWithEvent
をAddScore()
にサブスクライブし、CheckWinButton.InteractedWithEvent
をCheckWin()
にサブスクライブします。そして、GetPlayers()
を呼び出してゲーム内の各プレイヤーの配列を取得し、統計データ マネージャーのInitializeAllPlayers()
関数を使用してそれらすべてを初期化します。# 実行中のゲームで仕掛けが開始されたときに実行します OnBegin<override>()<suspends>:void= # ボタン イベントを登録します。 ScorePointsButton.InteractedWithEvent.Subscribe(AddScore) CheckWinButton.InteractedWithEvent.Subscribe(CheckWin) Players := GetPlayspace().GetPlayers() # プレイヤー統計データを初期化します。 PlayerStatsManager.InitializeAllPlayers(Players)
-
コードを保存してコンパイルします。
持続機能をレベルでテストする
持続データを編集セッションでテストできますが、そのセッションを終了して再起動すると、そのデータはリセットされます。セッションをまたいでデータを持続させるには、プレイテスト セッション を起動し、島設定 の特定の設定を変更する必要があります。 編集セッションとプレイテスト セッションの両方で持続可能データをテストできるように島を設定する方法については、持続データ ページの「持続データでテストする」を参照してください。
セッションを設定した後にレベルをプレイテストする場合、ScorePoints ボタンとインタラクトすると、プレイヤーのスコアに加算され、更新された値がビルボードに表示されるはずです。CheckWin ボタンとインタラクトすると、プレイヤーのスコアに応じて、プレイヤーの勝利数または敗北数に加算されるはずです。ロビーに戻ってからもう一度島に入ると、プレイヤーの統計データが持続されていて、更新されるたびに総勝利数/総敗北数と最高スコアがビルボードに表示されるはずです。
応用編
このガイドを完了したことで、Verse を使用して、ゲームプレイ セッション間で持続する、プレイヤーごとに追跡される持続可能データを作成する方法を習得できました。次は、持続機能を応用して独自の体験をどのように高めることができるかを確かめてください。
- プレイヤーが到達した最後のチェックポイントを覚えている保存ファイル システムを作成できますか?
- 会話したことがあるキャラクターおよびそのキャラクターとの現在の関係を覚えているシステムについてはどうですか?
- 複数のセッションにわたってゴールに到達までの限られた時間のみをプレイヤーに与えて、失敗したらプレイヤーの進行度をリセットするシステムについてはどうですか?
完全なコード
このセクションのチュートリアルで作成した完全なコードを以下に示します。
player_stats_table.verse
using { /Fortnite.com/Devices}
using { /Verse.org/Simulation}
using { /UnrealEngine.com/Temporary/Diagnostics}
# プレイヤーごとに異なる持続可能な統計データを追跡します。
player_stats_table := class<final><persistable>:
# 最新の統計データ テーブルのバージョン。
Version<public>:int = 0
# プレイヤーのスコア。
Score<public>:int = 0
# プレイヤーの勝利数。
勝利<public>:int = 0
# プレイヤーの敗北数。
Losses<public>:int = 0
# 前回の player_stats_table と同じ値を使用して、新しい player_stats_table を作成します。
MakePlayerStatsTable<constructor>(OldTable:player_stats_table)<transacts> := player_stats_table:
Version := OldTable.Version
Score := OldTable.Score
Wins := OldTable.Wins
Losses := OldTable.Losses
# プレイヤーをそれぞれのプレイヤー統計データのテーブルにマッピングします。
var PlayerStatsMap:weak_map(player, player_stats_table) = map{}
player_stats_manager.verse
using { /Fortnite.com/Devices}
using { /Verse.org/Simulation}
using { /UnrealEngine.com/Temporary/Diagnostics}
# 各プレイヤーの player_stat_tables を管理および更新します。
player_stats_manager := class():
# 指定されたエージェントの player_stats_table を返します。
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)
PlayerStats
# 現在の全プレイヤーの統計データを初期化します。
InitializeAllPlayers(Players:[]player):void =
for (Player : Players):
InitializePlayer(Player)
# 指定されたプレイヤーの統計データを初期化します。
InitializePlayer(Player:player):void=
if:
not PlayerStatsMap[Player]
set PlayerStatsMap[Player] = player_stats_table{}
else:
Print("Unable to initialize player stats")
# 指定されたエージェントのスコアに加算し、両方の統計データ テーブルを更新します。
# レベルにあるビルボードの両方を更新します。
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 + NewScore
else:
Print("Unable to record player Score")
# 指定されたエージェントの勝利数に加算し、両方の統計テーブルを更新します。
# レベルにあるビルボードの両方を更新します。
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 + NewWins
else:
Print("Unable to record player Wins")
# 指定されたエージェントの敗北数に加算し、両方の統計テーブルを更新します。
# レベルにあるビルボードの両方を更新します。
AddLoss<public>(Agent:agent, NewLosses:int):void=
if:
Player := player[Agent]
PlayerStatsTable := PlayerStatsMap[Player]
CurrentLosses := PlayerStatsTable.Losses
set PlayerStatsMap[Player] = player_stats_table:
MakePlayerStatsTable<constructor>(PlayerStatsTable)
Losses := CurrentLosses + NewLosses
else:
Print("Unable to record player Loss")
player_stats_example.verse
using { /Fortnite.com/Devices}
using { /Fortnite.com/Game}
using { /Verse.org/Simulation}
using { /UnrealEngine.com/Temporary/Diagnostics}
# レベルに配置できる、Verse で作成したクリエイティブの仕掛け
player_stats_example := class(creative_device):
# アクティブ化したプレイヤーのスコアに加算します。
@editable
ScorePointsButton:button_device = button_device{}
# プレイヤーの Score、HighScore、Wins、Losses を表示します。
@editable
StatsBillboard:billboard_device = billboard_device{}
# プレイヤーのスコアを設定し直し、プレイヤーの現在のスコアが WinScore
# より大きいかどうかに応じてプレイヤーに勝利または敗北を与えます。
@editable
CheckWinButton:button_device = button_device{}
# CheckWinButton がアクティブ化された後にこのスコアに達していれば、
# プレイヤーに勝利が与えられます。
@editable
WinScore:int = 10
# ボタンを押すたびに付与されるスコアの量。
@editable
AwardScore:int = 1
# 各プレイヤーの統計データを管理および更新します。
PlayerStatsManager:player_stats_manager = player_stats_manager{}
# プレイヤーの統計データをビルボードに表示します。
StatsMessage<localizes>(Player:agent, Score:int, Wins:int, Losses:int):message = "{Player}, Stats:\n Score: {Score}\n Wins: {Wins}\n Losses: {Losses}"
# 実行中のゲームで仕掛けが開始されたときに実行します
OnBegin<override>()<suspends>:void=
# ボタン イベントを登録します。
ScorePointsButton.InteractedWithEvent.Subscribe(AddScore)
CheckWinButton.InteractedWithEvent.Subscribe(CheckWin)
Players := GetPlayspace().GetPlayers()
# プレイヤー統計データを初期化します。
PlayerStatsManager.InitializeAllPlayers(Players)
# 指定されたプレイヤーのスコアに加算し、PlayerStatsManager 内の統計データ テーブルと
# レベルにあるビルボードの両方を更新します。
AddScore(Agent:agent):void=
if:
CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent]
CurrentScore := CurrentPlayerStats.Score
then:
Print("Current Score is: {CurrentScore}")
PlayerStatsManager.AddScore(Agent, AwardScore)
UpdateStatsBillboard(Agent)
# 指定されたプレイヤーの統計データを取得し、その統計データを
# StatsBillboard に表示します。
UpdateStatsBillboard(Agent:agent):void=
if:
# 指定されたエージェントの現在の統計データを取得します。
CurrentPlayerStats := PlayerStatsManager.GetPlayerStats[Agent]
then:
StatsBillboard.SetText(
StatsMessage(
Player := Agent,
Score:=CurrentPlayerStats.Score,
Wins:=CurrentPlayerStats.Wins,
Losses:=CurrentPlayerStats.Losses
)
)
# CheckWin がインタラクトされたときにプレイヤーに
# 勝利または敗北を与えます。
CheckWin(Agent:agent):void=
var CurrentScore:int = 0
if:
PlayerStats := PlayerStatsManager.GetPlayerStats[Agent]
set CurrentScore = PlayerStats.Score
then:
Print("Current Score is: {CurrentScore}")
if:
CurrentScore > WinScore
then:
PlayerStatsManager.AddWin(Agent, 1)
# プレイヤーのスコアの統計データを 0 と記録することで、プレイヤーのスコアをリセットします。
PlayerStatsManager.AddScore(Agent, -CurrentScore)
else:
PlayerStatsManager.AddLoss(Agent, 1)
# プレイヤーのスコアの統計データを 0 と記録することで、プレイヤーのスコアをリセットします。
PlayerStatsManager.AddScore(Agent, -CurrentScore)
UpdateStatsBillboard(Agent)