ゲームのアイデアと機能

次に追加する機能

プレイヤー受信箱

個別通知とプロジェクト一斉配信を、保護された報酬と共通のソーシャルポーリングで扱います。

SDK:developプレイヤーセッションが必要
Unity
プレイヤー受信箱のイラスト
確認できる結果

ゲームが個別通知と一斉配信を表示し、既読にして、保護された各報酬を最大一度だけ受領します。

動画は後日公開

この手順の動画はまだありません。ガイドとMCPへの依頼は利用できます。

プレイヤー受信箱

同じプロジェクトを準備する

  1. ゲームの設定と同じプロジェクトをダッシュボードで選択してください。

    プレイヤー受信箱 →
  2. 最初のリクエストに追加の定義は不要です。対応するゲームデータがなければ、空の結果も正常です。

    このプロジェクトでテキスト一斉メッセージを公開する前にテストプレイヤーを登録します。同じプレイヤーで受信箱を読みます。

    公開時点までに登録済みで、現在アクティブなプロジェクトのプレイヤーが対象です。以前非アクティブだったプレイヤーも再有効化後に対象となり得ます。公開後の新規登録は対象外です。

この機能を実装する

ガイドは閲覧できます。実行には有効なプロジェクトキーが必要です。 プロジェクトを準備する

SDK をインストールし、プロジェクト設定をインポート済みで、プレイヤーがログインしていること。

この SDK サンプルは develop を使用します。必要な API がインストール済みの SDK にあるか確認してください。

クイックスタートで対象プレイヤーを接続します。ボタンやシーンの明示的な操作からRunReviewedAction()を呼び出してください。ファイルを開くだけではリクエストは送信されません。

C#
Assets/Scripts/InboxDemo.cs
horizOn 呼び出し
1using PM.horizOn.Cloud.Objects.Network.Responses;
2using UnityEngine;
3using PM.horizOn.Cloud.Core;
4using PM.horizOn.Cloud.Manager;
5​
6// Existing SDK/project configuration and authenticated player session required.
7// Call RunReviewedAction explicitly after reviewing this example and its data.
8// 現在のプレイヤーの認証済みセッションを使用してください。受領結果が不明なら同じ通知 ID
9// で再試行します。値はサーバー状態で置換し、報酬を二重加算しないでください。
10public sealed class InboxDemo : MonoBehaviour
11{
12 public async void RunReviewedAction()
13 {
14 var sessionUser = UserManager.Instance.CurrentUser;
15 if (sessionUser == null || !sessionUser.IsValid()) return;
16 var userId = UserManager.Instance.CurrentUser.UserId;
17 var manager = InboxManager.Instance;
18 var loaded = await manager.GetInbox(userId, since: null);
19 if (!loaded.IsSuccess) { Debug.LogWarning(loaded.ErrorCode); return; }
20 foreach (var entry in loaded.Data.entries) Debug.Log(entry.textKey);
21 // The manager retains full cached entries when the wire response is unchanged.
22 // Poll again only after loaded.Data.pollAfterSeconds, and stop with the game lifecycle.
23​
24 bool claimInFlight = false;
25 async System.Threading.Tasks.Task ClaimSelectedReward(string entryId)
26 {
27 if (claimInFlight) return;
28 const string projectId = "YOUR_PROJECT_ID";
29 string pendingKey = "horizOn_inbox_claim_" + projectId + "_" + userId;
30 string pending = PlayerPrefs.GetString(pendingKey, "");
31 if (pending.Length > 0 && pending != entryId) return; // Resolve the original claim first.
32 if (pending.Length == 0)
33 {
34 var current = manager.CurrentInbox; // Authorized for the current project/session.
35 if (current == null || current.userId != userId) return;
36 var selected = System.Array.Find(current.entries, entry => entry.id == entryId);
37 if (selected == null || selected.claimed || selected.attachment?.values == null ||
38 selected.attachment.values.Length == 0) return;
39 }
40 // Previously saved IDs remain replayable even after their visible state changes.
41 PlayerPrefs.SetString(pendingKey, entryId);
42 PlayerPrefs.Save();
43 if (PlayerPrefs.GetString(pendingKey) != entryId) return;
44 claimInFlight = true;
45 try
46 {
47 var claimed = await manager.Claim(userId, entryId);
48 if (!claimed.IsSuccess) { Debug.LogWarning(claimed.ErrorCode); return; }
49 // Display claimed.Data.inbox and replace values with claimed.Data.playerValues.
50 // The SDK refreshes its cache. Never add reward deltas yourself.
51 if (PlayerPrefs.GetString(pendingKey, "") == entryId)
52 {
53 PlayerPrefs.DeleteKey(pendingKey);
54 PlayerPrefs.Save();
55 }
56 }
57 finally { claimInFlight = false; }
58 }
59 // Invoke ClaimSelectedReward only from an explicit player action.
60 // Retry the saved entryId after a lost response; no replacement grant or new action ID.
61 // Other deliberate actions: await manager.MarkRead(userId, entryId);
62 // await manager.Remove(userId, entryId); // Protects unclaimed rewards.
63 }
64}
完全なSDKサンプルを開く ↗

新しい機能をテストしましょう。

ゲームが個別通知と一斉配信を表示し、既読にして、保護された各報酬を最大一度だけ受領します。

ゲームの設定と同じプロジェクトをダッシュボードで選択してください。

エンドポイント
  • GET/inbox
  • POST/inbox/read
  • POST/inbox/claim
  • POST/inbox/remove
API リファレンスのすべてのエンドポイント
次のステップへのおすすめ

毎ラウンドにハイスコアを。

ラウンド終了後にスコアを保存し、上位のプレイヤーを表示します。現在の接続とプレイヤーセッションを引き続き使用します。