# Steam

> Provide a Steam sign-in option to enable players to authenticate using their Steam accounts in your game.

###### SDK 最低版本：2.0.0##minimum-sdk-version-200

本文将引导您完成以下场景，为您游戏中使用 Steam 帐户的玩家设置身份验证：

* 设置 Steam 帐户登录。
* 回归用户登录或创建新用户。
* 将用户从匿名登录更新为通过　Steam 帐户进行平台登录。

要在您的游戏中为玩家提供 Steam 登录选项，请在 SteamWorks Partner Portal 中创建应用，并安装 [Steamworks.Net SDK](https://partner.steamgames.com/doc/webapi_overview/auth)，以便登录用户并获取会话票证。

## 设置 Steam 帐户登录

1. 根据 [Steamworks 文档](https://partner.steamgames.com/doc/store/application#creating_applications)创建应用并记下应用 ID。

2. 根据[使用 Web API 密钥进行身份验证](https://partner.steamgames.com/doc/webapi_overview/auth)文档创建发布者 Web API 密钥。

3. 根据 [Unity 专用 SDK 安装说明](http://steamworks.github.io/installation/)安装 [SteamWorks.Net SDK](https://github.com/rlabrecque/Steamworks.NET/releases)。

   1. 将 SteamWorks.Net SDK 复制到您项目的 *Assets/* 文件夹。
   2. 打开 Unity 项目根目录中的 *steam\_appid.txt* 并将 480 更改为您自己的应用 ID。
   3. 将 Steam Manager 游戏组件添加到该场景中的游戏对象。这样会初始化 Steam 库。
   4. 测试前，您要确保已安装并登录 Steam。Steam 用户能在库中找到您正在开发的游戏。

4. 将 Unity Authentication 中的 ID 提供商设置为 Steam：

   1. 在 Unity 编辑器菜单中，访问 **Edit（编辑）**> **Project Settings…（项目设置…）**，然后从导航菜单中选择 **Services（服务）**> **Authentication（身份验证）**。
   2. 将 **ID Providers（ID 提供商）** 设置为 **Steam**，然后选择 **Add（添加）**。
   3. 在 **App ID（应用 ID）** 文本字段中输入应用 ID。
   4. 在 **Key（密钥）** 文本字段中输入发布者 Web API 密钥，然后选择 **Save（保存）**。

   > **Note:**
   >
   > （可选）添加附加 App ID 以用于 Demo、PlayTest、Alpha 构建。仍然在 **Authentication Settings（身份验证设置）** 中：
   >
   > 1. 选择 **Additional App ID（附加 App ID）** 旁边的箭头。
   > 2. 在展开视图的底部选择 **Add App ID（添加 App ID）**。
   > 3. 在 **App ID** 和 **Description（描述）** 中输入相应的内容。
   > 4. 选择 **Save（保存）**。

5. 使用以下样本代码执行 Steam 登录。请参阅 [GetAuthTicketForWebApi](https://partner.steamgames.com/doc/api/ISteamUser#GetAuthTicketForWebApi) 文档。Unity Authentication SDK 仅接受 Steam 会话票证，不接受加密的应用程序票证。

> **Warning:**
>
> **重要**：必须要注册 Steam SDK 提供的 **OnAuthCallback**。它会进行相应的身份验证票证验证。更多信息，请查看[此处](https://partner.steamgames.com/doc/api/ISteamUser#GetAuthTicketForWebApi)。以下代码是正确进行 Steam 身份验证的示例。**重要**：Unity Player Authentication 仅接受长度在 5 到 30 之间的字母数字字符串作为 **identity** 字段，请确保使用相同的字符串并按照相同的要求来请求票证。

```cs
Callback<GetTicketForWebApiResponse_t> m_AuthTicketForWebApiResponseCallback;
string m_SessionTicket;
string identity = "unityauthenticationservice"

void SignInWithSteam()
{
    // It's not necessary to add event handlers if they are 
    // already hooked up.
    // Callback.Create return value must be assigned to a 
    // member variable to prevent the GC from cleaning it up.
    // Create the callback to receive events when the session ticket
    // is ready to use in the web API.
    // See GetAuthSessionTicket document for details.
    m_AuthTicketForWebApiResponseCallback = Callback<GetTicketForWebApiResponse_t>.Create(OnAuthCallback);

    SteamUser.GetAuthTicketForWebApi(identity);
}

void OnAuthCallback(GetTicketForWebApiResponse_t callback)
{
    m_SessionTicket = BitConverter.ToString(callback.m_rgubTicket).Replace("-", string.Empty);
    m_AuthTicketForWebApiResponseCallback.Dispose();
    m_AuthTicketForWebApiResponseCallback = null;
    Debug.Log("Steam Login success. Session Ticket: " + m_SessionTicket);
    // Call Unity Authentication SDK to sign in or link with Steam, displayed in the following examples, using the same identity string and the m_SessionTicket.
}
```

> **Note:**
>
> **注意**：下面的代码示例假设您已经使用 `GetAuthTicketForWebApi` 方法获得了玩家的 Steam 会话票证，并且已经传递了相同的 `identity` 参数来颁发票证。

## 回归玩家登录或创建新玩家##sign-in-a-returning-player-or-create-new-player

使用 `SignInWithSteamAsync` 方法执行以下操作之一：

* 通过 Steam 凭据创建新的 Unity Authentication 玩家。
* 通过 Steam 凭据登录现有玩家。

如果您的项目中没有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithSteamAsync` 将创建新的玩家帐户。如果您的项目中具有与凭据关联的 Unity Authentication 玩家帐户，`SignInWithSteamAsync` 将登录该玩家帐户。该功能不考虑缓存的玩家帐户，`SignInWithSteamAsync` 会替换缓存的玩家帐户。

```cs
async Task SignInWithSteamAsync(string ticket, string identity)
{
    try
    {
        await AuthenticationService.Instance.SignInWithSteamAsync(ticket, identity);
        Debug.Log("SignIn is successful.");
    }
    catch (AuthenticationException ex)
    {
        // Compare error code to AuthenticationErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
    catch (RequestFailedException ex)
    {
        // Compare error code to CommonErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
}
```

## 将玩家从匿名更新为　Steam 帐户##update-a-player-from-anonymous-to-a-steam-account

在设置完匿名身份验证后，如果玩家想从匿名升级为 Steam 帐户，并使用 Steam 帐户登录，则游戏应提示玩家触发 Steam 登录并从 Steam 获取会话票证。然后，调用 LinkWithSteamAsync API，将玩家关联到 Steam　会话票证。

如果 SDK 上有缓存的玩家帐户，您可以将缓存的玩家帐户与 Steam 帐户关联。

1. 通过 `SignInAnonymouslyAsync` 登录缓存玩家的帐户。
2. 通过 `LinkWithSteamAsync` 将缓存的玩家帐户与 Steam 帐户关联。

```cs
async Task LinkWithSteamAsync(string ticket, string identity)
{
    try
    {
        await AuthenticationService.Instance.LinkWithSteamAsync(ticket, identity);
        Debug.Log("Link is successful.");
    }
    catch (AuthenticationException ex) when (ex.ErrorCode == AuthenticationErrorCodes.AccountAlreadyLinked)
    {
        // Prompt the player with an error message.
        Debug.LogError("This user is already linked with another account. Log in instead.");
    }
    catch (Exception ex)
    {
        Debug.LogError("Link failed.");
        Debug.LogException(ex);
    }
}
```

如果玩家通过登录或创建新玩家配置文件而触发 Steam 登录，并且您已使用相同的 **identity** 参数收到 Steam 访问令牌，请调用以下 API 来对玩家进行身份验证。

```cs
async Task SignInWithSteamAsync(string ticket, string identity)
{
    try
    {
        await AuthenticationService.Instance.SignInWithSteamAsync(ticket, identity);
    }
    catch (AuthenticationException ex)
    {
        // Compare error code to AuthenticationErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
    catch (RequestFailedException ex)
    {
        // Compare error code to CommonErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
}
```

## 回归玩家登录或创建新玩家来登录附加 App ID##sign-in-a-returning-player-or-create-new-player-for-additional-app-ids

使用相同的 `SignInWithSteamAsync` 方法让玩家登录附加 App ID，例如 Demo、PlayTest、Alpha。

> **Note:**
>
> **注意**：下面的代码示例假设您已经使用 `GetAuthTicketForWebApi` 方法获得了玩家的 Steam 会话票证，并且已经传递了相同的 `identity` 参数来颁发票证。

> **Warning:**
>
> **重要**：玩家对于同一项目下的所有 App ID 都采用相同的 Unity Authentication Player ID，因此请尽量设置不同的环境，以使玩家数据（例如，Economy、Cloud Save）限定到每个 App ID，并避免使生产数据与非生产数据混合。

```cs
async Task SignInWithSteamAsync(string ticket, string identity, string appId)
{
    try
    {
        await AuthenticationService.Instance.SignInWithSteamAsync(ticket, identity, appId);
        Debug.Log("SignIn is successful.");
    }
    catch (AuthenticationException ex)
    {
        // Compare error code to AuthenticationErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
    catch (RequestFailedException ex)
    {
        // Compare error code to CommonErrorCodes
        // Notify the player with the proper error message
        Debug.LogException(ex);
    }
}
```

## 实现 Steam 登录身份验证##unlink-steam-account

您可以使用 Steam 会话票证进行登录或关联 Steam 帐户。调用以下 API 登录玩家：`SignInWithSteamAsync(string ticket, string identity)`。

```cs
Unlink Steam account#
Use the `UnlinkSteamAsync` API so your players can unlink their Steam account. Once unlinked, if their account isn’t linked to any additional identity, it transitions to an anonymous account.

async Task UnlinkSteamAsync(string idToken)
{
   try
   {
       await AuthenticationService.Instance.UnlinkSteamAsync(idToken);
       Debug.Log("Unlink is successful.");
   }
   catch (AuthenticationException ex)
   {
       // Compare error code to AuthenticationErrorCodes
       // Notify the player with the proper error message
       Debug.LogException(ex);
   }
   catch (RequestFailedException ex)
   {
       // Compare error code to CommonErrorCodes
       // Notify the player with the proper error message
       Debug.LogException(ex);
   }
}
```
