Overview
MultiplayerStack covers the same features as the Alpha XP plugins CognitoPass, DynamoLedger and GameLiftMatch in a single plugin with one shared AWS connection, one set of credentials and one settings page — plus combined nodes that connect the three areas. It can be installed next to those plugins: every module, class and setting has its own name.
- Player (combined): Sign In And Connect signs the player in to the user pool, gets identity-pool credentials for the DynamoDB and GameLift calls and creates or loads the player profile — in one node. Restore Session And Connect, Connect Player, Sign Out Everywhere, Get Player Id, Get Player Name.
- Profile (combined): one DynamoDB item per player keyed by the player id, with rating, wins / losses / draws, numeric stats and text fields. Ensure / Load / Save Player Profile, Update Player Stats (atomic), Get Leaderboard, Record Match Result with an Elo rating update and the pure Calculate Elo.
- Matchmake (combined): Matchmake With Profile sends the player's rating and region latencies to FlexMatch; Find Match And Travel also travels to the server; Cancel Matchmaking.
- Login: Amazon Cognito user pools — sign-up, sign-in with challenges and MFA, authenticator apps, password reset, attributes, remembered sessions with automatic refresh, AWS credentials.
- Data: Amazon DynamoDB with plain JSON — items, queries, scans, batches, transactions, atomic counters, leaderboards,
{IdentityId}tokens. - Match: Amazon GameLift for the game client — FlexMatch, queue placement, session search and creation, region latencies, connect URLs.
- MultiplayerStack Subsystem events: On Signed In, On Signed Out, On Session Refreshed, On Profile Loaded, On Match Found, On Matchmaking Failed.
Requirements
| Requirement | Details |
|---|---|
| Unreal Engine | 4.27 and 5.8 |
| Platforms | Win64, Linux and Android |
| Modules | MultiplayerStack (Runtime), MultiplayerStackSdk (prebuilt AWS SDK for C++ 1.11.916 in Source/ThirdParty: cognito-idp, cognito-identity, dynamodb, gamelift) |
| Dependencies | No other plugins. On Linux and Android the SDK uses the engine's libcurl, OpenSSL and certificate store. |
| AWS | An AWS account with a Cognito user pool and identity pool, a DynamoDB table for profiles and (for matchmaking) a GameLift fleet with a FlexMatch configuration. Usage is billed by AWS. |
Installation
- Install MultiplayerStack from Fab into your engine, or copy the
MultiplayerStackfolder into your project'sPluginsfolder. - Enable MultiplayerStack in Edit > Plugins and restart the editor.
- Open Project Settings > Plugins > MultiplayerStack and set User Pool Id, App Client Id, Identity Pool Id, Profile Table and Default Matchmaking Configuration. Region can stay empty (it is read from the user pool id).
- C++ only: add
PublicDependencyModuleNames.Add("MultiplayerStack");to yourBuild.cs.
LogMultiplayerStack), config section and SaveGame slot, so it installs side by side with the other Alpha XP cloud plugins, including the standalone CognitoPass, DynamoLedger and GameLiftMatch.Setting up AWS
1. User pool
In Amazon Cognito create a user pool and an app client with the ALLOW_USER_PASSWORD_AUTH and ALLOW_REFRESH_TOKEN_AUTH flows (preferably without a client secret). Copy the pool id (for example us-east-1_AbCdEf123) and the client id into the Login settings.
2. Identity pool
Create an identity pool and add the user pool as an identity provider (user pool id + app client id). Enable guest access if players may play before signing in. Signed-in players are registered with the pool automatically; their identity id is the player id of every area.
3. Profile table
Table mygame-prod-players (on-demand capacity)
PlayerId String partition key = the player id (Cognito identity id)
Global secondary index Rating-index (one per stat you rank by: Wins-index, xp-index ...)
partition key Board (String) every profile has Board = "global"
sort key Rating (Number)
projection INCLUDE PlayerName (or ALL)
Set Profile Table to players and Table Prefix to mygame-prod- (or the full name with an empty prefix). The key name, the leaderboard partition attribute and the index name pattern are settings.
4. Matchmaking
Upload your dedicated server, create a fleet (and an alias), a game session queue, a FlexMatch rule set and a matchmaking configuration. For Matchmake With Profile the rule set needs a Number attribute named like Rating Attribute Name (default skill), for example:
"playerAttributes": [{ "name": "skill", "type": "number", "default": 1000 }],
"rules": [{ "name": "FairSkill", "type": "distance", "measurements": ["avg(teams[*].players.attributes[skill])"],
"referenceValue": "avg(flatten(teams[*].players.attributes[skill]))", "maxDistance": 200 }]
5. Role policy
Attach this policy to the role the identity pool gives to players (authenticated and/or guest). The first statement only allows the player's own profile item (the partition key must be the caller's identity id), the second lets everyone read the leaderboard indexes, the third allows the GameLift client actions.
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "OwnProfileOnly",
"Effect": "Allow",
"Action": [
"dynamodb:GetItem", "dynamodb:BatchGetItem", "dynamodb:Query",
"dynamodb:PutItem", "dynamodb:UpdateItem", "dynamodb:DeleteItem",
"dynamodb:BatchWriteItem", "dynamodb:ConditionCheckItem"
],
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/mygame-prod-players",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${cognito-identity.amazonaws.com:sub}"]
}
}
},
{
"Sid": "ReadLeaderboards",
"Effect": "Allow",
"Action": "dynamodb:Query",
"Resource": "arn:aws:dynamodb:us-east-1:123456789012:table/mygame-prod-players/index/*"
},
{
"Sid": "Matchmaking",
"Effect": "Allow",
"Action": [
"gamelift:StartMatchmaking", "gamelift:DescribeMatchmaking",
"gamelift:StopMatchmaking", "gamelift:AcceptMatch",
"gamelift:StartGameSessionPlacement", "gamelift:DescribeGameSessionPlacement",
"gamelift:StopGameSessionPlacement", "gamelift:SearchGameSessions",
"gamelift:DescribeGameSessions", "gamelift:CreateGameSession",
"gamelift:CreatePlayerSession"
],
"Resource": "*"
}
]
}
Remove the actions your game does not call (FlexMatch games only need the first four GameLift actions). User-pool calls (sign-in, sign-up, MFA, attributes) need no IAM permissions: they are authenticated by the app client and the player's tokens.
DefaultGame.ini and in packaged games. Use them only for development and dedicated servers; players should always use the identity pool. Shipping builds refuse settings keys unless Allow Static Keys In Shipping is enabled.Quick start
Sign in, profile, match
- Main menu: call Restore Session And Connect. On Success = the returning player is signed in and Profile is loaded; On Failure with
NoSavedSession= show the login screen. - Login screen: Sign In And Connect with user name and password. On Challenge (MFA code, new password): answer with Respond To Challenge, then call Connect Player. New players use Sign Up / Confirm Sign Up first.
- Show Get Player Name and Profile > Rating; bind UI to the subsystem's On Profile Loaded so it updates by itself.
- Play button: Find Match And Travel (Configuration Name empty = the settings default). The player's Rating goes to FlexMatch, latencies are measured, and when the match is ready the player travels to
host:port?PlayerSessionId=.... On Requires Acceptance: call Accept Match withTicket.TicketId. A Cancel button calls Cancel Matchmaking on the subsystem. - After the match: Record Match Result (Win / Loss / Draw, the opponent's rating) and Update Player Stats (for example
kills = 12,xp = 300). - Leaderboard screen: Get Leaderboard (Stat
Rating, Count 10) → rows with Rank, Player Name, Score and Is Local Player. - Settings menu: Sign Out Everywhere.
Your dedicated server must validate each player: read PlayerSessionId from the login options and accept it through GameLift's server-side AcceptPlayerSession call, rejecting the login when that fails.
Player profiles
A profile is one item in the Profile Table, keyed by the player id (the Cognito identity id). Fixed attributes: PlayerName, Rating, Wins, Losses, Draws, MatchesPlayed, CreatedAt, UpdatedAt (ISO-8601 UTC) and the leaderboard partition attribute (Board = "global"). Every other number attribute appears in Stats, every other text attribute in Attributes; the whole item is in Item JSON, so the Data nodes work on the same item too.
{ "PlayerId": "us-east-1:7a3c...", "PlayerName": "Ada", "Rating": 1016.4, "Wins": 3, "Losses": 1, "Draws": 0,
"MatchesPlayed": 4, "Board": "global", "kills": 41, "xp": 1200, "avatar": "fox",
"CreatedAt": "2026-10-29T18:02:11.000Z", "UpdatedAt": "2026-10-29T19:40:03.000Z" }
- New profiles get Default Rating (1000) and Default Stats. Ensure Player Profile uses a conditional write, so it is safe to call on every start.
- Update Player Stats is one atomic
ADD; Record Match Result increments the counters atomically and writes the new rating only when the rating did not change since it was read (retried up to four times). - Elo:
Expected = 1 / (1 + 10^((Opponent - Player) / 400)),New = Player + K * (Score - Expected), Score 1 / 0.5 / 0, K = Elo K Factor (32). Ratings are rounded to 0.01 and never go below 0. - Guest and signed-in players have different identity ids, so a guest's profile does not carry over to the account automatically.
Nodes: Player, Profile, Matchmake
The combined nodes. Latent nodes can be stopped with Cancel on their return value and fire exactly one final pin on the game thread.
| Node | Kind | Inputs | Outputs | Notes |
|---|---|---|---|---|
| Sign In And Connect | Latent | Username, Password | On Success / On Failure (Session, Profile, Error), On Challenge (Challenge Name, Challenge Parameters) | Sign In + identity-pool credentials + Ensure Player Profile (when Ensure Profile On Connect). On Failure with a valid Session: signed in, but credentials or profile failed. |
| Restore Session And Connect | Latent | — | On Success / On Failure (Session, Profile, Error) | Restore Session (SaveGame slot MultiplayerStackSession) + credentials + profile. NoSavedSession when there is none. |
| Connect Player | Latent | Ensure Profile | On Success / On Failure (Session, Profile, Error) | Credentials + profile for the current player: after Respond To Challenge, Set Login Token, or for guests. |
| Sign Out Everywhere | Latent | — | On Success / On Failure (Error) | Cancels matchmaking, global sign-out (all devices), clears session, remembered session, identity login and cached profile (even when the server call fails). |
| Get Player Id | Pure | — | Player Id | The identity id, else the signed-in player's sub. |
| Get Player Name | Pure | — | Name | Cached profile's Player Name, else the user name. |
| Ensure Player Profile | Latent | Player Name | On Success / On Failure (Profile, Created, Error) | Creates the profile with the defaults unless it exists; returns it either way. |
| Load Player Profile | Latent | — | On Success / On Not Found / On Failure (Profile, Error) | Strongly consistent read of the player's profile. |
| Save Player Profile | Latent | Profile | On Success / On Failure (Profile, Error) | Replaces the whole item; Player Id is always the current player. |
| Update Profile Attributes | Latent | Fields (map) | On Success / On Failure (Profile, Error) | Sets text fields (PlayerName, avatar ...) without touching the rest. |
| Update Player Stats | Latent | Stat Deltas (map name → number) | On Success / On Failure (Profile, Error) | Atomic ADD of every delta; negative values subtract. Needs an existing profile. |
| Get Leaderboard | Latent | Stat, Count; advanced: Descending, Index Name | On Success / On Failure (Entries, Error) | Query on "<Stat>-index" (Board = global). Entries: Rank, Player Id, Player Name, Score, Is Local Player, Item JSON. |
| Record Match Result | Latent | Outcome (Win / Loss / Draw), Opponent Rating; advanced: K Factor | On Success / On Failure (Profile, Rating Delta, Error) | Counters + Elo rating update with an optimistic check. |
| Calculate Elo | Pure | Player Rating, Opponent Rating, Outcome; advanced: K Factor | New Rating, Rating Delta, Expected Score | The same formula, without a request. |
| Get Cached Player Profile | Pure | Target: MultiplayerStack Subsystem | Profile | The profile last loaded or written (Valid = false before that). |
| Matchmake With Profile | Latent | Configuration Name, Latencies; advanced: Team, Extra Attributes, Poll Interval, Max Wait Seconds | On Status Changed, On Requires Acceptance; On Matched / On Failed (Ticket, Error) | FlexMatch with Rating as Rating Attribute Name (Number) + Extra Attributes. Empty Latencies = measured now. Cancel stops the ticket. One matchmaking at a time. |
| Find Match And Travel | Latent | Player Controller, Configuration Name, Latencies; advanced: Team, Extra Attributes, Extra Options, Prefer Dns Name, Poll Interval, Max Wait Seconds | Same pins as Matchmake With Profile | On Matched fires, then ClientTravel to the connect URL. No address / player controller = On Failed with TravelFailed. |
| Cancel Matchmaking | Callable | Target: MultiplayerStack Subsystem | Return: was one running | Stops the running Matchmake With Profile / Find Match And Travel and its ticket. |
| Is Matchmaking | Pure | Target: MultiplayerStack Subsystem | Return value | True while one of them is waiting. |
Nodes: Config & Identity
Shared by all areas (one region, one set of credentials).
| Node | Kind | Inputs | Outputs | Notes |
|---|---|---|---|---|
| Set Region | Callable | Region | — | Region of every following request (empty = from the User Pool Id). |
| Set Credential Mode | Callable | Mode | — | Overrides the settings at runtime. |
| Set Login Token | Callable | Provider, Token | — | Identity-pool login with another provider (Google, Apple, Facebook, OpenID). Not needed after Sign In. |
| Clear Login Tokens | Callable | — | — | Forgets the logins and the identity (the player becomes a guest). |
| Set Static Credentials | Callable | Access Key Id, Secret Access Key, Session Token | — | Static Keys mode with keys from your backend. |
| Get Identity Id | Pure | — | Identity Id | Empty until credentials were resolved once. |
| Make User Pool Provider Name | Pure | Region, User Pool Id | Provider | cognito-idp.<region>.amazonaws.com/<pool id>. |
| Is Configured | Pure | — | Return, Problem | Checks the SDK, user pool, app client, region and credential settings. |
| Resolve Identity | Latent | Force Refresh | On Success / On Failure (Identity Id, Error) | Fetches identity and credentials now. |
| Cancel | Callable | Target: any latent node | — | None of its pins fire any more (matchmaking nodes also stop their ticket). |
| Is Finished | Pure | Target: any latent node | Return value | True after it finished or was cancelled. |
Nodes: Login (Amazon Cognito user pools)
| Node | Kind | Inputs | Outputs | Notes |
|---|---|---|---|---|
| Sign Up | Latent | Username, Password, Email; advanced: Attributes | On Success / On Failure (User Confirmed, Code Delivery Destination, Error) | Attribute names are Cognito's: name, preferred_username, phone_number, custom:team ... |
| Confirm Sign Up | Latent | Username, Code | On Success / On Failure (Error) | Confirms the account. |
| Resend Confirmation Code | Latent | Username | On Success / On Failure (Code Delivery Destination, Error) | Masked destination, for example a***@e***.com. |
| Sign In | Latent | Username, Password | On Success (Session, Error), On Challenge (Challenge Name, Challenge Parameters), On Failure | USER_PASSWORD_AUTH. The ID token is registered with the identity pool automatically. |
| Respond To Challenge | Latent | Challenge Name, Responses | Same pins as Sign In | NEW_PASSWORD_REQUIRED, SMS_MFA, SOFTWARE_TOKEN_MFA, EMAIL_OTP, SELECT_MFA_TYPE; the key CODE maps to the right one. |
| Restore Session | Latent | — | On Success / On Failure (Session, Error) | Remembered refresh token (Remember Session). A rejected token is deleted. |
| Refresh Session | Latent | — | On Success / On Failure (Session, Error) | Renews the tokens now (Auto Refresh does it before expiry). |
| Sign Out | Latent | Global | On Success / On Failure (Error) | Global = all devices. Local and remembered session are always cleared. |
| Forgot Password | Latent | Username | On Success / On Failure (Code Delivery Destination, Error) | Sends a reset code. |
| Confirm Forgot Password | Latent | Username, Code, New Password | On Success / On Failure (Error) | Sets the new password. |
| Change Password | Latent | Old Password, New Password | On Success / On Failure (Error) | Signed in. |
| Get User Attributes | Latent | — | On Success / On Failure (Attributes, Error) | sub, email, email_verified, custom attributes ... |
| Update User Attributes | Latent | Attributes | On Success / On Failure (Code Delivery Destination, Error) | A changed e-mail / phone number needs Verify User Attribute. |
| Verify User Attribute | Latent | Attribute Name, Code | On Success / On Failure (Code Delivery Destination, Error) | Empty Code = send a new code. |
| Delete Account | Latent | — | On Success / On Failure (Error) | Deletes the player from the pool and signs out. |
| Setup Authenticator App | Latent | — | On Success / On Failure (Secret Code, Otp Auth Uri, Error) | otpauth:// URI for a QR code; also during an MFA_SETUP challenge. |
| Verify Authenticator App | Latent | Code; advanced: Friendly Name | On Success / On Failure (Error) | Makes the app the preferred MFA; completes an MFA_SETUP sign-in. |
| Get AWS Credentials | Latent | — | On Success / On Failure (Credentials, Error) | The player's temporary AWS keys (identity pool), or the static keys / default chain. |
| Is Signed In | Pure | — | Return value | True while a session exists. |
| Get Session | Pure | — | Session | Username, Sub, Id Token, Access Token, Expires At, Valid. |
| Get Token Claims | Pure | Token | Return, Claims, Json | JWT payload; the signature is not checked. |
| Get User Pool Provider Name | Pure | — | Return value | The identity-pool login key of the configured user pool. |
Nodes: Data (Amazon DynamoDB)
Items are plain JSON; {IdentityId} inside any string value is replaced with the player id. Plain table names get the Table Prefix.
| Node | Kind | Inputs | Outputs | Notes |
|---|---|---|---|---|
| Put Item | Latent | Table, Item JSON, Condition Expression; advanced: Return Old, Values JSON, Names JSON | On Success / On Condition Failed / On Failure (Old Item JSON, Error) | Writes or replaces a whole item. |
| Get Item | Latent | Table, Key JSON; advanced: Projection Expression, Consistent Read, Names JSON | On Success / On Not Found / On Failure (Item JSON, Error) | Reads one item by key. |
| Update Item | Latent | Table, Key JSON, Update Expression, Values JSON; advanced: Names JSON, Condition Expression | On Success (Updated JSON), On Condition Failed, On Failure | SET / REMOVE / ADD / DELETE; returns the item after the update. |
| Delete Item | Latent | Table, Key JSON; advanced: Condition Expression, Values JSON, Names JSON | On Success / On Condition Failed / On Failure (Old Item JSON, Error) | Deletes one item and returns it. |
| Query | Latent | Table, Key Condition, Values JSON; advanced: Names JSON, Index Name, Filter Expression, Limit, Scan Forward, Start Key JSON | On Success / On Failure (Items JSON, Next Start Key JSON, Count, Error) | One page of a partition; pass Next Start Key JSON back for the next page. |
| Scan | Latent | Table, Filter Expression, Values JSON; advanced: Names JSON, Limit, Start Key JSON, Segment, Total Segments | On Success / On Failure (Items JSON, Next Start Key JSON, Count, Error) | Page by page; parallel scan with segments. |
| Batch Get | Latent | Table, Keys JSON | On Success / On Failure (Items JSON, Error) | 100 per request, unprocessed keys retried; order of the keys. |
| Batch Write | Latent | Table, Put Items, Delete Keys | On Success / On Failure (Written Count, Error) | 25 per request with retries; not atomic. |
| Transact Write | Latent | Operations JSON; advanced: Client Token | On Success / On Failure (Error) | Up to 100 put / update / delete / check operations, all or nothing. |
| Increment Counter | Latent | Table, Key JSON, Attribute, Delta | On Success / On Failure (New Value, Error) | Atomic; nested paths such as stats.kills. |
| Get Top Scores | Latent | Table, Index Name, Partition Key Name, Partition Value, Count, Descending | On Success / On Failure (Items JSON, Error) | Generic leaderboard query on any table. |
| Make Key JSON | Pure | Name, Value, Sort Name, Sort Value; advanced: Sort Value Is Number | Return value | {"pk":"{IdentityId}","sk":"inventory"}. |
| Struct To JSON | Callable | Struct (any) | Return, Json | Ready to use as Item JSON. |
| JSON To Struct | Callable | Json | Return, Out Struct (any) | Missing fields keep their defaults. |
| Get JSON Field | Pure | Json, Path | Return, Value | Path such as inventory[2].count. |
Nodes: Match (Amazon GameLift)
| Node | Kind | Inputs | Outputs | Notes |
|---|---|---|---|---|
| Find Match | Latent | Configuration Name, Players, Latencies; advanced: Poll Interval, Max Wait Seconds | On Status Changed, On Requires Acceptance; On Matched / On Failed (Ticket, Error) | Start Matchmaking + Wait For Match; Cancel stops the ticket. |
| Start Matchmaking | Latent | Configuration Name, Players, Latencies; advanced: Ticket Id | On Success / On Failure (Ticket, Error) | Players empty = one player with the identity id. |
| Wait For Match | Latent | Ticket Id; advanced: Poll Interval, Max Wait Seconds, Stop Ticket On Cancel | On Status Changed, On Requires Acceptance; On Matched / On Failed | Polls the ticket; transient errors are retried up to 5 times in a row. |
| Accept Match | Latent | Ticket Id, Player Ids, Accept | On Success / On Failure (Error) | Player Ids empty = this player. |
| Stop Matchmaking | Latent | Ticket Id | On Success / On Failure (Error) | Cancels a ticket. |
| Start Game Session Placement | Latent | Queue Name, Max Players, Game Session Name, Game Properties, Players, Latencies; advanced: Placement Id, Game Session Data | On Success / On Failure (Placement, Error) | New session through a queue. |
| Wait For Placement | Latent | Placement Id; advanced: Poll Interval, Max Wait Seconds, Stop Placement On Cancel | On Placed / On Failed (Placement, Error) | Until Fulfilled, Cancelled, Timed Out or Failed. |
| Stop Game Session Placement | Latent | Placement Id | On Success / On Failure (Placement, Error) | Cancels a pending placement. |
| Search Game Sessions | Latent | Filter Expression, Sort Expression, Limit; advanced: Next Token, Fleet Id, Alias Id, Location | On Success / On Failure (Sessions, Next Token, Error) | Server browser; 20 per page. |
| Describe Game Sessions | Latent | Game Session Id; advanced: Status Filter, Next Token, Fleet Id, Alias Id, Location, Limit | On Success / On Failure (Sessions, Next Token, Error) | One session or all sessions of a fleet / alias. |
| Create Game Session | Latent | Max Players, Name, Game Properties; advanced: Fleet Id, Alias Id, Location, Game Session Data, Idempotency Token, Wait Until Active | On Success / On Failure (Session, Error) | Direct session on a fleet; waits until active by default. |
| Create Player Session | Latent | Game Session Id, Player Id; advanced: Player Data | On Success / On Failure (Connection, Error) | Reserves a slot and returns the address. |
| Measure Region Latencies | Latent | Regions; advanced: Samples, Timeout Seconds | On Success / On Failure (Latencies, Best Region, Failed Regions) | TCP connect times to every region at the same time, fastest first. |
| Make Connect URL | Pure | Connection, Player Id; advanced: Extra Options, Prefer Dns Name | Return value | host:port?PlayerSessionId=psess-... |
| Travel To Game Session | Callable | Player Controller, Connection, Player Id; advanced: Extra Options, Prefer Dns Name | Return, Url | Make Connect URL + ClientTravel. |
| Get Best Region | Pure | Latencies | Return, Latency Ms | Fastest region of a latency map. |
Subsystem events
Get Game Instance Subsystem > MultiplayerStack Subsystem, then bind:
| Event | Kind | Fires when |
|---|---|---|
| On Signed In (Session) | Event | Sign In, Respond To Challenge, Restore Session, Verify Authenticator App (MFA_SETUP) or a combined sign-in signed a player in. |
| On Signed Out | Event | Sign Out, Sign Out Everywhere, Delete Account, or the user pool rejected the refresh token. |
| On Session Refreshed (Session) | Event | Refresh Session or an automatic refresh renewed the tokens. |
| On Profile Loaded (Profile) | Event | A profile node (or a connect / matchmake node) loaded, created or changed the profile. |
| On Match Found (Ticket) | Event | Matchmake With Profile / Find Match And Travel found a match. |
| On Matchmaking Failed (Ticket, Error) | Event | They ended without a match (failed, timed out, cancelled on AWS, travel failed). Not for Cancel. |
Credentials
| Mode | Use for | How |
|---|---|---|
| Cognito Identity Pool | Game clients | Guests get unauthenticated credentials; after Sign In (or Set Login Token) the player gets the authenticated role. Tokens and credentials are renewed automatically before they expire. Guest identities are remembered across restarts. |
| Static Keys | Development, dedicated servers, keys from your backend | Settings keys or Set Static Credentials. There is no identity id: the player id falls back to the user-pool sub. |
| Default Credential Chain | Servers and tools | Environment variables, the ~/.aws profile, ECS and EC2 instance roles. |
User-pool requests (the Login area) are always unsigned; the Data and Match areas and Get AWS Credentials use the mode above. All areas share one region, one worker pool and one SDK instance.
C++ API
// Build.cs: PublicDependencyModuleNames.Add("MultiplayerStack");
#include "MultiplayerStackGlueAsyncActions.h"
UMultiplayerStackSignInAndConnectAction* Connect = UMultiplayerStackSignInAndConnectAction::SignInAndConnect(this, User, Password);
Connect->OnSuccess.AddDynamic(this, &UMyLoginWidget::HandleConnected); // (Session, Profile, Error)
Connect->OnFailure.AddDynamic(this, &UMyLoginWidget::HandleConnectFailed);
Connect->Activate();
UMultiplayerStackFindAndTravelAction* Play = UMultiplayerStackFindAndTravelAction::FindMatchAndTravel(this, nullptr, FString(), FString(),
TMap<FString, FMultiplayerStackMatchAttribute>(), FMultiplayerStackMatchLatencyMap(), TMap<FString, FString>());
Play->OnFailed.AddDynamic(this, &UMyLobbyWidget::HandleNoMatch);
Play->Activate();
Every latent node class has a static factory with the node's inputs; bind the delegates, then call Activate(). Area headers: MultiplayerStackLoginAsyncActions.h, MultiplayerStackDataAsyncActions.h, MultiplayerStackMatchAsyncActions.h; libraries: MultiplayerStackLibrary.h, MultiplayerStackGlueLibrary.h, MultiplayerStackLoginLibrary.h, MultiplayerStackDataLibrary.h, MultiplayerStackMatchLibrary.h.
Types
| Type | Kind | Members |
|---|---|---|
| FMultiplayerStackPlayerProfile | Struct | Player Id, Player Name, Rating, Wins, Losses, Draws, Matches Played, Stats, Attributes, Created At, Updated At, Item JSON, Valid |
| FMultiplayerStackLeaderboardEntry | Struct | Rank, Player Id, Player Name, Score, Is Local Player, Item JSON |
| EMultiplayerStackMatchOutcome | Enum | Win, Loss, Draw |
| FMultiplayerStackLoginSession | Struct | Username, Sub, Id Token, Access Token, Expires At (UTC), Valid |
| FMultiplayerStackLoginAwsCredentials | Struct | Identity Id, Access Key Id, Secret Access Key, Session Token, Expiration |
| FMultiplayerStackLoginStringMap | Struct | Values (challenge parameters, user attributes) |
| FMultiplayerStackMatchPlayer | Struct | Player Id, Team, Attributes, Latency Ms, Player Data |
| FMultiplayerStackMatchAttribute | Struct | Type, String Value, Number Value, String List, Number Map |
| FMultiplayerStackMatchLatencyMap | Struct | Values (region → ms) |
| FMultiplayerStackMatchTicket | Struct | Ticket Id, Configuration Name, Status, Status Reason, Status Message, Estimated Wait Seconds, Player Ids, Connection |
| FMultiplayerStackMatchPlacement | Struct | Placement Id, Queue Name, Status, Game Session Name, Connection |
| FMultiplayerStackMatchConnection | Struct | Game Session Id, Ip Address, Dns Name, Port, Region, Player Sessions |
| FMultiplayerStackMatchPlayerSession | Struct | Player Id, Player Session Id |
| FMultiplayerStackMatchGameSession | Struct | Game Session Id, Name, Fleet Id, Status, Current / Max Players, Accepts New Players, Ip Address, Dns Name, Port, Location, Creator Id, Game Properties, Game Session Data |
| FMultiplayerStackError | Struct | Code, Message, Http Status, Retryable |
| EMultiplayerStackCredentialMode | Enum | Cognito Identity Pool, Static Keys, Default Credential Chain |
| EMultiplayerStackMatchTicketStatus / PlacementStatus / SessionStatus / AttributeType | Enum | As in the GameLift API (Queued, Searching, Requires Acceptance, Placing, Completed, Failed, Cancelled, Timed Out ...) |
| UMultiplayerStackSubsystem | Class | Game Instance Subsystem with the events above, Cancel Matchmaking, Is Matchmaking, Get Cached Player Profile |
Settings
Project Settings > Plugins > MultiplayerStack (saved to DefaultGame.ini, section [/Script/MultiplayerStack.MultiplayerStackSettings]). Changes apply to the next request.
| Setting | Default | Description |
|---|---|---|
| Connection: Region | (empty) | Region of all resources; empty = from the User Pool Id, then the Identity Pool Id, then us-east-1. |
| Connection: Request / Connect Timeout Ms | 30000 / 5000 | Time limits per request. |
| Connection: Max Retries, Worker Threads | 3, 4 | Retries with back-off; background threads. |
| Connection: Verify SSL, Log Sdk Warnings | On, On | TLS checks; SDK warnings to LogMultiplayerStack. |
| Credentials: Credential Mode | Cognito Identity Pool | Source of the Data / Match credentials. |
| Credentials: Identity Pool Id, Allow Guest Access | (empty), On | For example us-east-1:01234567-89ab-cdef-0123-456789abcdef. |
| Credentials: Access Key Id / Secret Access Key, Allow Static Keys In Shipping | (empty), Off | Static Keys mode (development and servers). |
| Login: User Pool Id, App Client Id, App Client Secret | (empty) | The user pool and its app client (secret only if the client has one). |
| Login: Remember Session, Auto Refresh | On, On | SaveGame slot MultiplayerStackSession; renew tokens about 5 minutes before expiry. |
| Login: Login Endpoint Override | (empty) | A local user-pool emulator. |
| Data: Table Prefix, Consistent Reads By Default | (empty), Off | Prefix for plain table names; strongly consistent reads. |
| Data: Data Endpoint Override | (empty) | For example DynamoDB Local (http://localhost:8000). |
| Player Profile: Profile Table, Profile Key Name | players, PlayerId | The profile table and its partition key. |
| Player Profile: Ensure Profile On Connect | On | The connect nodes create / load the profile. |
| Player Profile: Default Rating, Elo K Factor, Default Stats | 1000, 32, (empty) | Values of new profiles and the rating update. |
| Leaderboard: Partition Key, Partition Value, Index Format | Board, global, {stat}-index | How Get Leaderboard finds the index. |
| Match: Default Matchmaking Configuration, Default Queue Name, Default Fleet Id / Alias Id | (empty) | Used when a node leaves them empty. |
| Match: Poll Interval Seconds | 10 | Status checks of the wait / matchmaking nodes. |
| Match: Rating Attribute Name | skill | FlexMatch Number attribute filled with the profile's Rating. |
| Match: Match Endpoint Override | (empty) | A local test service. |
| Latency: Latency Regions, Host Format, Port | 15 regions, gamelift.{region}.amazonaws.com, 443 | Where latency is measured. |
Troubleshooting
| Error code | Cause and fix |
|---|---|
NotConfigured | A required setting is empty (User Pool Id, App Client Id, Identity Pool Id, Profile Table, Leaderboard Partition Key). Call Is Configured for the details. |
NotAuthorizedException | Wrong password, a disabled user, guest access off on the identity pool, or a token that expired. |
AccessDeniedException | The identity pool role lacks the DynamoDB or GameLift permission, or the profile key is not the caller's identity id (LeadingKeys). |
NoProfile | The player has no profile yet: call Ensure Player Profile (the connect nodes do it with Ensure Profile On Connect). |
NoPlayerId | No identity id and nobody signed in: use the Cognito Identity Pool credential mode or sign in first. |
ValidationException (leaderboard) | The index does not exist or its keys differ: create "<Stat>-index" with partition key Board and the stat as Number sort key. |
RatingConflict | The rating changed four times in a row while recording a result; try again. |
MatchmakingFailed / MatchmakingTimedOut / WaitLimit | FlexMatch found no match within its timeout, or Max Wait Seconds was reached. Check the rule set's attributes (Rating Attribute Name) and latency rules. |
TravelFailed | A match was found but there was no player controller or address. Pass a Player Controller to Find Match And Travel. |
Unavailable | The SDK library could not be loaded or the engine is shutting down. Check the Output Log for LogMultiplayerStack errors. |
Credits
© 2026 Alpha XP — alphaxp.net · Support: support@alphaxp.net. Includes the AWS SDK for C++ and the AWS Common Runtime (Apache License 2.0). Built for Unreal Engine 4.27 and 5.8.