이벤트 열기

이벤트를 설정하고 개최 전후의 동작을 확인한 뒤 공지와 보상 지급을 추가합니다.

기간 한정 ‘숲 축제’를 추가합니다. 스태미나 5를 사용하고 클리어하면 30코인을 받는 모험입니다. 받은 편지함으로 공지를 보내고, 마지막으로 플레이어 A에게 10코인이 첨부된 메시지를 보냅니다.

1. 이벤트 확인 화면 추가하기

재생을 멈추고 Extensions의 Adventure Social 체크를 해제합니다. 로그인과 모험 화면은 그대로 사용합니다.

Studio의 Add features 에서 Inbox 를 추가하고 저장한 뒤 Publish → Calculate server differences 에서 배포합니다. 이어서 Update the Unity project 를 실행합니다. Unity의 Gs2에 Message List Handler 를 추가합니다. Auto Subscribe 는 켜 두고 Item Prefab 과 Content Parent 는 비워 둡니다. 이 장의 확인 화면이 Handler의 목록으로 메시지를 표시합니다.

AdventureEventView.cs를 Assets/AdventureExtensions에 넣고 Extensions에 Adventure Event View 를 추가합니다. Messages 에 방금 추가한 Message List Handler 를 할당합니다.

AdventureEventView.cs를 Assets/AdventureExtensions에 넣고 Extensions에 Adventure Event View 를 추가합니다. Login 에 씬의 AdventureLogin을 할당합니다.

계정 A로 재생하고 로그인하면 오른쪽에 개최 시각 입력란과 받은 편지함이 나타납니다.

개최 시각 입력란에는 지금부터 몇 분 뒤에 시작하고 종료할지 지정합니다. 위에 15, 아래에 30을 입력하고 시작·종료 시각 만들기 를 누릅니다. 표시된 시각을 다음 설정에 사용합니다.

2. 개최 기간과 모험 등록하기

개최 기간 만들기

Tables → Scheduling → Schedule 에서 행을 추가합니다. 시작·종료 일시 셀을 각각 열고 Local 로 전환한 뒤 확인 화면에 표시된 날짜와 시각을 선택합니다.

항목값
IDfestival
일정 방식absolute
시작 일시확인 화면의 ‘Studio 시작 시각’
종료 일시확인 화면의 ‘Studio 종료 시각’
반복 방식always

모험 만들기

  1. Tables → Quests → QuestCollection 에 ID가 event인 행을 추가합니다. Schedule 은 festival을 선택합니다.
  2. Quest 에 ID event_forest, 그룹 event, displayName이 ‘숲 축제’인 행을 추가합니다.
  3. Start costs 에 ConsumeStaminaByUserId를 하나 추가합니다. namespaceName = Energy, userId = #{userId}, staminaName = stamina, consumeValue = 5를 입력합니다.
  4. Completion rewards 에 DepositByUserId를 하나 추가합니다. namespaceName = Currency, userId = #{userId}, slot = 0으로 설정합니다. depositTransactions에 항목을 하나 추가하고 price = 0, currency는 값 없음, count = 30으로 설정합니다.
  5. 저장한 뒤 Publish 에서 서버에 배포하고 Unity 프로젝트를 업데이트합니다.
  6. 재생을 멈추고 Gs2의 Quest List Handler → Collection 을 event로 바꿉니다. 다시 재생하고 로그인합니다.

개최 기간 만들기

  1. 이벤트 설정 템플릿을 저장합니다.
  2. START_AT과 END_AT을 확인 화면의 ‘SDK 템플릿’에 표시된 두 숫자로 바꿉니다. 숫자를 따옴표로 감싸지 않습니다.
  3. 같은 파일의 festival-news → metadata에 시작·종료 시각을 포함한 공지문을 작성합니다.
  4. 관리 콘솔의 Deploy → Stack list → Create stack 에서 이름을 adventure-events로 지정하고 Template data 에서 수정한 파일을 선택해 생성합니다.

