Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
You can follow these docs to create an integration with Player Zero, integrate Player Zero avatars into your games, and eventually submit your game to the Player Zero Games Catalog.
Before taking a look at any of our integration guides, please ensure you have been in contact with a member of the Player Zero team, and that we have provided you with your developer account credentials.
Note: these docs are early access and still partially incomplete
A step by step guide to integrate the Player Zero SDK into your game
Note: these docs are still early access and partially incomplete
🎥 Prefer to watch instead? This short video (under 5 minutes) walks you through the steps of integrating the Player Zero SDK into your Unity game.
You should have been in contact with a member of the Player Zero team.
If you intend to use your own existing character proportions and rig with P0 visuals applied on top, then you should have sent us your base character FBX so we can setup a custom blueprint for you. Note: this is not required if you intend to use the default P0 proportions and P0 rig in your game.
You have should have received confirmation from Player Zero that your account is setup, and you should've been given your Player Zero developer account credentials.
If any of the above prerequisites are not true, please reach out to us before continuing.
You can visit our Unity SDK GitHub releases page to access the latest release and install it via the Unity Package Manager.
Using the credentials provided to you by your account manager, you should now login to your Player Zero developer account as shown in the screenshot below. You can access the developer login window by going to tools -> Player Zero.
Before following this document, your Player Zero account manager should've asked you for your character base model, and they should've taken it away and setup a blueprint for you account. Take some time now to verify that your blueprint appears in the window, similar to the ones shown below. It should also have already been populated with a default template prefab.
Using the test script below, you can now try to test out loading a Player Zero character. You can use any avatar ID, including ones from the playerzero.readyplayer.me platform, or one of the test avatar IDs we’ve provided, such as: 6799e786ad3f17b0ac17f265
, 6799e89a4f6181e930480786
.
using PlayerZero.Runtime.Sdk;
using UnityEngine;
public class TestScript : MonoBehaviour
{
// Start is called before the first frame update
private async void Start()
{
var avatar = await PlayerZeroSdk.InstantiateAvatarAsync(
new CharacterRequestConfig()
{
AvatarId = "AVATAR_ID_HERE"
}
);
}
}
In some scenarios, you may already have a character prefab in your scene that is fully rigged and wired up with your controller logic, animations, clothing, and more. In this case, instantiating a brand new Player Zero avatar GameObject and setting everything up again at runtime can be unnecessary and complicated.
To simplify this, the SDK provides a Mesh Transfer utility class. This allows you to load a Player Zero avatar and transfer its mesh, materials, and textures onto an existing character prefab that already has the correct rig setup. The temporary avatar is cleaned up automatically after the transfer is complete.
Keeps your original prefab, controller setup, and hierarchy intact.
Supports runtime mesh customization while maintaining gameplay logic.
Works with any prefab using a compatible rig (e.g., a Player Zero blueprint rig or custom rig if prearranged with the team).
Under the hood:
A Player Zero avatar is loaded in the background.
Meshes and materials from the new avatar are transferred to your existing character.
The temporary avatar is destroyed after transfer.
Your existing character prefab must use a compatible rig and hierarchy (typically a previously registered Player Zero blueprint).
Your avatar should be loaded with a matching BlueprintId
.
using PlayerZero.Runtime.Sdk;
using PlayerZero.Runtime.MeshTransfer;
using UnityEngine;
public class MeshTransferExample : MonoBehaviour
{
public GameObject existingCharacter; // This should be your in-scene character prefab with a SkinnedMeshRenderer setup.
private async void Start()
{
var avatar = await PlayerZeroSdk.InstantiateAvatarAsync(new CharacterRequestConfig
{
AvatarId = "AVATAR_ID_HERE",
BlueprintId = "BLUEPRINT_ID_HERE"
});
var meshTransfer = new MeshTransfer();
// Perform the transfer from the new avatar to your existing character
meshTransfer.Transfer(avatar, existingCharacter);
}
}
Using the test script below, you can now try to test out loading a Player Zero character as a specific blueprint in your account. The returned avatar will come with the rig and proportions of whatever the target blueprint has.
using PlayerZero.Runtime.Sdk;
using UnityEngine;
public class TestScript : MonoBehaviour
{
// Start is called before the first frame update
private async void Start()
{
var avatar = await PlayerZeroSdk.InstantiateAvatarAsync(
new CharacterRequestConfig()
{
AvatarId = "AVATAR_ID_HERE",
BlueprintId = "BLUEPRINT_ID_HERE"
}
);
}
}
Using the test script below, you can now try to test out loading a Player Zero character that has been passed to the SDK via hot loading, as a specific blueprint in your account. The returned avatar will come with the rig and proportions of whatever the target blueprint has.
using PlayerZero.Runtime.Sdk;
using UnityEngine;
public class TestScript : MonoBehaviour
{
// Start is called before the first frame update
private async void Start()
{
var avatarId = PlayerZeroSdk.GetHotLoadedAvatarId();
var avatar = await PlayerZeroSdk.InstantiateAvatarAsync(
new CharacterRequestConfig()
{
AvatarId = avatarId,
BlueprintId = "BLUEPRINT_ID_HERE"
});
}
}
🎥 Prefer to watch instead? This short video (under 2 minutes) walks you through how to set up Player Zero SDK analytics in your Unity game.
In order for us to understand how Player Zero players are interacting with your game, we require you to add the PlayerZeroAnalytics component into your game. The metric captured by this component are vital to your partnership with Player Zero. To set this up, simply create a new empty component in the initial scene of your game, and then add the PlayerZeroAnalytics component.
Making sure you have set your GAME ID in tools -> Player Zero, otherwise you will see an error and player sessions will not be captured
As part of the integration of Player Zero, you may sometimes need to trigger Player Zero game events manually at certain points in your game loop. For example, if you allow your player to switch out their Player Zero avatar for one of your own. Doing this is as simple as calling the SendEvent and StartEventSession functions that is are available through the SDK.
The difference between StartEventSession and SendEvent is that the former creates a new session id when it is sent, and the latter requires a session id to be passed to it to end the session. There are multiple event types that can be sent, and you can see all of these in the Events folder in the SDK.
using PlayerZero.Api.V1;
using PlayerZero.Runtime.Sdk;
using UnityEngine;
public class TestScript : MonoBehaviour
{
// Start is called before the first frame update
private void Start()
{
var avatarId = PlayerZeroSdk.GetHotLoadedAvatarId();
PlayerZeroSdk.StartEventSession<GameSessionStartedEvent, GameSessionStartedProperties>(
new GameSessionStartedEvent()
{
Properties = new GameSessionStartedProperties()
{
AvatarId = avatarId,
}
});
}
}
Important: If you're sending custom analytics events manually (not using the PlayerZeroAnalytics component), you must send the full set of required events to ensure session tracking and payouts work properly:
– GameSessionStartedEvent
– AvatarSessionStartedEvent
– AvatarSessionHeartbeatEvent
– AvatarSessionEndedEvent
– GameSessionEndedEvent
Missing any of these will result in uncaptured sessions and missed payouts.
Enable multiplayer-style lobby support, allowing players to gather before entering the game. 👉 Learn more about Player Zero Lobby
Allow your app to respond to custom URLs for loading specific avatars or scenes directly. 👉 Learn more about Deeplinking
The QuickStart Sample is included with the Player Zero Unity SDK to demonstrate how to use the SDK to load Ready Player Me avatars onto existing player prefabs in both First Person and Third Person setups.
This guide will help you:
Import the sample from Unity Package Manager
Open and run the sample scene
Customize the avatar by editing the Sample Avatar Loader component
Open your Unity project.
In the Unity Editor toolbar, go to: Window > Package Manager
Locate the Player Zero SDK package.
Click the arrow to expand the package details.
Scroll to the bottom and click Import into Project under QuickStart sample.
After import, you'll find the sample under:
Assets/Samples/Player Zero SDK/<version>/QuickStart/
Once imported:
Navigate to: Assets/Samples/Player Zero SDK/<version>/QuickStart/
Open the appropriate sample scene:
FirstPerson/PlayerZeroFP.unity
ThirdPerson/PlayerZeroTP.unity
Press Play in the Unity Editor.
You’ll see a player character with a Ready Player Me avatar loaded via our SDK.
To load your own avatar:
Select the PlayerZeroAvatar
GameObject in the scene hierarchy.
This may be named something like PlayerZeroAvatarFP
, PlayerZeroAvatarTP
In the Inspector, locate the Sample Avatar Loader
component.
Set the Avatar ID field to your personal or test avatar ID.
Press Play again. The scene will load the avatar linked to the ID you provided.
✅ Tip: You can obtain an avatar ID by creating one via the Player Zero Avatar Creator or API.
The Player Zero platform allows players to form pre-game lobbies with their friends, then launch your Unity game together with synchronized session data.
When a host starts the game from the Player Zero website, the game is launched with metadata that helps your game:
Identify the lobby (lobbyId
)
Determine who is the host (host
)
Match all players to the correct region (region
)
This page explains how to read this data inside your Unity project and use it to connect all players to the same multiplayer session, especially when using a networking solution like Photon.
When the game is launched from a Player Zero lobby, the following parameters are passed:
lobbyId
string
A shared ID for the session. Can be used as the room name or lobby code.
host
boolean
Indicates whether the current player is the lobby host.
region
string
The region code for the session (e.g., us
, eu
, etc). Use this to ensure all players connect to the same region and prevent connection issues.
The Player Zero SDK includes a helper class called ZeroLobby
that makes it easy to retrieve lobby data passed from the Player Zero platform.
You can use it to:
Check if lobby data is available
LobbyQueryHandler.CheckForLobby()
Get the lobby ID
LobbyQueryHandler.LobbyId
Check if the player is the host LobbyQueryHandler.IsHost
Get the region of the host LobbyQueryHandler.HostRegion
Call LobbyQueryHandler.CheckForLobby()
early in your game's startup flow to initialize and apply the correct values.
For example you might have a NetworkManager
class that checks for a lobby in the Start function.
using PlayerZero.Runtime;
public class NetworkManager
{
private void Start()
{
if(LobbyQueryHandler.CheckForLobby())
{
//Lobby parameters found, setup in game network room or lobby
}
}
}
The following code samples are using API's from Photon PUN2 networking plugin but the concepts should be the same for any Unity networking solution.
lobbyId
as your room nameThis ensures that all players connect to the same room or lobby.
PhotonNetwork.JoinOrCreateRoom(LobbyQueryHandler.LobbyId, new RoomOptions(), TypedLobby.Default);
LobbyQueryHandler.IsHost
to determine roleIf LobbyQueryHandler.IsHost == true
, the player should create the room. Otherwise, they should join the room.
if (LobbyQueryHandler.IsHost) //host will create room while others will join room
{
PhotonNetwork.CreateRoom(LobbyQueryHandler.LobbyId, new RoomOptions(), TypedLobby.Default);
}
else
{
PhotonNetwork.JoinRoom(LobbyQueryHandler.LobbyId);
}
region
to connect to the correct serverPhoton normally selects a region based on the player's location. You'll want to force all players to use the host's region to prevent mismatched rooms.
PhotonNetwork.PhotonServerSettings.AppSettings.FixedRegion = LobbyQueryHandler.HostRegion;
PhotonNetwork.ConnectUsingSettings();
If you're building a WebGL game, the SDK includes a function that allows you to return players back to the Player Zero lobby after a game session ends
To trigger this behavior from your Unity code, call the following method:
// playerScore is an int value that represents the players score.
// the score is used to determine which member of the lobby is the "winner" of the game
// if score is not applicable to your game then you can just send 0
PlayerZeroSDK.SendBackToPlayerZero(playerScore);
Calling this will exit the game view and return the player to the Player Zero lobby interface.
By using lobbyId
, host
, and region
, you can ensure:
All players join the same room
The correct player creates the room
Everyone connects to the same region
This approach ensures a consistent multiplayer experience across all participants, especially when using cloud-based networking solutions like Photon.
Deep linking allows your application to respond to external URLs and launch directly into specific content or actions within the app. This is particularly useful for experiences like loading user-specific avatars or jumping into a custom scene from a shared link. Our SDK supports deep linking across mobile platforms (Android and iOS) as well as desktop platforms (Windows and macOS). This guide will walk you through enabling and handling deep links in your Unity project using our SDK.
When it comes to sending avatars created in our PlayerZero web platform the simplest way to send them to a mobile application is by passing data via deep linking. Unity supports deeplinking and the steps described below can also be found in the Unity documentation here. 🎥 Prefer to watch instead? This short video (2 minutes) walks you through how to set up mobile deep linking using the PlayerZero SDK in Unity on both Android and iOS.
To enable deeplinking for Android you can use an intent filter. The process is as follows:
In Unity navigate to Edit > Project Settings > Player
In the Android settings tab, expand the Publishing Settings section
In the Build section, enable Custom Main Manifest. This creates a new file called AndroidManifest.xml
in Assets/Plugins/Android
.
In the Project window, go to Assets > Plugins > Android and open the AndroidManifest.xml
file
Add the following code sample inside the Unity<activity>
element, named com.unity3d.player.UnityPlayerGameActivity
or com.unity3d.player.UnityPlayerActivity
, and save the file.
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="playerzero0000" android:host="playerzero" />
</intent-filter>
Remember to replace the number 0000
in playerzero0000
with your unique GAMEID
to ensure you are using your own unique scheme.
To enable deeplinking for iOS it is even simpler, the process is as follows.
Go to Edit > Project Settings > Player > Other Settings > Configuration.
Expand Supported URL schemes to set the following properties:
Size property to 1
.
Element 0 property to the URL scheme to use with your application. For example, use playerzero0000
to open your application when the device processes a link that starts with playerzero0000://
.
Remember to replace the number 0000
in playerzero0000
with your unique GAMEID
to ensure you are using your own unique scheme.
To enable deeplinking for desktop applications on Windows we a custom entry needs to be added to the Window registry. Without this it is not possible to trigger the application to launch from a web URL. For more information on Windows registries including how to add and remove them please refer to the Windows documentation.
Ensure that you have set your GameID by logging into the Player Zero Developer Window located in the tool bar Tools > Player Zero
In your first scene add an empty GameObject and add the component DesktopDeepLinkSetup.
If you look in the components inspector the SetupOnStart
property will be enabled by default. If enabled this means that when this scene is run it will automatically create a custom Windows registry that will enable us to launch the application from a web URL.
The deeplinking setup process for MacOS is exactly the same as for iOS. In any case you can find the steps below.
Go to Edit > Project Settings > Player > Other Settings > Configuration.
Expand Supported URL schemes to set the following properties:
Size property to 1
.
Element 0 property to the URL scheme to use with your application. For example, use playerzero0000
to open your application when the device processes a link that starts with playerzero0000://
.
Remember to replace the number 0000
in playerzero0000
with your unique GAMEID
to ensure you are using your own unique scheme.
Now that we have enabled deeplinking we can make use of the PlayerZeroSdk.OnHotLoadedAvatarIdChanged
event.
Lets create a new C# script and call it DeepLinkingSample.
First we will create a load avatar function that uses our PlayerZeroSDK functions to request, download and instantiate the character model.
public class DeepLinkingSample : MonoBehaviour {
public async Task LoadAvatar(string avatarId)
{
var response = await PlayerZeroSdk.GetAvatarMetadataAsync(avatarId);
var characterRequestConfig = new CharacterRequestConfig()
{
AvatarId = avatarId,
AvatarUrl = response.ModelUrl,
BlueprintId = response.BlueprintId,
Parent = transform
};
var avatarGameObject = await PlayerZeroSdk.InstantiateAvatarAsync(characterRequestConfig);
}
}
Now we can create a new function that uses the PlayerZeroSDK.HotLoadedAvatarId()
to get the avatarId
.
public void LoadHotLoadedAvatar()
{
LoadAvatar(PlayerZeroSdk.GetHotLoadedAvatarId());
}
Now you can use the LoadHotLoadedAvatar()
function whenever you want to load the avatar.
Alternatively you can subscribe to the PlayerZeroSdk.OnHotLoadedAvatarIdChanged
event which is automatically triggered whenever a new avatar id has been detected.
To do this lets we can use the Awake function subscribe to the OnHotLoadedAvatarIdChanged
event and assign a new function that loads the avatar.
private void Awake()
{
PlayerZeroSdk.OnHotLoadedAvatarIdChanged += OnHotLoadedAvatarIdChanged;
}
private void OnHotLoadedAvatarIdChanged(string avatarId)
{
LoadAvatar(avatarId);
}
Don't forget to unsubscribe to the event
private void OnDestroy()
{
PlayerZeroSdk.OnHotLoadedAvatarIdChanged -= OnHotLoadedAvatarIdChanged
}
Below you can find the full sample script.
using System.Threading.Tasks;
using PlayerZero.Runtime.Sdk;
using UnityEngine;
public class DeepLinkingSample : MonoBehaviour
{
private void Awake()
{
PlayerZeroSdk.OnHotLoadedAvatarIdChanged += OnHotLoadedAvatarIdChanged;
}
private void OnDestroy()
{
PlayerZeroSdk.OnHotLoadedAvatarIdChanged -= OnHotLoadedAvatarIdChanged;
}
private void OnHotLoadedAvatarIdChanged(string avatarId)
{
LoadAvatar(avatarId);
}
public void LoadHotLoadedAvatar()
{
LoadAvatar(PlayerZeroSdk.GetHotLoadedAvatarId());
}
public async Task LoadAvatar(string avatarId)
{
var response = await PlayerZeroSdk.GetAvatarMetadataAsync(avatarId);
var characterRequestConfig = new CharacterRequestConfig()
{
AvatarId = avatarId,
AvatarUrl = response.ModelUrl,
BlueprintId = response.BlueprintId,
Parent = transform
};
var avatarGameObject = await PlayerZeroSdk.InstantiateAvatarAsync(characterRequestConfig);
}
}
A step by step guide to integrate Player Zero into your game via our APIs
Note: these docs are still early access and partially incomplete
You should have been in contact with a member of the Player Zero team.
If you intend to use your own existing character proportions and rig with P0 visuals applied on top, then you should have sent us your base character FBX so we can setup a custom blueprint for you. Note: this is not required if you intend to use the default P0 proportions and P0 rig in your game.
You have should have received confirmation from Player Zero that your account is setup, and you should've been given your Player Zero developer account credentials and/or blueprint id.
If any of the above prerequisites are not true, please reach out to us before continuing.
Using the example http call below, you cantry to test out loading a Player Zero avatar's metadata. You can use any avatar ID, including ones from the playerzero.readyplayer.me platform, or from any test avatar ids we have provided to you.
```
GET https://api.readyplayer.me/v1/characters/:avatarId
```
Example Response:
{
"data": {
"id": "avatarId",
"userId": "userId",
"applicationId": "applicationId",
"blueprintId": "blueprintId",
"assets": {
"iris": [
"irisId"
],
"sclera": [
"scleraId"
],
"hair": [
"hairId"
],
"eyebrows": [
"eyebrowsId"
],
"lipshape": [
"lipshapeId"
],
"eyeshape": [
"eyeshapeId
],
"faceshape": [
"faceshapeId"
],
"top": [
"topId"
],
"bottom": [
"bottomId"
],
"footwear": [
"footwearId"
],
"piercing": [],
"tattoo": [],
"eyeliner": [],
"blemish": [],
"scar": [],
"foundation": [],
"lipstick": [],
"blush": [],
"eyeshadow": [],
"sticker": [],
"cloth": [],
"freckles": [],
"sunburn": [],
"vitiligo": [],
"teeth": [],
"attachment": []
},
"colors": {
"skin": "#B06B45",
"lips": "#C97B7B",
"hair": {
"primary": "#191919",
"secondary": "#583C2F"
},
"beard": {
"primary": "#2e201a",
"secondary": "#543f36"
},
"eyebrows": {
"primary": "#4B3329",
"secondary": "#715447"
},
"eye": "#9d6937",
"eyeshadow": {
"primary": "#0c0804"
}
},
"createdAt": "2025-02-22T13:32:59.906Z",
"updatedAt": "2025-02-22T13:32:59.906Z",
"username": "anonymous",
"modelUrl": "https://avatars.readyplayer.me/:avatarId.glb",
"iconUrl": "https://avatars.readyplayer.me/:avatarId.png"
}
}
Using the modelUrl from the response in step 1, you can make a GET request to that to download the Player Zero avatar GLB. You can also optionally pass a blueprintId as a query parameter to load a version of the Player Zero avatar that matches the proportions and rig of a given blueprint.
```
GET https://avatars.readyplayer.me/:avatarId.glb?targetBlueprintId=:blueprintId
```
Example Response:
.GLB file download response
On the Player Zero platform, avatar ids will be provided to you as a query param in the url that loads the game. In order to hot load an avatar you need to take this avatar id from the url, and pass it to the endpoint in step 1 in order to successfully hot load an avatar. An example of a game url on the Player Zero platform would be the below.
https://playerzero.readyplayer.me/games/my-great-game?avatarId=AVATAR_ID_HERE
The Player Zero APIs support a range of optimization query parameters that enable you to maximize the performance of your avatars for different use-cases. Below are the available parameters that you can add to https://avatars.readyplayer.me/:avatarId.glb API calls.
quality
String
low, medium or high - Use quality presets to combine performance related parameters.
textureSizeLimit
Int
Sets the upper limit for texture resolution in pixels of any texture in the avatar.
textureAtlas
Int
Generates a texture atlas of the desired resolution. The operation merges all meshes and splits opaque objects from transparent ones resulting in a maximum of 2 draw calls.
textureFormat
String
Reduce avatar file size by formatting all textures into the specified format. Using webp encoding can result in up to 40% reduction in avatar file size. Supported values: webp, jpeg, png
morphTargets
String
Comma-separated list of individual morph targets or morph target standard groups to include on the avatar.
textureQuality
String
Choose which texture quality preset to get on the avatar. Options are 'low', 'medium', or 'high'.
meshCompression
Boolean
Whether or not to use mesh compression.
textureChannels
String
Define which textureChannels should be included in the .glb. It can be a comma-separated combination of the following values: baseColor, normal, metallicRoughness, emissive, occlusion.
meshLOD
Int
Control the triangle count of the assets equipped on the avatar.
targetBlueprint
String
The blueprint that the avatar should confirm to. This dictates the rig and the character proportions.
removeSkin
Boolean
Whether or not we should automatically remove parts of the avatar's skin mesh that is covered by clothing.
As part of your partnership with Player Zero, it is crucial that you we receive accurate game events from you about how Player Zero players are using your game. For this we provide a game events endpoint which you can call to provide information about player sessions.
```
POST https://api.readyplayer.me/v1/public/events
```
Example Payload:
{
"data": {
"event": "avatar_session_ended",
"properties": {
"avatar_session_id": "AVATAR_SESSION_ID"
}
}
}
Example Response:
{
"data": {
"event": "avatar_session_ended",
"properties": {
"avatar_session_id": "AVATAR_SESSION_ID"
}
}
}
There are a range of events that we required you to send to this endpoint in different scenarios. These are detailed below.
user_game_session_started
avatar_id: String game_session_id: String game_id: String
When your game launches, or a player starts playing.
user_game_session_ended
game_session_id: String game_id: String
When a player exits your game, or your game stops for any reason.
avatar_session_started
avatar_id: String avatar_session_id: String game_session_id: String game_id: String
When a player starts using their Player Zero avatar in your game.
avatar_session_heartbeat
avatar_session_id: String game_id: String
Fire one event for every minute that a player is using their Player Zero avatar in your game.
avatar_session_ended
avatar_session_id: String game_id: String
When a player stops using their Player Zero avatar in your game, or your game stops for any reason.