---
metadata:
  - name: generator
    content: Diplodoc Platform v5.52.0
alternate:
  - https://yandex.com/dev/games/doc/en/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/hi/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/ko/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/ru/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/tr/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/vi/sdk/sdk-player.md
  - https://yandex.com/dev/games/doc/zh/sdk/sdk-player.md
  - href: zh/sdk/sdk-player.md
    type: text/markdown
    title: Markdown version
  - href: ../llms.txt
    type: text/markdown
    title: llms.txt
---
> **Documentation Index:** Fetch the complete configuration index at https://yandex.com/dev/games/doc/zh/llms.txt

# 玩家数据

<!-- source: zh/_includes/script-common.md -->
<!-- source: zh/_includes/script/index-js.md -->

<!-- endsource: zh/_includes/script/index-js.md -->

<!-- source: zh/_includes/script/requirements-js.md -->

<!-- endsource: zh/_includes/script/requirements-js.md -->

<!-- source: zh/_includes/script/image-modal-js.md -->

<!-- endsource: zh/_includes/script/image-modal-js.md -->
<!-- endsource: zh/_includes/script-common.md -->

您可以：

- 使用 SDK 方法将游戏数据（完成的关卡、经验、应用内购买等）保存到 Yandex 服务器，或将其传输到您自己的服务器。云存档允许用户在不同设备上继续游戏。
- 使用 Yandex 用户个人资料中的数据（例如姓名）对游戏进行个性化。

`Player` 对象可用于处理用户数据。

## 初始化 {#getplayer}

要初始化 `Player` 对象，请使用 `ysdk.getPlayer()` 方法：

```javascript showLineNumbers
const ysdk = await YaGames.init();

try {
    const player = await ysdk.getPlayer();
} catch (e) {
    // 初始化 Player 对象时出错。
}
```

初始化 `Player` 对象时会传入以下数据：

