Initializing the NakamaSystem #

The first System you need to initialize is the NakamaSystem. This System is responsible for handling connections and authorization with the Nakama server and maintaining the Client, Session and Socket objects.

Add a private variable to store a reference to the NakamaSystem:

1
private NakamaSystem _nakamaSystem;

In order to initialize the NakamaSystem we need to create an AuthorizerFunc which tells Hiro how you want to authorize users against Nakama.

This example creates an authorizer that uses Device Authentication:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
// Authorizer functions
AuthorizerFunc authorizer = async client =>
{
  const string ppAuthToken = "nakama.AuthToken";
  const string ppRefreshToken = "nakama.RefreshToken";
  const string ppDeviceId = "nakama.DeviceId";

  var authToken = PlayerPrefs.GetString(ppAuthToken);
  var refreshToken = PlayerPrefs.GetString(ppRefreshToken);
  var serssion = Session.Restore(authToken, refreshToken);

  // If the session is valid and has not expired, return it
  var expiredDate = DateTime.UtcNow.AddDays(1);
  if (session != null && !session.HasExpired(expiredDate))
  {
    return session;
  }

  var deviceId = PlayerPrefs.GetString(ppDeviceId, SystemInfo.deviceUniqueIdentifier);
  if (deviceId == SystemInfo.unsupportedIdentifier)
  {
    deviceId = System.Guid.NewGuid().ToString();
  }

  try
  {
    session = await client.AuthenticateDeviceAsync(deviceId);

    PlayerPrefs.SetString(ppAuthToken, session.AuthToken);
    PlayerPrefs.SetString(ppRefreshToken, session.RefreshToken);
    PlayerPrefs.SetString(ppDeviceId, deviceId);

    return session;
  }
  catch (Exception ex)
  {
    Debug.LogError($"Error authenticating: {ex.Message}");
    return null;
  }
};

Using the AuthorizerFunc you can now initialize the NakamaSystem and add it to the Systems object you defined earlier:

1
2
3
4
5
6
var scheme = "http";
var host = "127.0.0.1";
var port = 7350;
var serverKey = "defaultKey";
_nakamaSystem = new NakamaSystem(Logger, scheme, host, port, serverKey, authorizer);
_systems.Add(_nakamaSystem);

Using the NakamaSystem #

Accessing the NakamaSystem can be done from within any MonoBehaviour by using the GetSystem extension method defined within Hiro:

1
2
3
4
5
var nakamaSystem = GetSystem<NakamaSystem>();
if (nakamaSystem == null)
{
  Debug.LogError("NakamaSystem not initialized");
}

You can use the NakamaSystem to access Nakama as you normally would through the Client object.

1
var account = await nakamaSystem.Client.GetAccountAsync(nakamaSystem.Session);

The NakamaSystem provides some additional quality of life properties and functions, such as providing direct access to the IApiAccount via the Account property or retrieving a storage object via the ReadStorageObjectAsync function.

Refreshing the NakamaSystem #

To ensure the system has the latest data from Nakama, call the RefreshAsync function.

1
2
3
4
await nakamaSystem.RefreshAsync();

var account = nakamaSystem.Account;
var storageObject = await nakamaSystem.ReadStorageObjectAsync("<Collection>", "<Key>", nakamaSystem.UserId);

Logging events #

The NakamaSystem comes with several methods to facilitate logging pre-defined events for the authorized User.

For example:

1
2
3
4
5
// Log an event to say the user installed and opened the app for the first time
nakamaSystem.Install();

// Log an event to say the user viewed an ad
nakamaSystem.AdImpression("<AdId>", "<Placement>", "<Type>");