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


# プレイヤー同士をつなぐ

二つのアカウントで、プロフィール、ランキング、フレンド、ギルドを試します。



ここまで使ったプレイヤーを A として、もう一人 B を作ります。二人の名前を表示し、スコアを競い、フレンドやギルドでつながれるようにします。

## 1. プロフィール・ランキング・ギルドの設定を追加する


**Studio**

**機能を追加** で「フレンド・プロフィール」「ランキング」「ギルド」を追加します。プロフィールとフレンドには、表への設定追加はありません。

**表 → ランキング → ランキング（Ranking）** で行を追加し、次を入力します。

| 項目 | 値 |
| --- | --- |
| ID | `adventure` |
| 順位方向 | `desc`（スコアが高い順） |
| スコアを合算 | オフ |
| 最小スコア | `0` |
| 最大スコア | `1000000` |
| 開催スケジュール | 空欄 |

ランキング報酬の行は追加しません。今回は最後に送ったスコアを使うランキングを作ります。

続いて **表 → ギルド → ギルド権限（GuildRole）** に、次の2行を追加します。リンク先の JSON 全文を、それぞれの **権限ポリシー** セルへ貼り付けます。

| ID | 権限ポリシー |
| --- | --- |
| `master` | <a href="/samples/adventure/extensions/guild-master-policy.json" download>マスター用ポリシー</a>。ギルドの設定変更と申請の承認を許可します |
| `member` | <a href="/samples/adventure/extensions/guild-member-policy.json" download>一般メンバー用ポリシー</a>。ギルドとして管理操作する権限は与えません |

**ギルド種別（Guild）** に行を追加し、次を入力します。

| 項目 | 値 |
| --- | --- |
| ID | `adventure` |
| 初期定員・最大定員 | どちらも `10` |
| 再参加待機時間 | `0` |
| 同時所属上限・同時マスター上限 | どちらも `1` |
| マスターロール | `master` |
| 一般メンバーロール | `member` |
| マスター不在判定期間 | 空欄 |

**反映 → サーバとの差分を確認** からデプロイし、続けて **Unity プロジェクトを更新する** を押します。


**SDK（Unity）**

<a href="/samples/adventure/extensions/social.json" download>交流機能のテンプレート</a>をダウンロードします。マネージメントコンソールの東京リージョンで **Deploy → スタックリスト → スタックを新規作成** を開きます。名前を `adventure-social` とし、**テンプレートデータ**でダウンロードしたファイルを選び、作成します。

| 機能 | サービス / ネームスペース | 設定 |
| --- | --- | --- |
| プロフィールとフレンド | Friend / `adventure-friend` | プレイヤーごとに名前とフレンドを保存 |
| ランキング | Ranking2 / `adventure-ranking` | `adventure`。スコアが高い順、合算せず最後に送った値で更新 |
| ギルド | Guild / `adventure-guild` | 種別 `adventure`。定員10人、同時所属1件、再参加の待機なし |

このスタックを追加しても、既存の冒険やキャラクターの設定はそのまま使えます。




### Unity に交流画面を追加する

Unity の再生を止め、`Extensions` の **Adventure Characters** のチェックを外します。左側の冒険画面はそのまま使います。


**Studio**

<a href="/samples/adventure/extensions/studio/AdventureSocial.cs" download>AdventureSocial.cs</a> を `Assets/AdventureExtensions` に入れ、`Extensions` に **Adventure Social** を追加します。接続には、ログイン済みの `Gs2ClientHolder` と `Gs2GameSessionHolder` を使います。


**SDK（Unity）**

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




再生すると、右側に交流画面が出ます。下のボタンは画面内をスクロールすると見えます。

### A と B を切り替える

まず、右側の **自分の ID をコピー** を押し、テキストエディターなどに A のプレイヤー ID として控えます。**表示名** を `冒険者 A` にして **自分の名前を保存** を押します。


**Studio**

再生を止めます。ログイン用オブジェクトの **PlayerPrefs Account Store → Key Prefix** を `adventure.main` から `adventure.social-b` に変え、再生します。初回は B のアカウントが作られます。

以降、A を使うときは再生を止めて Key Prefix を `adventure.main`、B を使うときは `adventure.social-b` に変えて再生します。保存済みのアカウントでログインするため、同じプレイヤー ID に戻ります。


**SDK（Unity）**

再生を止め、`AdventureLogin` の **Account Slot** を `main` から `social-b` に変えて再生し、ログインします。初回は B のアカウントが作られます。

以降も再生を止め、A を使うときは Account Slot を `main`、B を使うときは `social-b` に変えて再生し、ログインします。保存済みのアカウントでログインするため、同じプレイヤー ID に戻ります。




