> For the complete documentation index, see [llms.txt](/llms.txt)


# Run an event

Set up an event, try it before and after its active period, then add announcements and reward messages.



Add a limited-time Forest festival quest. It costs 5 stamina and rewards 30 coins on completion. Deliver an announcement to the inbox, then send player A a message with 10 coins attached.

## 1. Add the event test panel

Stop Play Mode and uncheck **Adventure Social** on `Extensions`. Keep the login and adventure screens.


**Studio**

In Studio, add **Inbox** from **Add features**, save, and deploy from **Publish → Calculate server differences**. Then run **Update the Unity project**. In Unity, add **Message List Handler** to `Gs2`. Leave **Auto Subscribe** enabled and **Item Prefab** and **Content Parent** empty. This chapter's panel renders each message from the Handler's list.

Place <a href="/samples/adventure/en/extensions/studio/AdventureEventView.cs" download>AdventureEventView.cs</a> in `Assets/AdventureExtensions`, then add **Adventure Event View** to `Extensions`. Assign the new **Message List Handler** to **Messages**.


**SDK (Unity)**

Place <a href="/samples/adventure/en/extensions/sdk/AdventureEventView.cs" download>AdventureEventView.cs</a> in `Assets/AdventureExtensions`, then add **Adventure Event View** to `Extensions`. Assign the scene's `AdventureLogin` to **Login**.




Enter Play Mode and log in with account A. The right panel shows event time fields and an inbox.

The time fields specify how many minutes from now the event starts and ends. Enter `15` in the top field and `30` in the bottom field, then click **Generate start and end times**. Use the displayed times in the following settings.

## 2. Register the schedule and quest


**Studio**

### Create the schedule

Add a row under **Tables → Scheduling → Schedule**. For each start and end date cell, switch to **Local** and select the date and time shown in the test panel.

| Field | Value |
| --- | --- |
| ID | `festival` |
| Schedule type | `absolute` |
| Start | “Studio start time” in the test panel |
| End | “Studio end time” in the test panel |
| Repeat type | `always` |

### Create the quest

1. Under **Tables → Quests → QuestCollection**, add a row with ID `event`. Select `festival` for **Schedule**.
2. In **Quest**, add a row with ID `event_forest`, group `event`, and `displayName` set to “Forest festival”.
3. Add one `ConsumeStaminaByUserId` action to **Start costs**. Set `namespaceName = Energy`, `userId = #{userId}`, `staminaName = stamina`, and `consumeValue = 5`.
4. Add one `DepositByUserId` action to **Completion rewards**. Set `namespaceName = Currency`, `userId = #{userId}`, and `slot = 0`. Add one `depositTransactions` entry with `price = 0`, no `currency` value, and `count = 30`.
5. Save, deploy to the server from **Publish**, and update the Unity project.
6. Stop Play Mode. Change **Quest List Handler → Collection** on `Gs2` to `event`, then enter Play Mode and log in.


**SDK (Unity)**

### Create the schedule

1. Save the <a href="/samples/adventure/en/extensions/events.yaml" download>event settings template</a>.
2. Replace `START_AT` and `END_AT` with the two numbers under “SDK template” in the test panel. Do not put quotes around them.
3. In the same file, write an announcement including the start and end times in `festival-news` → `metadata`.
4. In the management console, open **Deploy → Stack list → Create stack**, name it `adventure-events`, select the edited file under **Template data**, and create it.

### Create the quest

In your `adventure-game` template, append the following group to `QuestMaster` → `Settings` → `groups`. Keep the existing `main` group.

```yaml
- name: event
  challengePeriodEventId: grn:gs2:{region}:{ownerId}:schedule:adventure-events:event:festival
  quests:
    - name: event_forest
      metadata: Forest festival
      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}]}'
```

Open **Deploy → adventure-game → Update stack**, select the edited file under **Template data**, and update.

In Unity, change `"main"` to `"event"` in two places: `QuestGroupModel("main")` in `AdventurePlayer.cs` → `LoadQuests()`, and `StartAsync("main", ...)` in `AdventurePlay.cs` → `BeginQuest()`. Enter Play Mode and log in.




