身份验证 #

我们将首先讨论多人游戏的一个更重要的功能:让玩家能够证明自己的用户身份,并相互交流。

Nakama 可帮助我们实现这一点,其方法是让您可以轻松创建存储和处理数据的集中化服务器,并让玩家(客户端)可以连接到服务器。

建立连接 #

在此我们连接 Unity 客户端和 Nakama 服务器。

第一步是在 Unity 中游戏开始时注册一个新的 Client 对象。该对象将是在客户端和服务器之间进行任何交互的界面。

下面是对客户端进行初始化的主菜单脚本的片段:

Scene01MainMenuController.cs

1
2
var client = new Client("http", "localhost", 7350, "defaultkey", UnityWebRequestAdapter.Instance);
client.Timeout = 5;

在此我们传送以下连接值,创建连到您在本地启动的服务器(位于 http://localhost:7350)的连接:

  • Scheme:连接方案,此处为 http
  • Host:服务器主机,对于本例为 localhost
  • Port:服务器端口,默认设置为 7350
  • ServerKey:默认使用 defaultkey。可通过服务器配置更改。

设备身份验证 #

建立服务器连接后,我们对玩家进行身份验证,以便我们可以将他们连接到一个标识。

启动 Pirate Panic 时,您可能会注意到您已自动经过身份验证并被分配了一个用户名。这种类型的无缝身份验证是设备身份验证,它创建与运行游戏的设备(例如手机或计算机)相关联的帐户。

在 Unity 中,完成设备身份验证的方法是获取设备 ID 并将其传递到 AuthenticateDeviceAsync

1
2
string deviceId = SystemInfo.deviceUniqueIdentifier;
session = await client.AuthenticateDeviceAsync(deviceId);
如面向 WebGL 构建,您可能需要使用 System.Guid.NewGuid().ToString() 而非 deviceUniqueIdentifier

身份验证完成后,玩家加入会话,这表示玩家登录的一个时间段。参见会话,了解详情。

会话对象可让我们主要通过 SocketAccount 对象,发出请求和访问用户信息:

1
2
3
var socket = client.NewSocket(useMainThread: true);
await socket.ConnectAsync(session);
account = await client.GetAccountAsync(session);

在 Pirate Panic 中,clientsocketaccountsession 属性保存在 GameConnection 对象中。以后任何一次访问 _connection,记住这指的是这些属性。

您可以根据需要组织服务器连接,只要确保它可以被其他类访问。

Facebook 身份验证 #

设备身份验证使玩家可以轻松地直接进入游戏,但是将帐户链接到设备意味着如果设备丢失或重置,则帐户将丢失。通过外部社交服务提供商(如 Facebook)连接到用户帐户,可以缓解此问题并获取其他用户信息。

如果您克隆了项目存储库,Pirate Panic 代码中包含了 Facebook SDK。如您启动了自己的项目,您需要获取 SDK

将 Facebook SDK 加入场景脚本,并按如下方式对其进行初始化:

1
2
3
4
5
6
7
8
using Facebook.Unity;
..
private void InitializeFacebook() {
    FB.Init(() =>
    {
        FB.ActivateApp();
    });
}

然后,以下片段处理登录:

ProfileUpdatePanel.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
private void LinkFacebook()
{
    List<string> permissions = new List<string>();
    permissions.Add("public_profile");

    FB.LogInWithReadPermissions(permissions, async result =>
    {
        string facebookToken = result.AccessToken.TokenString;
        await _connection.Client.AuthenticateFacebookAsync(facebookToken);
    });
}
您可以选择将 LinkFacebook 绑定到 Connect Facebook 按钮,以便玩家可以选择何时登录,而不是被迫立即登录。

此处我们给出了 public_profile 权限,因此 Nakama 可以访问用户名或个人资料图片等基本的用户信息。您还可以添加其他权限和功能,这些都包含在 Facebook SDK 文档中。

登录 Facebook,将自动将玩家的 Facebook 好友添加到其游戏内好友列表。

初始化新玩家 #

在玩家有了登录的方法后,接下来是设置初始玩家信息,以便他们可以开始添加好友、收集宝石、完成任务或其他需要不断存储用户数据的内容。

这可以使用 register 挂钩,在服务器端完成。对于每个身份验证方法,有一个不同的挂钩。例如,因为我们设置了设备和 Facebook 身份验证,我们应当使用 registerAfterAuthenticateDeviceregisterAfterAuthenticateFacebook

我们将一个函数绑定到它们,触发此挂钩时,函数即运行:

main.ts

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
initializer.registerAfterAuthenticateDevice(afterAuthenticateDeviceFn);

const afterAuthenticateDeviceFn: nkruntime.AfterHookFunction<nkruntime.Session, nkruntime.AuthenticateDeviceRequest> = function(ctx: nkruntime.Context, logger: nkruntime.Logger, nk: nkruntime.Nakama, data: nkruntime.Session, req: nkruntime.AuthenticateDeviceRequest) {
    afterAuthenticate(ctx, logger, nk, data);

    if (!data.created) {
        return; // Account already exists.
    }
    ...
    // Player initialization goes here. Write initial stats, add items to inventory, etc.
}

会话令牌 #

出于安全原因,在您在 Nakama 配置中定义的时间段后,玩家会话将自动过期。为了避免强制玩家不断重新登录,我们可以设置一个方法,在旧会话即将到期时自动请求新会话。

其实现方法是将身份验证令牌保存到客户端,定期将其传回服务器,以请求新的令牌。

令牌有两种:

  • 访问令牌:将客户端标识告诉服务器,让服务器信任此客户端。
  • 刷新令牌:用于请求新的访问令牌。

通过 Nakama,我们可以用 client 对象通过 SessionRefreshAsync 请求新的令牌:

Scene01MainMenuController.cs

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
string authToken = PlayerPrefs.GetString("nakama.authToken", null);
string refreshToken = PlayerPrefs.GetString("nakama.refreshToken", null);

session = Session.Restore(authToken, refreshToken);

// Check whether a session is close to expiry.
if (session.HasExpired(DateTime.UtcNow.AddDays(1))) {
    try {
        // get a new access token
        session = await client.SessionRefreshAsync(session);
    } catch (ApiResponseException) {
        // get a new refresh token
        session = await client.AuthenticateDeviceAsync(deviceId);
        PlayerPrefs.SetString("nakama.refreshToken", session.RefreshToken);
    }

    PlayerPrefs.SetString("nakama.authToken", session.AuthToken);
}

此处我们使用 Unity 的内置 PlayerPrefs 引擎存储访问令牌,并将令牌分别刷新到 nakama.authTokennakama.refreshToken。 如果会话离到期还有不到一天,脚本将尝试用 SessionRefreshAsync 请求新的访问令牌。如果刷新令牌无效,这将失败,我们将需要从头开始重新进行身份验证。

下一主题 #

好友和聊天

Related Pages