UEFN에서만 사용할 수 있는 이 템플릿에는 퍼시스턴스와 오프라인 진행 기능을 지원하는 작은 공장 스타일의 게임이 포함되어 있습니다.
템플릿 속의 튜토리얼을 따라가려면 포트나이트 언리얼 에디터(Unreal Editor for Fortnite, UEFN)에 대한 기본 지식이 있어야 하며, Verse 파일을 열 수 있어야 합니다. 다른 요구 사항은 없습니다. 템플릿 자체에서 튜토리얼 지침을 제공합니다.
레고® 템플릿 산타의 장난감 공장(Santa's Toy Factory)에 오신 것을 환영합니다. 이 템플릿은 아래와 같은 두 가지 기능을 사용해 흥미로운 게임플레이 루프로 플레이어 리텐션을 높여줍니다.
퍼시스턴스: 게임 세션 간 플레이어 데이터를 저장합니다.
오프라인 진행: 플레이어가 게임 중이 아닐 때에도 공장 컨테이너에 자리가 있는 한 공장에서는 계속 장난감이 생산되고, 플레이어가 있든 없든 사탕 막대 숲은 계속해서 자라납니다.
위의 두 가지 기능을 모두 사용하면 매일 적용되는 메커니즘을 만들어 플레이어가 계속 섬을 다시 찾도록 유도할 수도 있습니다. 템플릿을 사용해 여러분의 아늑한 홀리데이 섬에 이러한 메커니즘을 구현해 보세요!
템플릿에는 다음과 같은 세 개의 짧은 튜토리얼이 포함되어 있습니다.
초급: Verse에서 사탕 막대 숲의 성장 시간을 변경하는 방법을 보여줍니다.
중급: Verse에서 변수를 편집하는 방법을 안내합니다.
고급: Verse 코드를 수정하고 추가해 봅니다.
프로젝트에 포함된 각 튜토리얼은 Verse를 사용해 해당 프로젝트에 사용된 메커니즘을 구현하는 방법을 설명합니다.
템플릿은 크게 세 부분으로 나뉩니다.
플레이하기(Play): 먼저 5~10분 동안 게임을 플레이해 보며 작동 방식을 익힙니다.
생성하기(Create): 다음으로, 튜토리얼의 과제를 따라 세 가지 모드를 만들어 봅니다.
살펴보기(Explore): 마지막으로, 작성된 코드를 분석하고 살펴보면서 작동 방식을 이해한 다음 자신만의 홀리데이 게임을 직접 제작해 봅니다.
플레이하기
UEFN에서 템플릿을 로드합니다. 이는 다른 레고 템플릿과 함께 있습니다. 게임을 플레이해 봅니다.
게임 내에서 퀘스트를 따라 북극꽁꽁 경(Sir Pawlar)에게 다가가면 해야 할 일을 설명해 줍니다.
게임의 지침을 따릅니다.
어느 지점에 다다르면 튜토리얼에서 게임 종료를 요청합니다. Esc를 누르고 게임 종료(End Game)를 선택합니다.
2분간 대기합니다.
2분이 지나면 Esc를 다시 누르고 게임 시작(Start Game)을 선택합니다.
이상하다고 생각할 수 있지만, 이는 아주 중요한 점을 보여주기 위한 것입니다. 바로 이 게임은 플레이 중이 아닐 때에도 진행된다는 것입니다! 공장은 멈추지 않고 돌아가고 사탕 막대 숲도 계속해서 자라납니다.
바로 이 기능이 플레이어가 쉬는 사이에 자란 작물을 수확하거나 그동안 생산된 자원을 수거하러 다시 게임으로 돌아오도록 유도하는 중요한 메커니즘입니다.
게임으로 돌아오면 그 사이에 게임에서 무엇이 생산되었는지 볼 수 있습니다.
이 과정은 factory_manager.verse 파일을 통해 이루어집니다. 이 파일은 퍼시스턴스 데이터 및 리얼타임 시계(Real Time Clock) 장치를 사용해 플레이어가 없는 동안 경과한 시간을 측정합니다. 그런 다음 그 시간 동안 공장에서 만들어졌어야 할 생산품의 양을 계산합니다.
두 번째 공장 빌드를 생산하고 나면 UEFN으로 돌아가라는 메시지가 표시됩니다.
첫 번째 튜토리얼이 완료되었습니다! 이제 창의적인 과제로 넘어갈 차례입니다.
제작
본격적인 재미가 시작되는 단계죠! 세 가지 과제가 여러분을 기다리고 있습니다.
첫 번째로 신입생 파닥이(Freshman Flapjack)를 찾습니다. 파닥이는 세 개의 노란색 사각형 중 하나에서 여러분을 기다리고 있습니다.
초급 과제: 사탕 막대 재성장 시간 수정하기
첫 번째 과제는 간단합니다. 사탕 막대 밭의 재성장 시간을 변경하는 것입니다. 과제를 완료하면 몇 가지 값만 수정해도 게임을 크게 바꿀 수 있다는 사실을 알 수 있습니다.
신입생 파닥이 옆에는 Verse로 제작된 사탕 막대 장치가 있습니다.
장치를 선택하고, 디테일(Details) 패널을 선택한 상태에서 과제를 진행해야 합니다.
CandyCaneRegrowthTime
파라미터를 변경합니다. 파라미터 값이 게임플레이에 어떤 영향을 미치는지 실험해 보세요.
중급 과제: 업그레이드 가격 수정하기
두 번째 과제에서는 Verse 코드 자체를 살펴봅니다.
이번 과제 역시 공장 업그레이드 가격만 변경해도 게임의 속도와 느낌이 얼마나 달라지는지 직접 확인할 수 있습니다.
Verse 익스플로러에서 upgrade_config.verse 파일을 엽니다.
다양한 공장 엘리먼트의 업그레이드 가격을 모두 볼 수 있습니다. 첫 번째 배치는 공장 벨트의 가격입니다. 공장에는 4개의 벨트가 있으며 가격표에도 4개의 열이 있습니다. 표의 각 행에는 벨트를 해당 레벨로 업그레이드하는 데 필요한 가격이 표시되어 있습니다.
Verse# This file contains the data used to configure the factory in the game. # This includes upgrade prices, max levels, production speeds, storage capacities and more. # It also contains functions for getting all this data. using { /Verse.org/Simulation } using { Persistence } # Blubberchops: "Looks like this is the place to modify the upgrade prices for belts."
두턱이의 조언에 따라 벨트 업그레이드 가격을 낮춰 보겠습니다. 가격을 올려 게임의 진행 속도를 늦추면 어떻게 되는지 실험해 볼 수도 있습니다.
준비가 되면 Verse 코드를 빌드하고 Verse 변경 사항을 푸시해 게임이 어떻게 바뀌었는지 살펴봅니다.
이 단계의 과제에 대한 자세한 내용은 Verse 프로그램 처음으로 수정하고 실행하기를 참고하세요.
변경사항을 푸시할 때마다 공장의 진행 상황이 초기화됩니다.
전문가 과제: 일일 선물
세 번째이자 마지막 과제는 철푸덕 교수(Professor Flopkins) 옆에 있는 일일 선물 작업입니다.
이 과제를 수행하려면 선물을 마지막으로 개봉한 시점을 저장할 퍼시스턴스 데이터를 추가해야 합니다. Verse로 제작된 일일 선물 장치의 로직도 수정해야 합니다.
Verse의 퍼시스턴스 데이터 작업에 대한 자세한 내용은 퍼시스턴스 데이터 사용하기를 참고하세요.
과제 수행에 도움이 필요하다면 아래의 일일 선물 장치 섹션을 참고하세요!
Verse 익스플로러에서 player_info.verse 파일을 엽니다.
파일 상단 근처에서 철푸덕 교수의 코멘트를 찾습니다.
선물을 마지막으로 개봉한 시점을 저장할 수 있도록
player_info
클래스에date_and_time
배열 필드를 추가합니다.MakePlayerInfo
생성자의 필드 값도 설정되어 있어야 합니다.Verse# This file defines player_info, the collection of persistable information stored for each player. # It also contains functions for creating, updating and returning information about a player. using { /Verse.org/Simulation } using { Config } using { Time } # Maps each player to their persisted information. var PlayerInfoMap:weak_map(player, player_info) = map{}
새로 추가된 필드를 가져오고 설정하기 위한 함수를 수정합니다. 이번에는 파일 하단에 있는 철푸덕 교수의 코멘트를 살펴봅니다.
함수가 올바르게 작동하도록 누락된 줄을 채웁니다. 파일에 있는 다른 함수를 참고해도 좋습니다.
Verse# This file defines player_info, the collection of persistable information stored for each player. # It also contains functions for creating, updating and returning information about a player. using { /Verse.org/Simulation } using { Config } using { Time } # Maps each player to their persisted information. var PlayerInfoMap:weak_map(player, player_info) = map{}
퍼시스턴스 데이터를 위한 새로운 함수 기능이 준비된 상태에서 daily_gift.verse 파일을 열고 선물이 하루에 한 번만 나타나게 하는 로직을 변경합니다.
로직에는 다음과 같은 중요한 두 가지 요소가 빠져 있습니다.
선물을 개봉한 현재 시간을 저장하는 기능
마지막으로 선물을 개봉한 뒤 날짜가 바뀌었는지 확인하는 기능
철푸덕 교수의 코멘트를 따라 빠진 코드를 추가해 보세요.
Verse# When the gift is opened (harvested), give the selected player gold. OnHarvesting(Agent:agent):void= # Hide gift. set Opened = true PropManipulator.HideProps() # Show effect. spawn: ShowGiftEffect()
Verse# Succeeds if the current date is different from the opening time. IsDateRolledOver()<decides><transacts>:void= # Get the current date. Now := RealTime.GetDateAndTime() # Professor Flopkins: "Hmm, the code to determine if the date has rolled over is also missing." # "Let's see.. first we'll get the selected player." # "Look in the OnHarvesting function to see how to do that."
이제 솔루션을 테스트해 볼 준비가 되었습니다! Verse 코드를 빌드하고 Verse 변경 사항을 푸시한 뒤 여러분의 세션에서 실행해 보세요.
서브제로의 디버그 버튼을 시간을 빠르게 보내기 위한 단축키로 사용하여 날짜가 바뀌었을 때 선물이 재생성되는지 미리 테스트할 수 있습니다.
살펴보기
과제를 완료했으니 이 템플릿에 사용된 다른 장치들을 살펴볼 차례입니다.
리얼타임 시계 장치
리얼타임 시계 장치는 협정 세계시(Coordinated Universal Time, UTC)를 기준으로 현재 시간을 알려주며, 시곗바늘 애니메이션이 적용되어 있습니다.
이 장치를 사용하면 매일 특정 시간에 발생해야 하는 이벤트를 구현하거나, 시간이 얼마나 경과했나를 추적할 수 있습니다.
장치에는 현재 시간을 오프셋할 수 있는 테스트 기능이 내장되어 있습니다. real_time_device.verse 파일과 date_and_time.verse 파일, time_interval.verse 파일을 확인해 보세요.
사탕 막대 밭 장치
Verse로 제작된 사탕 막대 밭 장치는 사탕 막대를 수확할 수 있는 밭을 추적합니다. 수확한 자원을 제공하고, 시간이 지나면 사탕 막대가 다시 자라게 하는 기능도 있습니다. 다양한 자원을 다시 기르는 데 활용할 수 있습니다. candy_cane_field.verse 파일을 체크아웃합니다.
퍼시스턴스 모듈
이 모듈은 각 플레이어와 연관된 모든 퍼시스턴스 데이터를 보유하고 있습니다. 메인 클래스는 player_info.verse 파일의 player_info
클래스입니다.
데이터를 읽고 조작하는 모든 함수도 이 파일에 포함되어 있습니다. 플레이어별로 저장된 데이터를 정의하는 모듈의 다른 클래스도 확인해 보세요. 필요에 따라 클래스를 수정할 수도 있고 데이터를 추가할 수도 있습니다.
# This file defines player_info, the collection of persistable information stored for each player.
# It also contains functions for creating, updating and returning information about a player.
using { /Verse.org/Simulation }
using { Config }
using { Time }
# Maps each player to their persisted information.
var PlayerInfoMap:weak_map(player, player_info) = map{}
# This tracks all persistable information for a player.
player_info := class<final><persistable>:
# The version of the current player info.
일일 선물 장치
이 장치는 일일 선물을 생성합니다. 단, 장치가 작동할 때 얘기죠.
여기에는 Verse로 제작된 일일 선물 장치를 충분히 활용하는 데 도움이 되는, 전문가 과제에 대한 솔루션이 나와 있습니다. 다양한 일일 이벤트와 보상을 구현하는 데 사용할 수 있습니다.
다음과 같이 player_info.verse 파일에서
player_info
클래스에 필요한 데이터를 추가하고MakePlayerInfo
생성자를 수정합니다.Verse# This tracks all persistable information for a player. player_info := class<final><persistable>: # The version of the current player info. Version:int = 0 # Latest harvest times of all candy canes. CandyCaneHarvestTimes:[]date_and_time = array{date_and_time{}, date_and_time{}, date_and_time{}, date_and_time{}, date_and_time{}, date_and_time{}, date_and_time{}, date_and_time{}, date_and_time{}, date_and_time{}} # The amount of gold the player has.
다음과 같이
SetGiftOpeningTime
및GetGiftOpeningTime
함수를 완성합니다.Verse# Sets the gift opening time for the player. SetGiftOpeningTime<public>(Player:player, GiftOpeningTime:date_and_time)<decides><transacts>:void= CheckPlayerInfoForPlayer[Player] SourceInfo := PlayerInfoMap[Player] set PlayerInfoMap[Player] = player_info: MakePlayerInfo<constructor>(SourceInfo) GiftOpeningTime := GiftOpeningTime # Gets the gift opening time for the player.
daily_gift.verse 파일의
daily_gift
클래스를 살펴보겠습니다. 먼저 아래와 같이 선물을 개봉할 때 현재 시간을 저장하는 기능을 완성합니다.Verse# When the gift is opened (harvested), give the selected player gold. OnHarvesting(Agent:agent):void= # Hide gift. set Opened = true PropManipulator.HideProps() # Show effect. spawn: ShowGiftEffect()
다음과 같이
IsDateRolledOver
함수를 구현합니다.Verse# Succeeds if the current date is different from the opening time. IsDateRolledOver()<decides><transacts>:void= # Get the current date. Now := RealTime.GetDateAndTime() SelectedPlayer := MaybeSelectedPlayer? GiftOpeningTime := GetGiftOpeningTime[SelectedPlayer] Now.Years <> GiftOpeningTime.Years or Now.Months <> GiftOpeningTime.Months or Now.Days <> GiftOpeningTime.Days
공장 관리 장치
Verse로 제작된 공장 관리 장치는 공장을 초기화하고 가동하며, 플레이어가 없는 동안 만들어진 생산품의 양을 계산합니다.
여러 공장 벨트가 하나의 공장 저장소를 공유하기 때문에 이 계산은 복잡해질 수 있습니다. 간단한 구성의 경우 마지막 생산 이후 경과한 시간을 계산한 뒤 이를 생산 속도로 나누어 생산품의 수를 계산할 수 있습니다.