Check that Forest festival appears in the list. After deployment, the new quest can take up to five minutes to appear. If it is missing, wait a little, then stop and restart Play Mode.

## 3. Play before, during, and after the event

Change the event period and try the following steps in order. Settings can take up to five minutes to take effect after deployment. At each step, wait five minutes after deploying, then restart Play Mode and log in.

1. Generate times with the start `15` minutes from now and the end `30` minutes from now. In Studio, update the start and end of `festival`; for the SDK, update `absoluteBegin` and `absoluteEnd` in the `adventure-events` template. Deploy. Try starting Forest festival: it is outside the active period and cannot start.
2. Generate new times with start `-5` and end `30`, update the same settings, and deploy. With at least 5 stamina, start and complete the quest. Stamina decreases by 5 and coins increase by 30.
3. Update and deploy with start `-30` and end `-15`. Try starting again: the event has ended, so the quest cannot start.

These settings control when a new adventure can be started. In step 2, complete the quest before changing the settings to the ended period.

## 4. Deliver an announcement to the inbox

Create the announcement as a global message delivered to players' inboxes. In the test panel, enter `-5` and `30` and generate new start and end times.


**Studio**

Update the `festival` schedule with the new start and end times.

1. Add a row under **Tables → Inbox → GlobalMessage**.
2. Set the ID to `festival-news` and **Message content** to “Forest festival: spend 5 stamina to enter and earn 30 coins on completion. Event period: …”, including the actual start and end times.
3. Open the **Delivery start** and **Delivery end** cells, switch to **Local**, and select the dates and times generated in the test panel.
4. Save, deploy to the server, and update the Unity project.


**SDK (Unity)**

The announcement is included in the `adventure-events` template. Change `festival`'s `absoluteBegin` and `absoluteEnd` to the numbers in the test panel, and update the dates in `festival-news`'s `metadata`. Apply them through **Deploy → adventure-events → Update stack**.




Wait five minutes after deployment, then click **Receive announcements and update inbox**. The announcement appears in the inbox.


**Studio**

The SDK's `ReceiveGlobalMessageAsync()` receives global messages, then the list is loaded into **Message List Handler**. The update button also fetches new messages sent from the console. After a message is opened, Handler change notifications update the display.

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


**SDK (Unity)**

The panel receives global messages before loading the list. This also fetches messages sent from the console. After opening a message, `SubscribeMessages()` notifications update the display.

```csharp
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. Send 10 coins to player A

1. In the management console's Tokyo region, open **Inbox**. Select `Inbox` for Studio or `adventure-inbox` for the SDK.
2. Under **User data**, enter player A's ID shown in the game.
3. From the message list, open **Send message**. In **Metadata**, enter “Thanks for joining! Here are 10 coins.”
4. Add one **Acquire action on read** and select **GS2-Money2 DepositByUserId**. Switch **Namespace name** to **Text** and enter `Currency` for Studio or `adventure-coin` for the SDK. Keep **User ID** as `#{userId}` and **Slot** as `0`.
5. Click **Deposit transactions → Add row**. Set **Purchase price** to `0` and **Currency amount** to `10`. Leave **Deposit date** off. A purchase price of 0 grants 10 free coins.

6. Click **Send**. Return to Unity, note the coin balance, and click **Receive announcements and update inbox**.
7. On the “Thanks for joining!” message, click **Open and claim reward**. Once it finishes, check that the adventure panel on the left shows 10 more coins.
8. Check that the same message's button now says **Opened** and cannot grant the reward again.


**Studio**

Each message in the list is a Binder. Calling `Read()` waits until both opening the message and claiming its reward are complete. The view does not need to wait for a transaction or reload after opening.

```csharp
private async UniTask Read(IActionableMessageBinder item)
{
    await item.Read();
    message = "Message opened";
}
```


**SDK (Unity)**

Use `ReadAsync()` to open the message and claim its reward, then wait for the returned transaction to complete. Message change notifications update the opened status.

```csharp
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);
}
```




[Next: Samples and reference]()