- 用户ID —— 所有玩家都会包含。
- 头像和名称 —— 仅限已授权玩家。
- 平台内购数据（仅适用于[支持应用内购买](https://yandex.com/dev/games/doc/zh/console/purchases.md)的游戏）—— 仅限俄罗斯地区玩家。

有关这些参数的更多信息，请参阅[用户个人资料数据](#profile-data)。

访问用户数据取决于其[个人资料](https://yandex.com/games/user){.external}中的隐私设置。如果玩家禁止访问个人数据，响应中将只包含用户ID。

要授权用户并在您的服务器上保存游戏状态数据，请使用可选参数 `{ signed: true }` 和 `fetch()` 方法。这将允许您使用[密钥](https://yandex.com/dev/games/doc/zh/sdk/sdk-purchases.md#key-example)验证玩家的真实性并避免可能的作弊。密钥在[连接应用内购买](https://yandex.com/dev/games/doc/zh/console/purchases.md#connect)后可用。

```javascript showLineNumbers
const ysdk = await YaGames.init();

try {
    const player = await ysdk.getPlayer({ signed: true });

    // 使用 player.signature 在您的服务器上进行授权。
    const authData = await fetch('https://your.game.server/auth', {
        method: 'POST',
        headers: { 'Content-Type': 'text/plain' },
        body: player.signature
    });
} catch (e) {
    // 初始化 Player 对象或授权时出错。
}
```

发送到服务器的请求中的 `signature` 参数包含 Yandex 个人资料中的用户数据和签名。该参数由两个 `base64` 编码的字符串组成：

```text
<签名>.<个人资料数据>
```

详情请参见[防作弊保护](https://yandex.com/dev/games/doc/zh/sdk/sdk-purchases.md#signature)。

{% note info %}

请求的发送频率不能超过每5分钟20次，否则将会因错误而被拒绝。

{% endnote %}


## 用户授权 {#auth}

### 检查授权 {#auth-check}

要检查玩家是否已在 Yandex 上授权，请使用 `Player` 对象的 `player.isAuthorized()` 方法。该方法返回 `true | false`。

{% note alert %}

方法 `player.getMode(): 'lite' | ''` 已弃用，未来将从接口中移除。

{% endnote %}


### 调用授权对话框 {#open-auth-dialog}

要调用授权窗口，请使用 `ysdk.auth.openAuthDialog()` 方法。

{% note warning %}

将授权的好处通知用户。如果用户不了解授权的必要性，很可能会拒绝授权并退出游戏。

详细信息请参阅[授权提案](https://yandex.com/dev/games/doc/zh/requirements/1/2.md#auth-offer)。

{% endnote %}


```javascript showLineNumbers
const ysdk = await YaGames.init();

try {
    let player = await ysdk.getPlayer();

    // 玩家未授权。
    if (!player.isAuthorized()) {
        try {
            // 打开授权窗口。
            await ysdk.auth.openAuthDialog();

            const authorizedPlayer = await ysdk.getPlayer();

            player = authorizedPlayer;
        } catch (e) {
            // 玩家授权或重新初始化 Player 对象时出错。
        }
    }
    // 玩家已成功授权。
} catch (err) {
    // 初始化 Player 对象时出错。
}
```

## 游戏内数据 {#ingame-data}

要处理用户的游戏内数据，请使用 `Player` 对象方法。

### player.setData(data, flush) {#setdata}

保存用户数据。每个玩家的数据大小上限为 200&nbsp;KB。

**方法签名**

```typescript
function setData(data: object, flush: boolean) => Promise<void> {}
```

接受参数：

<div class="table-25 table-2c25">

#|
|| **参数** | **类型** | **说明** ||
||`data` | `object` | 包含键值对的对象。 ||
|| `flush` | `boolean` | 确定数据发送的优先级:
- `true` —— 数据将立即发送到服务器。
- `false`（默认值）—— 数据发送请求将排队等待。 ||
|#

</div>

该方法返回 `Promise`，表示数据是否保存成功。

当参数值为 `flush: false` 时，返回的结果仅显示数据有效性（数据发送已排入队列，将在稍后执行）。此时，`player.getData()` 方法将返回最后一次调用 `player.setData()` 设置的数据，即使这些数据尚未发送。

{% note info %}

请求的发送频率不能超过每5分钟100次，否则将会因错误而被拒绝。

{% endnote %}

#### 示例 {#example-setdata}

```javascript showLineNumbers
const ysdk = await YaGames.init();

const player = await ysdk.getPlayer();

await player.setData({
    achievements: ['trophy1', 'trophy2', 'trophy3'],
})

console.log('data is set');
```

### player.getData(keys) {#getdata}

异步返回存储在 Yandex 数据库中的游戏内用户数据。

**方法签名**

```typescript
function getData(keys?: Array<string>) => Promise<object> {}
```

接受参数：

<div class="table-25 table-2c25">

#|
|| **参数** | **类型** | **说明** ||
|| `keys` | `Array<string>` | 需要返回的键列表。如果缺少 `keys` 参数，该方法将返回用户的所有游戏内数据。 ||
|#

</div>

该方法返回 `Promise<object>`，其中的对象包含键值对。

{% note info %}

请求的发送频率不能超过每5分钟100次，否则将会因错误而被拒绝。

{% endnote %}

### player.setStats(stats) {#setstats}

保存用户的数值数据。每个玩家的数值数据大小上限为 10&nbsp;KB。

{% note tip %}

对于频繁变化的数值（得分、经验值、游戏货币），应使用该方法，而不是 [player.setData()](#ingame-data).

{% endnote %}

**方法签名**

```typescript
function setStats(stats?: object) => Promise<void> {}
```

接受参数：

<div class="table-25 table-2c25">

#|
|| **参数** | **类型** | **说明** ||
|| `stats` | `object` | 包含键值对的对象，其中每个值必须是数字。 ||
|#

</div>

该方法返回 `Promise`，表示数据是否保存成功。

{% note info %}

请求的发送频率不能超过每1分钟60次，否则将会因错误而被拒绝。

{% endnote %}

### player.incrementStats(increments) {#incrementstats}

更改用户的数值数据。每个玩家的数值数据大小上限为 10&nbsp;KB。

**方法签名**

```typescript
function incrementStats(increments: object) => Promise<object> {}
```

接受参数：

<div class="table-25 table-2c25">

#|
|| **参数** | **类型** | **说明** ||
|| `increments` | `object` | 包含键值对的对象，其中每个值必须是数字。 ||
|#

</div>

该方法返回 `Promise<object>`，其中的对象包含更改和添加的键值对。

{% note info %}

请求的发送频率不能超过每1分钟60次，否则将会因错误而被拒绝。

{% endnote %}

### player.getStats(keys) {#getstats}

异步返回用户的数值数据。

**方法签名**

```typescript
function getStats(keys?: Array<string>) => Promise<object> {}
```

接受参数：

<div class="table-25 table-2c25">

#|
|| **参数** | **类型** | **说明** ||
|| `keys` | `Array<string>` | 需要返回的键列表。如果缺少 `keys` 参数，该方法将返回用户的所有数值数据。 ||
|#

</div>

该方法返回 `Promise<object>`，其中的对象包含键值对。

{% note info %}

请求的发送频率不能超过每1分钟60次，否则将会因错误而被拒绝。

{% endnote %}


## 用户个人资料数据 {#profile-data}

要从 Yandex 用户个人资料中获取数据，请使用 `Player` 对象方法。

### player.getUniqueID() {#getuniqueid}

返回用户的唯一永久 ID。

**方法签名**

```typescript
function getUniqueID() => string {}
```

{% note info %}

方法 `player.getID()` 已弃用，但仍可以继续使用，这会在错误控制台中引发警告。

一般来说，对于某个 `Player` 对象，player.getID() 和 `player.getUniqueID()` 的值并不相同，但对于某些用户来说却可能是相同的。如果值不同且游戏本身已将某些数据关联到 `player.getID()` 值，则您需要迁移该数据并将其关联到 `player.getUniqueID()` 的值。要一次性迁移所有用户的数据，请联系[支持服务](https://yandex.com/dev/games/doc/zh/concepts/troubleshooting.md).

{% endnote %}


### player.getIDsPerGame() {#getidspergame}

{% note alert %}

该请求仅供已授权用户使用。如何检查授权状态和调用登录对话框，请参见[用户授权](#auth)。

在发送请求之前，请使用 `ysdk.isAvailableMethod('player.getIDsPerGame')` 检查该方法的可用性。该方法返回 `Promise<Boolean>`。

{% endnote %}

该方法返回对象数组，其中包含用户在开发者所有游戏中的 ID，前提是用户明确同意传输个人数据。

**方法签名**

```typescript
function getIDsPerGame() => Promise<Array<{ appID: number, userID: string }>> {}
```

### player.getName() {#getname}

返回用户的名称。

**方法签名**

```typescript
function getName() => string {}
```

### player.getPhoto() {#getphoto}

根据请求的图像大小返回用户头像的 URL。

**方法签名**

```typescript
function getPhoto(size: 'small' | 'medium' | 'large') => string {}
```

### player.getPayingStatus() {#getpayingstatus}

返回取决于用户购买频率和金额的值。

**方法签名**

```typescript
function getPayingStatus() => EPayingStatus {}
```

`EPayingStatus` 可取以下值之一：

#|
|| **值** | **说明** ||
|| `paying` | 用户在过去一个月内购买了价值超过500卢布的平台货币。 ||
|| `partially_paying` | 用户在过去一年内至少有一次用真实货币购买平台货币的记录。 ||
|| `not_paying` | 用户在过去一年内没有用真实货币购买平台货币。 ||
|| `unknown` | 用户不在俄罗斯联邦，或者用户未允许向开发者传输此类信息。 ||
|#

#### 示例 {#example-status}

```javascript showLineNumbers
const ysdk = await YaGames.init(); // 初始化 SDK。
const player = await ysdk.getPlayer(); // 获取玩家。
const payingStatus = player.getPayingStatus(); // 获取用户在平台上的付费活跃度状态。

if (payingStatus === 'paying' || payingStatus === 'partially_paying') {
    // 在开始时或代替广告提供应用内商品。
}
```

## 方法限制 {#limits}

#|
|| **方法** | **说明** | **限制** ||
|| `ysdk.getPlayer()` | [初始化 `Player` 对象](#getplayer) |::{align="center"} 5分钟内20次请求 ||
|| `player.setData()` | [保存用户数据](#setdata) |::{align="center"} 5分钟内100次请求 ||
|| `player.getData()` | [异步返回用户的游戏内数据](#getdata) | ^ ||
|| `player.setStats()` | [保存用户的数值数据](#setstats) |::{align="center"} 1分钟内60次请求 ||
|| `player.getStats()` | [异步返回用户的数值数据](#getstats) | ^ ||
|| `player.incrementStats()` | [修改用户的数值数据](#incrementstats) | ^ ||
|#

## iOS 进度丢失 {#progress-loss}

如果您使用自己的域名集成游戏，`localStorage` 在新版 iOS 中可能会经常重置，这会导致玩家进度丢失。为避免发生这种情况，请使用与 `localStorage` 具有相同接口的 `safeStorage`：

```javascript showLineNumbers
const ysdk = await YaGames.init();

const safeStorage = await ysdk.getStorage();

safeStorage.setItem('key', 'safe storage is working');
console.log(safeStorage.getItem('key'));
```

为了避免手动更改代码，请全局重新定义 `localStorage`。

{% note alert %}

重新定义前请确保 `localStorage` 不在使用中。

{% endnote %}


```javascript showLineNumbers
const ysdk = await YaGames.init();

const safeStorage = await ysdk.getStorage();

Object.defineProperty(window, 'localStorage', { get: () => safeStorage });

localStorage.setItem('key', 'safe storage is working');
console.log(localStorage.getItem('key'));
```

如果您将源代码作为存档上传，则不需要执行任何操作：SDK 中的特殊包装器会自动使 `localStorage` 变得可靠。


## 问题解决 {#faq}

#### 如果保存大小超过SDK限制怎么办？ {#large-saves}

SDK方法对每个玩家的最大数据大小有限制：

#|
|| **方法** | **描述** | **限制** ||
|| `player.setData()` | [用户数据](#setdata) | 200 KB ||
|| `player.setStats()` | [统计数据（数值）](#setstats) | 10 KB ||
|#

如果您的游戏需要保存更多数据（例如，在拥有大量单位或复杂世界状态的策略游戏中），请使用您自己的服务器来存储进度。有关数据存储方法的更多信息，请参阅[保存进度的位置](https://yandex.com/dev/games/doc/zh/requirements/1/9.md#save-location)。

#### 如何通过代码重置玩家进度？ {#reset-progress}

要清除玩家数据，请使用[player.setData()](#setdata)和[player.setStats()](#setstats)方法写入空进度。

要测试进度重置，您还可以使用[debug面板](https://yandex.com/dev/games/doc/zh/console/debug-panel.md#cloud-icon)上的☁️ **Clear cloud data**按钮。


---

<!-- source: zh/_includes/sdk-support.md -->
{% note info %}

技术支持团队将协助您将已完成的游戏发布到 Yandex 游戏平台。关于开发和测试方面的具体问题，其他开发人员将在[Discord 频道](https://discord.com/invite/wU4p3whr4T){.external}中进行回答。

{% endnote %}

如果您遇到 Yandex Games SDK 方面的问题或有其他问题想要咨询，请联系支持部门：

<!-- source: zh/_includes/button-chat.md -->
<a href="https://yandex.com/chat/#/user/a4fa5c06-75db-9b38-6eea-b1673785f7d5">
  <span class="button">写入聊天信息</span>
</a>
<!-- endsource: zh/_includes/button-chat.md -->
<!-- endsource: zh/_includes/sdk-support.md -->