B でも **自分の ID をコピー** でプレイヤー ID を控え、表示名を `冒険者 B` にして保存します。**相手のプレイヤー ID** に A の ID を入れて **相手の名前を読む** を押すと、`冒険者 A` が表示されます。

A に切り替え、相手の ID に B の ID を入れて名前を読みます。B の名前が表示されれば、ID を使って別のプレイヤーを参照できています。

名前は Friend の公開プロフィールに保存しています。

```csharp
await Client.Friend.Namespace(FriendNamespace).Me(Session).Profile()
    .UpdateProfileAsync(publicProfile: displayName);

await Client.Friend.Namespace(FriendNamespace).User(targetUserId)
    .PublicProfile().ModelAsync();
```

## 2. スコアを送って順位を比べる

このランキングは最高記録を残す設定ではなく、**最後に送ったスコア** で順位を付けます。

画面には順位・送信時の表示名・スコア・プレイヤー ID が並びます。一覧への反映には最大 5 分かかることがあります。送ったスコアがまだ表示されないときは、少し待って **ランキングを読む** を押してください。順位を確認できたら、表の次の操作へ進みます。

| 操作 | ランキングを読んだときの結果 |
| --- | --- |
| A で表示名を `冒険者 A`、スコアを `100` にして **スコアを送る** | A が100点 |
| B に切り替え、表示名を `冒険者 B`、スコアを `200` にして送る | B が200点で A より上位 |
| A に切り替え、表示名を `冒険者 A`、スコアを `300` にして送る | A が300点で B より上位 |
| A から `50` を送る | A は50点に更新され、B より下位 |

```csharp
var ranking = Client.Ranking2.Namespace(RankingNamespace)
    .GlobalRankingModel("adventure").GlobalRankingSeason(Session);
await ranking.PutGlobalRankingAsync(value, displayName);
await foreach (var item in ranking.GlobalRankingsAsync())
{
    if (item != null) message += item.Rank + ": " + item.Metadata + " / " + item.Score + "\n";
}
```

表示名はスコアと一緒に送っています。プロフィールの名前を変えただけでは、ランキング上の名前は変わりません。新しい表示名を入力してスコアを送ると更新されます。

## 3. フレンドを申請し、承認する

1. A で、相手のプレイヤー ID に B の ID を入れ、**相手にフレンド申請** を押します。
2. **フレンド一覧を読む** を押します。承認前なので、B はまだ一覧に入りません。
3. B に切り替え、相手の ID に A の ID を入れて **相手からの申請を承認** を押します。フレンド一覧に A が表示されます。
4. A に切り替えて一覧を読むと、B が表示されます。
5. A で相手の ID に B の ID を入れ、**相手とのフレンドを解除** を押します。A の一覧から B が消えます。B に切り替えて読み直すと、B の一覧からも A が消えます。

申請先と、承認する申請の送り主を、それぞれ ID で指定します。

```csharp
var me = Client.Friend.Namespace(FriendNamespace).Me(Session);
await me.SendRequestAsync(targetUserId);
await me.ReceiveFriendRequest(targetUserId).AcceptAsync();
await foreach (var item in me.FriendsAsync(withProfile: true))
{
    if (item != null) message += item.UserId + " / " + item.PublicProfile + "\n";
}
```

## 4. ギルドに参加する

A に切り替え、**冒険者ギルドを作る** を押します。作成されたギルド ID が入力欄に入るので、控えてください。メンバー一覧には A とロール `master` が表示されます。

1. B に切り替え、控えた ID を **ギルド ID** へ入れます。
2. **このギルドに参加・申請** を押します。初めは自由参加（`anybody`）なので、そのまま参加できます。
3. **メンバー一覧を読む** を押すと、A と B が表示されます。B のロールは `member` です。
4. B で **このギルドから脱退** を押します。
5. A に切り替え、同じギルド ID を入力して **マスター: 承認制に変える** を押します。参加方式が `approval` になります。
6. B に切り替え、同じギルドへもう一度 **このギルドに参加・申請** を押します。今度は申請だけが送られ、メンバー一覧に B はまだ入りません。
7. A に切り替え、ギルド ID と相手のプレイヤー ID（B）を入力して **マスター: 相手の申請を承認** を押します。メンバー一覧に B が加わります。

作成と参加には、ログイン中のプレイヤーのセッションを使います。

```csharp
var me = Client.Guild.Namespace(GuildNamespace).Me(Session);
await me.CreateGuildAsync("adventure", "冒険者ギルド", "anybody");
await me.SendRequestAsync("adventure", guildName);
```

承認や参加方式の変更では、A の権限でギルドのセッションを取得してから操作します。この処理は `AdventureSocial.cs` の `ManageGuild()` にあります。

最後は A のままにします。次の章では、このプレイヤーにイベント報酬を配ります。

[次へ：イベントを開催する]()



