「タイムトライアル:ピザ配送」チュートリアルのこのステップを完了すると、プレイヤーがアイテムをピックアップして配送したときのスコアを管理する方法、および UI を更新してスコアを表示する方法を習得できます。 Verse でのインゲーム UI の作成の詳細については、「インゲーム UI を作成する」を参照してください。
スコア マネージャーは、以下をトラックして表示します。
Total Points (合計ポイント):プレイヤーがゲーム内で獲得した総ポイントを表します。
Pending Points (保留中のポイント):プレイヤーが現在の一連のピックアップに対して蓄積しているポイントを表します。
Pickup Level (ピックアップ レベル):現在のピックアップ レベルを表します。
UI を作成する
Verse でスコア マネージャーの UI を作成するには、以下の手順に従います。
新しい空の Verse ファイルを作成し、「score_manager.verse」という名前を付けます。
score_managerという名前で新しいクラスを作成し、次のフィールドをクラスに追加します。プレイヤーへの参照を格納する、
MaybePlayerという名前の任意指定のagent。MaybePlayer<internal> : ?agent = falseプレイヤーの UI への参照を格納する、
MaybePlayerUIという名前の任意指定のplayer_ui。MaybePlayerUI<internal> : ?player_ui = falseこのクラスが構築されるスコア マネージャーの仕掛けへの参照を格納する
score_manager_device(Verse で作成されたgame_coordinator_deviceの仕掛けに接続する必要があるため、この参照は編集可能ではありません)。ScoreManagerDevice<internal> : score_manager_device = score_manager_device{}プレイヤーがゲーム全体で獲得したすべてのポイントを表す、
TotalGameScoreという名前の整数変数。var TotalGameScore<private> : int = 0プレイヤーがこの一連のピックアップに対して現在蓄積しているポイントを表す
PendingScoreという名前の整数変数。var PendingScore<private> : int = 0現在のピックアップ レベルを表す
PickupLevelという名前の整数変数。var PickupLevel<private> : int = 0
score_manager のクラス定義は次のようになります。
score_manager := class: MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0クラスを最初に作成するときに UI を作成します。 これを行うには、クラスのインスタンスが作成されるたびに実行される
block式をクラス定義に追加します。 UI を生成するために次の変数を追加します。カスタム キャンバス ウィジェットを格納するための
internal指定子を持つCanvasという名前のcanvas変数。var Canvas<internal> : canvas = canvas{}プレイヤーがゲーム全体で獲得したすべてのポイント (
TotalGameScore変数で表される) を表示するテキスト ウィジェットを格納するための、internal指定子付きのTotalGameScoreWidgetという名前のtext_block。 このテキスト ブロックのデフォルトのテキストの色を白に設定します。TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White}プレイヤーがこの一連のピックアップに対して現在蓄積しているポイント (
PendingScore変数で表される) を表示するテキスト ウィジェットを格納するための、internal指定子付きのPendingScoreWidgetという名前のtext_block。 このテキスト ブロックのデフォルトのテキストの色を白に設定します。PendingScoreWidget<internal> : text_block = text_block{}現在のピックアップ レベル (
PickupLevel変数で表される) を表示するテキスト ウィジェットを格納するための、internal指定子付きのPickupLevelWidgetという名前のtext_block。 このテキスト ブロックのデフォルトのテキストの色を白に設定します。PickupLevelWidget<internal> : text_block = text_block{}プレイヤーがゲームで獲得した総合ポイントについて、UI に表示できるローカライズ可能なテキストを作成する、
TotalGameScoreTextという名前のmessageを返す関数。TotalGameScoreText<localizes>(CurrentTotalGameScore : int) : message = "Total Points: {CurrentTotalGameScore}"この一連のピックアップに対してプレイヤーが現在蓄積しているポイントの UI に表示できるローカライズ可能なテキストを作成する、
PendingScoreTextという名前のmessageを返す関数。PendingScoreText<localizes>(CurrentPendingScore : int) : message = "Pending Points: {CurrentPendingScore}"現在のピックアップ レベルの UI に表示できるローカライズ可能なテキストを作成する、
PickupLevelTextという名前のmessageを返す関数。PickupLevelText<localizes>(CurrentPickupLevel : int) : message = "Pickup Level: {CurrentPickupLevel}"キャンバス ウィジェットを作成して画面の左側に縦に並べてテキストを配置する
block式を追加します。<# スコア マネージャーの存続期間中にキャンバスを再作成しなくて済むように、この型のオブジェクトが作成されたときに、これを 1 回実行します。 #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidget
score_managerのコードは次のようになります。using { /UnrealEngine.com/Temporary/UI } using { /Fortnite.com/UI } using { /Verse.org/Colors } score_manager := class: var Canvas<internal> : canvas = canvas{} TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PendingScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} PickupLevelWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White} MaybePlayer<internal> : ?agent = false MaybePlayerUI<internal> : ?player_ui = false ScoreManagerDevice<internal> : score_manager_device = score_manager_device{} PickupLevelText<private><localizes>(InLevel : int) : message = "Pickup Level: {InLevel}" PendingScoreText<private><localizes>(InPoints : int) : message = "Pending Points: {InPoints}" TotalGameScoreText<private><localizes>(InPoints : int) : message = "Total Points: {InPoints}" var TotalGameScore<private> : int = 0 var PendingScore<private> : int = 0 var PickupLevel<private> : int = 0 <# スコア マネージャーの存続期間中にキャンバスを再作成しなくて済むように、この型のオブジェクトが作成されたときに、これを 1 回実行します。 #> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := true Widget := stack_box: Orientation := orientation.Vertical Slots := array: stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := TotalGameScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PendingScoreWidget stack_box_slot: HorizontalAlignment := horizontal_alignment.Left Widget := PickupLevelWidgetUI 内のテキストを最新のスコア値と現在のピックアップ レベルで更新する関数を、
UpdateUI()という名前で、private指定子付きで作成します。UpdateUI<private>() : void = if (PlayerUI := MaybePlayerUI?): PickupLevelWidget.SetText(PickupLevelText(PickupLevel)) PendingScoreWidget.SetText(PendingScoreText(PendingScore)) PendingScoreWidget.SetText(TotalGameScoreText(TotalGameScore))カスタム スコア マネージャーの UI でプレイヤーの UI を更新する関数を
AddScoreManagerToUI()という名前で作成します。AddScoreManagerToUI<public>() : void = if (PlayerUI := MaybePlayerUI?): PlayerUI.AddWidget(Canvas) UpdateUI()ゲーム ループが値を更新できるように、UI に表示される各値の関数を作成します。
public指定子を持つ「AddPendingScoreToTotalScore()」という名前の関数。 この関数は、保留中のスコアを総ゲーム スコアに加算し、保留中のスコア値を0にリセットします。TotalGameScoreの更新後、PendingScoreのリセットと UI の更新にdeferを実行できます。 そうすることで、一時変数を使用してリセット前のPendingScoreの値を保持する必要がなくなります。Verse<# Adds PendingScore to TotalGameScore and resets PendingScore to 0.#> AddPendingScoreToTotalScore<public>() : void = defer: set PendingScore = 0 UpdateUI() set TotalGameScore += PendingScoreUpdatePendingScore()という名前のpublic指定子付きの関数。Pointsという名前の整数パラメータを持ち、この値を関数が現在の保留中のスコアに加算します。Verse<# Adds the given amount of points to the pending points. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI()public指定子と現在のピックアップ レベルの新しい値であるLevelという整数パラメータを持つ、UpdatePickupLevelという名前の関数。VerseUpdatePickupLevel<public>(Level : int) : void = set PickupLevel = Level UpdateUI()public指定子付きで「AwardScore()」という名前の関数を作成します。 この関数は、スコア マネージャーの仕掛けを使用してプレイヤーにスコアを付与し、その仕掛けをアクティブ化します。Verse<# Awards the score to the player with the Score Manager device, by activating it. #> AwardScore<public>() : void = ScoreManagerDevice.SetScoreAward(TotalGameScore) if (AwardedPlayer := MaybePlayer?): ScoreManagerDevice.Activate(AwardedPlayer)
score_managerクラスは次のようになります。•Versescore_manager := class: <# Since we won't recreate the canvas during the score manager lifetime, do it once anytime an object of this type is created.> block: set Canvas = canvas: Slots := array: canvas_slot: Anchors := anchors{Minimum := vector2{X := 0.0, Y := 0.25}, Maximum := vector2{X := 0.0, Y := 0.25} } Offsets := margin{Top := 0.0, Left := 25.0, Right := 0.0, Bottom := 0.0} Alignment := vector2{X := 0.0, Y := 0.0} SizeToContent := truescore_managerクラスを作成したので、このクラスのコンストラクタを作成して、ゲームのプレイヤー変数を初期化します。 プレイヤーの UI への参照を取得するには、プレイヤーの参照をagentからplayerに型変換する必要があることに注意してください。VerseMakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}「score_manager.verse」ファイルは次のようになります。
Verseusing { /UnrealEngine.com/Temporary/SpatialMath} using { /UnrealEngine.com/Temporary/UI } using { /Fortnite.com/Devices } using { /Fortnite.com/UI } using { /Verse.org/Colors } using { /Verse.org/Simulation } MakeScoreManager<constructor><public>(InPlayer : agent, InScoreManagerDevice : score_manager_device) := score_manager: MaybePlayer := option{InPlayer} MaybePlayerUI := option{GetPlayerUI[player[InPlayer]]}
ゲーム ループでスコアと UI を更新する
次の手順に従って、「game_coordinator_device.verse」ファイルでゲーム中に UI を作成および更新します。
次のプロパティを
game_coordinator_deviceクラスに追加します。private指定子を持つScoreManagerという名前のscore_manager変数。 このインスタンスは、プレイヤーのスコアと UI を管理します。var ScoreManager<private> : score_manager = score_manager{}レベル内でスコア マネージャーの仕掛けに設定できる、編集可能な
score_manager_device。 これは、score_managerクラスで使用される仕掛けです。@editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{}各ピックアップ レベルでプレイヤーが獲得できるポイントを定義する、
public指定子を持つPointsForPickupLevelという名前の編集可能な整数配列。@editable # ピックアップ レベルに応じて、ピックアップに与えるポイント数をマッピングします。 PointsForPickupLevel<public> : []int = array{1, 2, 3}
この
StartGame関数では、プレイヤーとスコア マネージャーの仕掛けへの参照を指定してMakeScoreManager()コンストラクタを呼び出すことで、スコア マネージャーの変数を初期化し、そのプレイヤーに表示する UI を生成します。VerseStartGame<private>()<suspends> : void = Logger.Print("Trying to start the game...") # We construct a new countdown_timer that'll countdown from InitialCountdownTime once started. # Also construct a new score_manager that'll keep track of the player's score and pickup level. # The countdown_timer and score_manager require a player to show their UI to. # We should have a valid player by now: the one that entered the vehicle, triggering the game start. if (ValidPlayer := MaybePlayer?): Logger.Print("Valid player, starting game...")ゲーム ループ
PickupDeliveryLoop()関数では、ピックアップ レベルが変化し、プレイヤーがピックアップまたは配送を終了するたびに UI を更新します。VersePickupDeliveryLoop<private>()<suspends> : void = PickupZonesTags : []pickup_zone_tag = array{pickup_zone_level_1_tag{}, pickup_zone_level_2_tag{}, pickup_zone_level_3_tag{}} MaxPickupLevel := PickupZonesTags.Length - 1 FirstPickupZoneCompletedEvent := event(){} loop: var PickupLevel : int = 0 var IsFirstPickup : logic = true # Every time the loop restarts, we should reset the pickup level UI through the ScoreManager.カウントダウンが終了したら、プレイヤーにスコアを与えます。
HandleCountdownEnd()内でScoreManager.AwardScore()を呼び出します。HandleCountdownEnd<private>(InPlayer : player)<suspends>:void= TotalTime := CountdownTimer.CountdownEndedEvent.Await() ScoreManager.AwardScore() EndGame.Activate(InPlayer)「game_coordinator_device.verse」ファイルは次のようになります。
Verseusing { /Verse.org/Simulation } using { /Fortnite.com/Devices } using { /Fortnite.com/Vehicles } using { /Fortnite.com/Characters } using { /Fortnite.com/Playspaces } using { /Verse.org/Random } using { /UnrealEngine.com/Temporary/Diagnostics } using { /UnrealEngine.com/Temporary/SpatialMath } using { /EpicGames.com/Temporary/Curves } using { /Verse.org/Simulation/Tags }