타임 트라이얼: 피자 배달 게임 튜토리얼의 이번 단계를 마치면 플레이어가 아이템을 픽업하여 배달할 때 점수를 관리하고 이 점수를 표시하는 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{}플레이어가 게임 전체에서 득점한 모든 점수를 나타내는 integer 변수
TotalGameScore.var TotalGameScore<private> : int = 0플레이어가 이 픽업 세트에 대해 현재까지 누적한 점수를 나타내는 integer 변수
PendingScore.var PendingScore<private> : int = 0현재 픽업 레벨을 나타내는 integer 변수
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{}internal지정자가 있고,TotalGameScore변수로 나타나는 플레이어가 게임 전체에서 획득한 총점을 표시할 텍스트 위젯을 저장하는text_block인TotalGameScoreWidget. 텍스트 블록의 기본 텍스트 컬러를 흰색으로 설정합니다.TotalGameScoreWidget<internal> : text_block = text_block{DefaultTextColor := NamedColors.White}internal지정자가 있고,PendingScore변수로 나타나는 플레이어가 이 픽업 세트에서 현재까지 누적한 점수를 표시할 텍스트 위젯을 저장하는text_block인PendingScoreWidget. 텍스트 블록의 기본 텍스트 컬러를 흰색으로 설정합니다.PendingScoreWidget<internal> : text_block = text_block{}internal지정자가 있고,PickupLevel변수로 나타나는 현재 픽업 레벨을 표시할 텍스트 위젯을 저장하는text_block인PickupLevelWidget. 텍스트 블록의 기본 텍스트 컬러를 흰색으로 설정합니다.PickupLevelWidget<internal> : text_block = text_block{}플레이어가 게임에서 획득한 총점을 UI에 표시될 수 있는 현지화된 텍스트로 생성하는
message를 반환하는 함수TotalGameScoreText.TotalGameScoreText<localizes>(CurrentTotalGameScore : int) : message = "Total Points: {CurrentTotalGameScore}"플레이어가 이 픽업 세트에서 현재까지 누적한 점수를 UI에 표시될 수 있는 현지화된 텍스트로 생성하는
message를 반환하는 함수PendingScoreText.PendingScoreText<localizes>(CurrentPendingScore : int) : message = "Pending Points: {CurrentPendingScore}"현재 픽업 레벨을 UI에 표시될 수 있는 현지화된 텍스트로 생성하는
message를 반환하는 함수PickupLevelText.PickupLevelText<localizes>(CurrentPickupLevel : int) : message = "Pickup Level: {CurrentPickupLevel}"캔버스 위젯을 생성하고 텍스트를 화면 왼쪽에 세로로 쌓는
block표현식을 추가합니다.<# 점수 관리 장치의 수명 동안 캔버스를 재생성하지 않을 것이므로, 이 타입의 오브젝트가 생성될 때 한 번만 수행합니다. #> 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 <# 점수 관리자의 수명 동안 캔버스를 재생성하지 않을 것이므로, 이 타입의 오브젝트가 생성될 때 한 번만 수행합니다. #> 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이름이
UpdateUI()이고private지정자가 있는 함수를 생성합니다. 이 함수는 마지막 점수 값과 현재 픽업 레벨로 UI의 텍스트를 업데이트합니다.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으로 리셋합니다.PendingScore의 리셋과 UI 업데이트는TotalGameScore업데이트 이후로defer할 수 있습니다. 이렇게 하면PendingScore리셋 전에 값을 저장하기 위해 임시 변수를 사용하지 않아도 됩니다.Verse<# Adds PendingScore to TotalGameScore and resets PendingScore to 0.#> AddPendingScoreToTotalScore<public>() : void = defer: set PendingScore = 0 UpdateUI() set TotalGameScore += PendingScorepublic지정자와 함수에서 현재 획득 예정 점수에 더할 integer 파라미터Points가 있는UpdatePendingScore()함수.Verse<# Adds the given amount of points to the pending points. #> UpdatePendingScore<public>(Points : int) : void = set PendingScore += Points UpdateUI()public지정자와 현재 픽업 레벨에 대한 새 값인 integer 파라미터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 := true이제
score_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지정자가 있는score_manager변수ScoreManager. 이 인스턴스는 플레이어의 점수와 UI를 관리합니다.var ScoreManager<private> : score_manager = score_manager{}레벨에서 점수 관리 장치로 설정할 수 있는 편집 가능
score_manager_device.score_manager클래스에서 사용할 장치입니다.@editable ScoreManagerDevice<public> : score_manager_device = score_manager_device{}public지정자가 있고, 각 픽업 레벨에서 플레이어가 얻을 수 있는 점수를 정의하는 편집 가능 integer 배열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 }