모험 만들기

지금까지 수정한 adventure-game 템플릿에서 QuestMaster → Settings → groups 끝에 다음 그룹을 추가합니다. 기존 main 그룹은 그대로 둡니다.

- name: event
  challengePeriodEventId: grn:gs2:{region}:{ownerId}:schedule:adventure-events:event:festival
  quests:
    - name: event_forest
      metadata: 숲 축제
      consumeActions:
        - action: Gs2Stamina:ConsumeStaminaByUserId
          request: '{"namespaceName":"adventure-stamina","userId":"#{userId}","staminaName":"stamina","consumeValue":5}'
      contents:
        - weight: 1
          completeAcquireActions:
            - action: Gs2Money2:DepositByUserId
              request: '{"namespaceName":"adventure-coin","userId":"#{userId}","slot":0,"depositTransactions":[{"price":0,"currency":"","count":30}]}'

Deploy → adventure-game → Update stack 에서 Template data 에 수정한 파일을 선택해 업데이트합니다.

Unity에서 AdventurePlayer.cs의 LoadQuests()에 있는 QuestGroupModel("main")과 AdventurePlay.cs의 BeginQuest()에 있는 StartAsync("main", ...) 두 곳의 "main"을 "event"로 바꿉니다. 재생하고 로그인합니다.

목록에 ‘숲 축제’가 있는지 확인합니다. 배포 후 모험 추가가 적용되기까지 최대 5분이 걸릴 수 있습니다. 아직 보이지 않으면 잠시 기다린 뒤 Unity 재생을 다시 시작합니다.

3. 개최 전·중·후에 플레이하기

개최 기간을 바꾸며 다음 순서대로 확인합니다. 배포 후 설정 적용까지 최대 5분이 걸릴 수 있으므로 각 단계에서 배포 후 5분을 기다린 뒤 Unity 재생을 다시 시작하고 로그인합니다.

  1. 확인 화면에서 시작을 15분 뒤, 종료를 30분 뒤로 지정해 시각을 만듭니다. Studio는 festival의 시작·종료 일시를, SDK는 adventure-events 템플릿의 absoluteBegin과 absoluteEnd를 이 값으로 업데이트하고 배포합니다. ‘숲 축제’를 시작하면 개최 기간 밖이라 시작할 수 없습니다.
  2. 시작 -5, 종료 30으로 시각을 다시 만들고 같은 설정을 업데이트해 배포합니다. 스태미나가 5 이상인지 확인하고 시작·클리어합니다. 스태미나가 5 줄고 코인이 30 늘어납니다.
  3. 시작 -30, 종료 -15로 업데이트하고 배포합니다. 다시 시작하면 개최 기간 밖이라 시작할 수 없습니다.

이 설정은 새 모험을 시작할 수 있는 기간을 정합니다. 2번에서는 클리어한 뒤 종료 후 설정으로 변경합니다.

4. 받은 편지함에 공지 보내기

이 예제의 공지는 받은 편지함으로 전달되는 전체 메시지로 만듭니다. 확인 화면의 분 값을 -5와 30으로 바꾸고 시작·종료 시각을 다시 만듭니다.

festival 일정의 시작·종료 일시를 새로 만든 시각으로 바꿉니다.

  1. Tables → Inbox → GlobalMessage 에 행을 추가합니다.
  2. ID를 festival-news로 지정합니다. Message content 에 ‘숲 축제: 스태미나 5로 도전하고 클리어하면 30코인. 개최 기간: …’을 입력하고 실제 시작·종료 시각을 적습니다.
  3. Delivery start 와 Delivery end 셀을 각각 열고 Local 로 전환해 확인 화면에서 만든 날짜와 시각을 선택합니다.
  4. 저장하고 서버에 배포한 뒤 Unity 프로젝트를 업데이트합니다.

