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


# イベントを開催する

イベントを設定し、開催前後の動作を試してから、お知らせと報酬配布を追加します。



期間限定の「森のお祭り」を追加します。スタミナを5使い、クリアすると30コインをもらえる冒険です。お知らせを受信箱に届け、最後にプレイヤーAへ10コイン付きのメッセージを送ります。

## 1. イベント用の確認画面を追加する

Unity の再生を止め、`Extensions` の **Adventure Social** のチェックを外します。ログインと冒険の画面はそのまま使います。


**Studio**

Studio の **機能を追加** で **お知らせ・受信箱** を追加し、保存して **反映 → サーバとの差分を確認** からデプロイします。続いて **Unity プロジェクトを更新する** を実行します。Unity の `Gs2` に **Message List Handler** を追加します。**Auto Subscribe** は有効のままにし、**Item Prefab** と **Content Parent** は空欄にします。この章の確認画面が、Handler の一覧を使って各メッセージを描画します。

<a href="/samples/adventure/extensions/studio/AdventureEventView.cs" download>AdventureEventView.cs</a> を `Assets/AdventureExtensions` に入れ、`Extensions` に **Adventure Event View** を追加します。**Messages** に、追加した **Message List Handler** を割り当てます。


**SDK（Unity）**

<a href="/samples/adventure/extensions/sdk/AdventureEventView.cs" download>AdventureEventView.cs</a> を `Assets/AdventureExtensions` に入れ、`Extensions` に **Adventure Event View** を追加します。**Login** に、シーン内の `AdventureLogin` を割り当てます。




アカウントAで再生・ログインすると、右側に開催日時の入力欄と受信箱が表示されます。

開催日時の入力欄は、現在から何分後に開始・終了するかを指定します。まずは上に `15`、下に `30` を入れて **開始・終了日時を作る** を押します。表示された日時を、次の設定に使います。

## 2. 開催期間と冒険を登録する


**Studio**

### 開催期間を作る

**表 → スケジュール基盤 → スケジュール（Schedule）** で行を追加します。開始日時と終了日時は、それぞれセルを開いて **ローカル** に切り替え、確認画面に表示された日付と時刻を選びます。

| 項目 | 値 |
| --- | --- |
| ID | `festival` |
| スケジュール方式 | `absolute` |
| 開始日時 | 確認画面の「Studio の開始日時」 |
| 終了日時 | 確認画面の「Studio の終了日時」 |
| 繰り返し方式 | `always` |

### 冒険を作る

1. **表 → クエスト → クエストグループ（QuestCollection）** に、ID `event` の行を追加します。**開催スケジュール** は `festival` を選びます。
2. **クエスト（Quest）** に、ID `event_forest`、グループ `event`、`displayName` が「森のお祭り」の行を追加します。
3. **開始時消費** に `ConsumeStaminaByUserId` を1件追加します。`namespaceName = Energy`、`userId = #{userId}`、`staminaName = stamina`、`consumeValue = 5` と入力します。
4. **通常クリア報酬** に `DepositByUserId` を1件追加します。`namespaceName = Currency`、`userId = #{userId}`、`slot = 0` とし、`depositTransactions` を1件追加して `price = 0`、`currency` は値なし、`count = 30` と入力します。
5. 保存し、**反映** からサーバーへデプロイして Unity プロジェクトを更新します。
6. Unity の再生を止め、`Gs2` の **Quest List Handler → Collection** を `event` に変えます。再生し、ログインします。


**SDK（Unity）**

### 開催期間を作る

1. <a href="/samples/adventure/extensions/events.yaml" download>イベントの設定テンプレート</a>を保存します。
2. `START_AT` と `END_AT` を、確認画面の「SDK テンプレート」の二つの数値に置き換えます。数値は引用符で囲みません。
3. 同じファイルの `festival-news` の `metadata` に、開始・終了日時を含むお知らせ文を書きます。
4. マネージメントコンソールの **Deploy → スタックリスト → スタックを新規作成** で、名前を `adventure-events` とし、**テンプレートデータ**で編集したファイルを選び、作成します。

### 冒険を作る

