Game ideas & features

Your next feature

Matches

Turn-based games with explicit revisions, opaque state and separate result reports.

SDK developRequires a player session
Unity
Illustration of Matches
Your visible result

Coordinate a lobby, alternating turns and independent final reports with two player sessions.

Video coming later

This step does not have a video yet. The guide and MCP request are ready to use.

Turn-based matches

Prepare the same project

  1. Choose the same project in the dashboard as in your game configuration.

    Matches →
  2. No additional definition is needed for the first request. An empty result is valid until matching game data exists.

    Use two separate player sessions: create a lobby, join, start in an explicit order, submit alternating byte-state turns, then report the same final result independently.

    This first example reads data. It creates no group, match or object. An empty list is a valid first response.

Build this feature

You can preview the guide. Running it requires an active project key. Prepare project

SDK installed, project configuration imported and player signed in.

This SDK example uses develop. Check whether the required APIs exist in your installed SDK.

Complete the Quickstart connection with the intended player. Call ReadMyMatches() from an explicit button or scene action. Opening the file alone sends no request.

C#
Assets/Scripts/MatchesDemo.cs
horizOn call
1using UnityEngine;
2using PM.horizOn.Cloud.Manager;
3​
4public sealed class MatchesDemo : MonoBehaviour
5{
6 // Initialize/connect and restore the existing player in the Quickstart first.
7 // Invoke explicitly. The SDK also enforces the returned polling cadence.
8 public async void ReadMyMatches()
9 {
10 var user = UserManager.Instance.CurrentUser;
11 if (user == null || !user.IsValid()) return;
12 var result = await MatchesManager.Instance.GetMatches(user.UserId);
13 if (!result.IsSuccess) { Debug.LogWarning(result.ErrorCode); return; }
14 Debug.Log($"Ledger revision: {result.Data.revision}");
15 foreach (var match in result.Data.recent)
16 Debug.Log($"Match {match.id}: {match.status}");
17 // Recent may include an active match after this player's forfeit.
18 // Respect result.Data.pollAfterSeconds; no background poll or automatic timeout.
19 }
20}
21// Full two-player recipe: SDK Examples/MatchesExample and MatchesSampleStore.
22// ReadLedger/ReadMatch -> SaveCreateAfterLedgerReview/SaveActionAfterMatchReview.
23// ApplySavedIntent sends one durable original body/revision. Unknown create is reconciled.
24// Never replace a pending original with the revision from a later read.
25// ReportResult uses the original finalStateRevision/result bytes/sorted winnerIds.
26// Ordinary consensus is not trusted victory proof. Ranked runs use Validated Actions.
Open the complete SDK sample ↗

Two players, one original turn

Use two separate player sessions: create a lobby, join, start in an explicit order, submit alternating byte-state turns, then report the same final result independently.

Persist the exact request before sending. After a timeout, read current state and reconcile. Never replace its revision or create another intent silently.

Reports use the immutable final state revision. Agreement is not a trusted victory proof; disagreement and missing reports never imply a winner.

Ranked runs require a confirmed ranked match and the existing Validated Actions pipeline. Ordinary match reports do not grant rewards.

PHP supports ordinary match REST routes. Ranked validation and realtime are unavailable and return FEATURE_NOT_SUPPORTED where required.

Test your new feature.

Coordinate a lobby, alternating turns and independent final reports with two player sessions.

Choose the same project in the dashboard as in your game configuration.

Endpoints
  • GET/matches
  • GET/matches/limits
  • GET/matches/open
  • GET/matches/{matchId}
  • POST/matches
  • POST/matches/{matchId}/join
  • POST/matches/{matchId}/decline
  • POST/matches/{matchId}/start
  • POST/matches/{matchId}/turn
  • POST/matches/{matchId}/timeout
  • POST/matches/{matchId}/leave
  • POST/matches/{matchId}/cancel
  • POST/matches/{matchId}/result
  • POST/matches/{matchId}/ranked-run
All endpoints in the API reference
Our suggestion for your next step

Give every round a high score.

Save the score after a round and show who's ahead. Keep using your connection and player session.