> For the complete documentation index, see [llms.txt](https://docs.convai.com/api-docs/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/long-term-memory/usage-examples.md).

# 长期记忆使用示例

Unity 中四个完整的长期记忆模式——零配置持久化、认证身份、记忆初始化和记忆重置。

这些示例涵盖了四种最常见的长期记忆集成模式。每个示例都是自包含的，并展示了完整设置、相关代码以及预期的运行时结果。

### 模式 1 — 零配置持久化

使用 `DeviceEndUserIdProvider` （SDK 默认）当你不需要按账户划分的记忆时使用。无需编写代码。在控制台中启用 LTM，SDK 会自动处理身份和存储。

**适用场景：** 没有用户账户的消费类应用、快速原型，或基于编辑器的测试。

**限制：** 记忆仅限于设备。清除 `PlayerPrefs` 或重新安装应用会生成新的身份——不会保留任何记忆。

**设置：**

1. 在以下位置登录： [convai.com](https://convai.com)，打开角色，并切换 **长期记忆** 到 **开启** 中找到它，位于 **Memory** 选项卡之外，不会有任何 tick。
2. 添加 `ConvaiManager` 和 `ConvaiCharacter` 到你的场景，并配置好角色 ID。
3. 进入播放模式并进行对话。停止播放模式以触发记忆提取。
4. 重新进入播放模式并验证角色是否记住了之前分享的内容。

没有 `IEndUserIdentityProvider` 需要注册。SDK 默认使用 `DeviceEndUserIdProvider` 作为默认值。

**预期结果：** 角色会自动引用先前会话中的事实。相同的 GUID 在 `PlayerPrefs["convai.end_user_id"]` 会在同一台机器上的每个会话中使用。

***

### 模式 2 — 已认证身份

使用自定义的 `IEndUserIdentityProvider` 当用户使用账户登录时。这可确保记忆能跨设备和重新安装跟随用户。

**适用场景：** 具有用户认证的应用——企业培训平台、入职系统、带账户的消费类应用。

```csharp
using Convai.Domain.Identity;

public class AccountIdentityProvider : IEndUserIdentityProvider
{
    private readonly string _accountId;

    public AccountIdentityProvider(string accountId)
    {
        _accountId = accountId;
    }

    public string GetEndUserId()
    {
        return _accountId;
    }
}
```

在 `Awake()` 之前 `ConvaiRoomManager.Start()` 完成：

```csharp
using Convai.Runtime.Components;
using UnityEngine;

public class IdentityRegistrar : MonoBehaviour
{
    [SerializeField] private ConvaiManager _convaiManager;

    private void Awake()
    {
        string accountId = AuthService.CurrentUser.AccountId;
        _convaiManager.SetEndUserIdentityProvider(new AccountIdentityProvider(accountId));
    }
}
```

可选地附加显示名称，这样编辑器的长期记忆面板会显示可读标签而不是原始 ID：

```csharp
using System.Collections.Generic;
using Convai.Domain.Identity;

public class AccountMetadataProvider : IEndUserMetadataProvider
{
    private readonly string _displayName;

    public AccountMetadataProvider(string displayName)
    {
        _displayName = displayName;
    }

    public IReadOnlyDictionary<string, object> GetEndUserMetadata()
    {
        return new Dictionary<string, object> { { "name", _displayName } };
    }
}
```

```csharp
_convaiManager.SetEndUserMetadataProvider(
    new AccountMetadataProvider(AuthService.CurrentUser.DisplayName));
```

**预期结果：** 每个用户的记忆都存储在其账户 ID 下。记忆会跨设备和重新安装保留。编辑器面板会显示用户的显示名称。

***

### 模式 3 — 首次会话前预先播种记忆

在用户第一次对话之前预加载事实，以便角色从一开始就能引用已完成的模块、认证或入职状态。

{% hint style="danger" %}
**不要在面向玩家的构建中发布此模式。** `ConvaiRestClient` 需要你的 API 密钥。在分发的应用中嵌入 API 密钥会使其面临被提取的风险。仅应从服务器端服务或编辑器工具运行记忆播种。
{% endhint %}

```csharp
using Convai.RestAPI;
using System.Collections.Generic;
using UnityEngine;

public class OnboardingMemorySeeder : MonoBehaviour
{
    // 仅限编辑器 / 服务器端使用 — 切勿在嵌入 API 密钥的情况下发布
    [ContextMenu("播种新员工记忆")]
    private async void SeedEmployeeMemory()
    {
        string characterId = "onboarding-assistant-id";
        string employeeAccountId = "emp-00421";

        var certifications = new List<string>
        {
            "员工于 2025-04-10 完成了消防安全一级。",
            "员工于 2025-04-15 完成了危险材料处理。",
            "员工尚未完成受限空间进入认证。"
        };

        using var client = new ConvaiRestClient(ConvaiSettings.Instance.ApiKey);
        var response = await client.Memory.AddAsync(characterId, employeeAccountId, certifications);

        Debug.Log($"已播种 {response.Memories.Count} 条记忆记录。");
    }
}
```

**预期结果：** 在员工与入职助手的第一次对话中，角色已经知道其认证状态，并会引导他们进入下一项必需模块。

***

### 模式 4 — 重置用户的记忆

清除某个用户–角色对中的所有已存事实，然后可选地禁用 LTM。当用户记录已过期或在测试会话之间重置时使用。

```csharp
using Convai.RestAPI;
using UnityEngine;

public class MemoryReset : MonoBehaviour
{
    [ContextMenu("清除记忆然后禁用 LTM")]
    private async void PurgeAndDisable()
    {
        string characterId = "your-character-id";
        string endUserId = "target-end-user-id";

        using var client = new ConvaiRestClient(ConvaiSettings.Instance.ApiKey);

        // 步骤 1：删除此用户–角色对的所有记忆
        await client.Memory.DeleteAllAsync(characterId, endUserId);
        Debug.Log("记忆已清除。");

        // 步骤 2：在角色上禁用 LTM
        await client.Characters.SetMemoryEnabledAsync(characterId, false);
        Debug.Log("长期记忆已禁用。");
    }
}
```

如果只想移除记忆而保持 LTM 启用，请调用 `DeleteAllAsync` 并跳过 `SetMemoryEnabledAsync` 步骤。若要删除某个用户在所有角色中的记录，而不是仅删除单个角色中的记录，请改用 `client.EndUsers.DeleteAsync(endUserId)` 。另请参阅 [管理终端用户记录](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/long-term-memory/end-user-management.md).

**预期结果：** 此用户–角色对的下一次会话将从没有已存上下文开始。角色会将该用户视为新联系人。

***

### 下一步

{% content-ref url="/pages/0b7e1084a14c3bcf13fec179ad83b458f07ecff4" %}
[记忆管理 API](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/long-term-memory/memory-management-api.md)
{% endcontent-ref %}

{% content-ref url="/pages/9c55a31cd790424665e521972bff5affc2dbe7f9" %}
[长期记忆脚本参考](/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/long-term-memory/long-term-memory-scripting-reference.md)
{% endcontent-ref %}


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter, and the optional `goal` query parameter:

```
GET https://docs.convai.com/api-docs/zh/cha-jian-yu-ji-cheng/convai-unity-sdk/features/long-term-memory/usage-examples.md?ask=<question>&goal=<endgoal>
```

`ask` is the immediate question: it should be specific, self-contained, and written in natural language.
`goal` is optional and describes the broader end goal you are ultimately trying to accomplish on behalf of the user. GitBook uses it to tailor the answer towards what is most useful for that goal.

The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
