Spielideen & Features

Euer nächstes Feature

Spielerpostfach

Persönliche Einträge und gemeinsame Projektrundschreiben, mit geschützten Belohnungen und einer Abfrage für soziale Nachrichten.

SDK: developSpielersession erforderlich
Unity
Illustration für Spielerpostfach
Euer sichtbares Ergebnis

Dein Spiel zeigt persönliche Nachrichten und Rundschreiben an, markiert sie gelesen und holt jede geschützte Belohnung höchstens einmal ab.

Video folgt

Für diesen Schritt fehlt noch das Video. Die Anleitung und der MCP-Auftrag sind bereits nutzbar.

Spielerpostfach

Dasselbe Projekt vorbereiten

  1. Wählt im Dashboard dasselbe Projekt wie in eurer Spielkonfiguration.

    Spielerpostfach →
  2. Für die erste Anfrage ist keine weitere Definition nötig. Ein leeres Ergebnis ist gültig, solange passende Spieldaten fehlen.

    Registriert den Testspieler, bevor ihr in diesem Projekt eine reine Text-Rundnachricht veröffentlicht. Lest das Postfach mit demselben Spieler.

    Das Rundschreiben erreicht aktuell aktive Projektspieler, die spätestens bei Veröffentlichung registriert waren. Zuvor inaktive Spieler können nach Reaktivierung berechtigt sein. Spätere Registrierungen sind ausgeschlossen.

Feature einbauen

Ihr könnt die Anleitung vorab ansehen. Zum Ausführen braucht ihr einen aktiven Projekt-Key. Projekt vorbereiten

SDK installiert, Projekt-Konfiguration importiert und Spieler angemeldet.

Dieses SDK-Beispiel nutzt develop. Prüft, ob die nötigen APIs in eurem installierten SDK verfügbar sind.

Verbindet zuerst den vorgesehenen Spieler über den Schnellstart. Ruft RunReviewedAction() ausdrücklich über einen Button oder eine Szenenaktion auf. Allein das Öffnen der Datei sendet keine Anfrage.

C#
Assets/Scripts/InboxDemo.cs
horizOn-Aufruf
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// Verwende die authentifizierte Sitzung des aktuellen Spielers. Wiederhole
9// ein ungewisses Abholen mit derselben Eintrags-ID. Ersetze den Wertestand
10// aus der Serverantwort; wende keine Belohnungsdifferenz doppelt an.
11public sealed class InboxDemo : MonoBehaviour
12{
13 public async void RunReviewedAction()
14 {
15 var sessionUser = UserManager.Instance.CurrentUser;
16 if (sessionUser == null || !sessionUser.IsValid()) return;
17 var userId = UserManager.Instance.CurrentUser.UserId;
18 var manager = InboxManager.Instance;
19 var loaded = await manager.GetInbox(userId, since: null);
20 if (!loaded.IsSuccess) { Debug.LogWarning(loaded.ErrorCode); return; }
21 foreach (var entry in loaded.Data.entries) Debug.Log(entry.textKey);
22 // The manager retains full cached entries when the wire response is unchanged.
23 // Poll again only after loaded.Data.pollAfterSeconds, and stop with the game lifecycle.
24​
25 bool claimInFlight = false;
26 async System.Threading.Tasks.Task ClaimSelectedReward(string entryId)
27 {
28 if (claimInFlight) return;
29 const string projectId = "YOUR_PROJECT_ID";
30 string pendingKey = "horizOn_inbox_claim_" + projectId + "_" + userId;
31 string pending = PlayerPrefs.GetString(pendingKey, "");
32 if (pending.Length > 0 && pending != entryId) return; // Resolve the original claim first.
33 if (pending.Length == 0)
34 {
35 var current = manager.CurrentInbox; // Authorized for the current project/session.
36 if (current == null || current.userId != userId) return;
37 var selected = System.Array.Find(current.entries, entry => entry.id == entryId);
38 if (selected == null || selected.claimed || selected.attachment?.values == null ||
39 selected.attachment.values.Length == 0) return;
40 }
41 // Previously saved IDs remain replayable even after their visible state changes.
42 PlayerPrefs.SetString(pendingKey, entryId);
43 PlayerPrefs.Save();
44 if (PlayerPrefs.GetString(pendingKey) != entryId) return;
45 claimInFlight = true;
46 try
47 {
48 var claimed = await manager.Claim(userId, entryId);
49 if (!claimed.IsSuccess) { Debug.LogWarning(claimed.ErrorCode); return; }
50 // Display claimed.Data.inbox and replace values with claimed.Data.playerValues.
51 // The SDK refreshes its cache. Never add reward deltas yourself.
52 if (PlayerPrefs.GetString(pendingKey, "") == entryId)
53 {
54 PlayerPrefs.DeleteKey(pendingKey);
55 PlayerPrefs.Save();
56 }
57 }
58 finally { claimInFlight = false; }
59 }
60 // Invoke ClaimSelectedReward only from an explicit player action.
61 // Retry the saved entryId after a lost response; no replacement grant or new action ID.
62 // Other deliberate actions: await manager.MarkRead(userId, entryId);
63 // await manager.Remove(userId, entryId); // Protects unclaimed rewards.
64 }
65}
Vollständiges SDK-Beispiel öffnen ↗

Testet euer neues Feature.

Dein Spiel zeigt persönliche Nachrichten und Rundschreiben an, markiert sie gelesen und holt jede geschützte Belohnung höchstens einmal ab.

Wählt im Dashboard dasselbe Projekt wie in eurer Spielkonfiguration.

Endpunkte
  • GET/inbox
  • POST/inbox/read
  • POST/inbox/claim
  • POST/inbox/remove
Alle Endpunkte in der API-Referenz
Unser Vorschlag für den nächsten Schritt

Gebt jeder Runde einen Highscore.

Speichert den Score nach dem Spiel und zeigt, wer vorne liegt. Eure Verbindung und Spielersession nutzt ihr weiter.