編集してきた `adventure-game` のテンプレートで、`QuestMaster` の `Settings` にある `groups` の末尾へ、次のグループを追加します。既存の `main` グループは残します。

```yaml
- 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 → スタックを更新** で、**テンプレートデータ**で編集したファイルを選び、更新します。

Unity では、`AdventurePlayer.cs` の `LoadQuests()` にある `QuestGroupModel("main")` と、`AdventurePlay.cs` の `BeginQuest()` にある `StartAsync("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` にして、開始・終了日時を作り直します。


**Studio**

スケジュール `festival` の開始・終了日時を、作り直した日時に変更します。

1. **表 → お知らせ・受信箱 → 全体メッセージ（GlobalMessage）** に行を追加します。
2. ID を `festival-news`、**メッセージ内容** を「森のお祭り：スタミナ5で挑戦し、クリアすると30コイン。開催期間：…」とし、実際の開始・終了日時を書きます。
3. **配信開始日時** と**配信終了日時** は、それぞれセルを開いて **ローカル** に切り替え、確認画面で作った日付と時刻を選びます。
4. 保存し、サーバーへのデプロイと Unity プロジェクトの更新を行います。


**SDK（Unity）**

お知らせは `adventure-events` のテンプレートに含まれています。`festival` の `absoluteBegin` と `absoluteEnd` を確認画面の数値に変更し、`festival-news` の `metadata` に新しい開催日時を書きます。**Deploy → adventure-events → スタックを更新** で反映します。




デプロイしてから5分待ち、**お知らせを受信して一覧を更新** を押してください。本文が受信箱に表示されます。


**Studio**

全体メッセージの受信には SDK の `ReceiveGlobalMessageAsync()` を使い、受信後の一覧を **Message List Handler** に読み込ませます。この更新ボタンは、コンソールから新しく送ったメッセージも取り込むためのものです。開封後の表示は Handler の変更通知で更新されます。

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


**SDK（Unity）**

確認画面では、全体メッセージを受信してから一覧を読み込みます。コンソールから届いたメッセージもここで取得します。開封後の表示は `SubscribeMessages()` の変更通知で更新します。

```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. プレイヤーAに10コインを送る

1. マネージメントコンソールで、東京リージョンの **Inbox** を開きます。Studio は `Inbox`、SDK は `adventure-inbox` を選びます。
2. **ユーザーデータ** で、ゲーム画面に表示されているAのプレイヤーIDを入力します。
3. メッセージ一覧から **メッセージの送信** を開きます。**メタデータ** に「参加ありがとう！ 10コインをお届けします。」と入力します。
4. **開封時入手アクション**を1件追加し、アクションに **GS2-Money2 の DepositByUserId** を選びます。**ネームスペース名**は **Text** に切り替え、Studio は `Currency`、SDK は `adventure-coin` を入力します。**ユーザーID**は `#{userId}`、**スロット番号**は `0` のまま使います。
5. **入金トランザクションリスト → 行を追加**を押し、**購入価格**を `0`、**課金通貨の数量**を `10` にします。**入金日時**はオフのままです。購入価格が0なので、無償コイン10枚を付与する設定になります。

6. **送信** を押します。Unity に戻り、コイン残高を控えてから **お知らせを受信して一覧を更新** を押します。
7. 届いた「参加ありがとう！」の **開封して報酬を受け取る** を押します。完了後、左側の冒険画面で10コイン増えたことを確かめます。
8. 同じメッセージのボタンが **開封済み** になり、もう一度受け取れないことを確かめます。


**Studio**

一覧の各メッセージは Binder です。`Read()` を呼ぶと、開封と報酬の受け取りが完了するまで待ちます。画面側にトランザクション待機や開封後の再読み込みは要りません。

```csharp
private async UniTask Read(IActionableMessageBinder item)
{
    await item.Read();
    message = "開封しました";
}
```


**SDK（Unity）**

開封と報酬の受け取りには `ReadAsync()` を使います。返されたトランザクションの完了を待ちます。開封済みの表示は、メッセージの変更通知で更新されます。

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




[次へ：サンプルとリファレンス]()