공지는 adventure-events 템플릿에 포함되어 있습니다. festival의 absoluteBegin과 absoluteEnd를 확인 화면의 숫자로 바꾸고 festival-news의 metadata에 새 개최 시각을 적습니다. Deploy → adventure-events → Update stack 에서 반영합니다.

배포 후 5분을 기다리고 공지 수신 및 목록 갱신 을 누릅니다. 받은 편지함에 본문이 표시됩니다.

전체 메시지는 SDK의 ReceiveGlobalMessageAsync()로 수신한 뒤 Message List Handler 에 목록을 불러옵니다. 이 갱신 버튼은 콘솔에서 새로 보낸 메시지도 가져옵니다. 개봉 후에는 Handler의 변경 알림으로 화면이 갱신됩니다.

var user = Client.Inbox.Namespace(Inbox).Me(Session);
await user.ReceiveGlobalMessageAsync();
user.InvalidateMessages();
await messages.ReloadAsync();

확인 화면에서는 전체 메시지를 수신한 뒤 목록을 불러옵니다. 콘솔에서 보낸 메시지도 여기서 가져옵니다. 개봉 후에는 SubscribeMessages()의 변경 알림으로 화면을 갱신합니다.

var user = Client.Inbox.Namespace(Inbox).Me(Session);
await user.ReceiveGlobalMessageAsync();
user.InvalidateMessages();
var items = new List<EzMessage>();
await foreach (var item in user.MessagesAsync())
    if (item != null) items.Add(item);
UpdateMessages(items.ToArray());
var id = user.SubscribeMessages(UpdateMessages);

5. 플레이어 A에게 10코인 보내기

  1. 관리 콘솔의 Tokyo 리전에서 Inbox 를 엽니다. Studio는 Inbox, SDK는 adventure-inbox를 선택합니다.

  2. User data 에 게임 화면에 표시된 A의 플레이어 ID를 입력합니다.

  3. 메시지 목록에서 Send message 를 엽니다. Metadata 에 ‘참여해 주셔서 감사합니다! 10코인을 보내드립니다.’를 입력합니다.

  4. Acquire action on read 를 하나 추가하고 GS2-Money2 DepositByUserId 를 선택합니다. Namespace name 을 Text 로 전환하고 Studio는 Currency, SDK는 adventure-coin을 입력합니다. User ID 는 #{userId}, Slot 은 0을 그대로 사용합니다.

  5. Deposit transactions → Add row 를 누르고 Purchase price 를 0, Currency amount 를 10으로 설정합니다. Deposit date 는 끈 상태로 둡니다. 구매 가격이 0이므로 무상 코인 10개를 지급하는 설정입니다.

  6. Send 를 누릅니다. Unity로 돌아가 코인 잔액을 확인하고 공지 수신 및 목록 갱신 을 누릅니다.

  7. 도착한 ‘참여해 주셔서 감사합니다!’ 메시지에서 개봉하고 보상 받기 를 누릅니다. 완료 후 왼쪽 모험 화면의 코인이 10개 늘었는지 확인합니다.

  8. 같은 메시지의 버튼이 개봉 완료 로 바뀌고 다시 받을 수 없는지 확인합니다.

목록의 각 메시지는 Binder입니다. Read()를 호출하면 개봉과 보상 수령이 끝날 때까지 기다립니다. 화면에서 트랜잭션을 기다리거나 개봉 후 다시 불러올 필요는 없습니다.

private async UniTask Read(IActionableMessageBinder item)
{
    await item.Read();
    message = "개봉했습니다";
}

ReadAsync()로 메시지를 개봉하고 보상을 받은 뒤 반환된 트랜잭션의 완료를 기다립니다. 개봉 상태 표시는 메시지 변경 알림으로 갱신됩니다.

private async UniTask Read(string name, string requestId)
{
    var transaction = await Client.Inbox.Namespace(Inbox).Me(Session)
        .Message(name).ReadAsync(speculativeExecute: false, duplicationAvoider: requestId);
    if (transaction != null) await transaction.WaitAsync(all: true);
}

다음: 샘플과 참고 자료