Adapty 使用 `AdaptySDK` 命名空间。在使用 Adapty SDK 的脚本文件顶部,你可以添加:
```csharp showLineNumbers title="C#"
using AdaptySDK;
```
订阅 Adapty 事件:
```csharp showLineNumbers title="C#"
using UnityEngine;
using AdaptySDK;
public class AdaptyListener : MonoBehaviour, AdaptyEventListener {
public void OnLoadLatestProfile(AdaptyProfile profile) {
// handle updated profile data
}
public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { }
public void OnInstallationDetailsFail(AdaptyError error) { }
}
```
我们建议调整脚本执行顺序,将 AdaptyListener 放在 Default Time 之前,以确保 Adapty 尽早完成初始化。
接下来,在应用中配置付费墙:
- 如果您使用 [Adapty 付费墙编辑工具](adapty-paywall-builder),请先[激活 AdaptyUI 模块](#activate-adaptyui-module-of-adapty-sdk),然后按照[付费墙编辑工具快速入门](unity-quickstart-paywalls)进行操作。
- 如果您自行构建付费墙 UI,请参阅[自定义付费墙快速入门](unity-quickstart-manual)。
## 激活 Adapty SDK 的 AdaptyUI 模块 \{#activate-adaptyui-module-of-adapty-sdk\}
如果您计划使用[付费墙编辑工具](adapty-paywall-builder)并已安装 AdaptyUI 模块,则需要激活 AdaptyUI。您可以在配置过程中激活它:
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetActivateUI(true);
```
## 可选设置 \{#optional-setup\}
### 日志记录 \{#logging\}
#### 配置日志系统 \{#set-up-the-logging-system\}
Adapty 会记录错误和其他重要信息,帮助你了解运行情况。以下是可用的日志级别:
| Level | Description |
| ---------- | ------------------------------------------------------------ |
| `error` | 仅记录错误日志 |
| `warn` | 记录错误以及 SDK 中不会导致严重错误但值得关注的消息 |
| `info` | 记录错误、警告及各类信息消息 |
| `verbose` | 记录所有可能在调试时有用的附加信息,例如函数调用、API 请求等 |
你可以在配置 Adapty 时设置应用的日志级别:
```csharp showLineNumbers title="C#"
// 'verbose' is recommended for development and the first production release
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY");
builder.LogLevel = AdaptyLogLevel.Verbose;
```
你也可以在运行时动态修改日志级别:
```csharp showLineNumbers title="C#"
Adapty.SetLogLevel(AdaptyLogLevel.Verbose, (error) => {
// handle result
});
```
### 数据政策 \{#data-policies\}
Adapty 不会存储用户的个人数据,除非您明确发送,但您可以实施额外的数据安全策略,以符合应用商店或所在国家/地区的法规要求。
#### 禁用 IP 地址采集与共享 \{#disable-ip-address-collection-and-sharing\}
在激活 Adapty 模块时,将 `SetIPAddressCollectionDisabled` 设置为 `true` 即可禁用用户 IP 地址的采集与共享。默认值为 `false`。
使用此参数可增强用户隐私保护、遵守地区性数据保护法规(如 GDPR 或 CCPA),或在应用不需要基于 IP 的功能时减少不必要的数据采集。
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetIPAddressCollectionDisabled(true);
```
#### 禁止采集和共享广告 ID \{#disable-advertising-id-collection-and-sharing\}
在激活 Adapty 模块时,将 `SetAppleIDFACollectionDisabled` 和/或 `SetGoogleAdvertisingIdCollectionDisabled` 设置为 `true` 可禁用广告标识符的收集。默认值为 `false`。
如需遵守 App Store/Google Play 政策、避免触发 App 跟踪透明度提示,或者你的应用不需要基于广告 ID 的广告归因或分析功能,可使用此参数。
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetAppleIDFACollectionDisabled(true)
.SetGoogleAdvertisingIdCollectionDisabled(true);
```
#### 为 AdaptyUI 配置媒体缓存 \{#set-up-media-cache-configuration-for-adaptyui\}
默认情况下,AdaptyUI 会缓存媒体内容(如图片和视频),以提升性能并减少网络流量。你可以通过提供自定义配置来调整缓存设置。
使用 `SetAdaptyUIMediaCache` 覆盖默认缓存设置:
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetAdaptyUIMediaCache(
100 * 1024 * 1024, // MemoryStorageTotalCostLimit 100MB
null, // MemoryStorageCountLimit
100 * 1024 * 1024 // DiskStorageSizeLimit 100MB
);
```
参数:
| 参数 | 是否必填 | 描述 |
|-----------------------------|----------|---------------------------------------------------|
| memoryStorageTotalCostLimit | 可选 | 内存缓存大小(字节)。默认值因平台而异。 |
| memoryStorageCountLimit | 可选 | 内存存储的条目数量上限。默认值因平台而异。 |
| diskStorageSizeLimit | 可选 | 磁盘文件大小上限(字节)。默认值因平台而异。 |
### 启用本地访问等级(Android) \{#enable-local-access-levels-android\}
默认情况下,[本地访问等级](local-access-levels)在 iOS 上已启用,在 Android 上已禁用。若要在 Android 上同样启用,请将 `SetGoogleLocalAccessLevelAllowed` 设置为 `true`:
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetGoogleLocalAccessLevelAllowed(true);
```
### 备份恢复时清除数据 \{#clear-data-on-backup-restore\}
当 `SetAppleClearDataOnBackup` 设置为 `true` 时,SDK 会检测应用从 iCloud 备份恢复的情况,并删除所有本地存储的 SDK 数据,包括已缓存的用户画像信息、产品详情和付费墙。之后 SDK 将以全新状态完成初始化。默认值为 `false`。
:::note
仅删除本地 SDK 缓存。Apple 的交易记录及 Adapty 服务器上的用户数据不受影响。
:::
```csharp showLineNumbers title="C#"
var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY")
.SetAppleClearDataOnBackup(true);
```
## 故障排查 \{#troubleshooting\}
#### Android 备份规则(Auto Backup 配置) \{#android-backup-rules-auto-backup-configuration\}
部分 SDK(包括 Adapty)会自带 Android 自动备份配置。如果多个 SDK 都定义了备份规则,Android 清单合并工具可能会报错,提示 `android:fullBackupContent`、`android:dataExtractionRules` 或 `android:allowBackup` 相关问题。
常见错误示例:`Manifest merger failed: Attribute application@dataExtractionRules value=(@xml/your_data_extraction_rules)
is also present at [com.other.sdk:library:1.0.0] value=(@xml/other_sdk_data_extraction_rules)`
:::note
以下更改应在你的 Android 平台目录(通常位于项目的 `android/` 文件夹)中进行。
:::
要解决此问题,你需要:
- 告知清单合并工具使用应用自身的备份相关属性值。
- 创建备份规则文件,将 Adapty 的规则与其他 SDK 的规则合并。
#### 1. 在清单中添加 `tools` 命名空间 \{#1-add-the-tools-namespace-to-your-manifest\}
在 `AndroidManifest.xml` 文件中,确保根标签 `
2. 将以下内容添加到 `/Assets/Plugins/Android/launcherTemplate.gradle`:
```groovy showLineNumbers
apply plugin: 'com.android.application'
// highlight-next-line
apply plugin: 'kotlin-android'
apply from: 'setupSymbols.gradle'
apply from: '../shared/keepUnitySymbols.gradle'
```
3. 将以下内容添加到 `/Assets/Plugins/Android/baseProjectTemplate.gradle`:
```groovy showLineNumbers
plugins {
// If you are changing the Android Gradle Plugin version, make sure it is compatible with the Gradle version preinstalled with Unity
// See which Gradle version is preinstalled with Unity here https://docs.unity3d.com/Manual/android-gradle-overview.html
// See official Gradle and Android Gradle Plugin compatibility table here https://developer.android.com/studio/releases/gradle-plugin#updating-gradle
// To specify a custom Gradle version in Unity, go do "Preferences > External Tools", uncheck "Gradle Installed with Unity (recommended)" and specify a path to a custom Gradle version
id 'com.android.application' version '8.3.0' apply false
id 'com.android.library' version '8.3.0' apply false
// highlight-next-line
id 'org.jetbrains.kotlin.android' version '1.8.0' apply false
**BUILD_SCRIPT_DEPS**
}
```
---
# File: unity-quickstart-paywalls
---
---
title: "通过 Unity SDK 中的付费墙启用购买功能"
description: "了解如何在 Unity 应用中使用 Adapty SDK 展示付费墙。"
---
要启用应用内购买,您需要了解三个关键概念:
- [**产品**](product) – 用户可以购买的任何内容(订阅、消耗型商品、永久授权)
- [**付费墙**](paywalls) 是定义要提供哪些产品的配置。在 Adapty 中,付费墙是检索产品的唯一方式,但这种设计让您无需修改应用代码即可更改产品组合、定价和优惠内容。
- [**版位**](placements) – 在应用中展示付费墙的位置和时机(如 `main`、`onboarding`、`settings`)。您在看板中为版位配置付费墙,然后在代码中通过版位 ID 请求它们。这使得运行 A/B 测试以及向不同用户展示不同付费墙变得更加简单。
Adapty 为您提供三种在应用中启用购买功能的方式。请根据应用需求选择其中一种:
| 实现方式 | 复杂度 | 适用场景 |
|---|---|---|
| Adapty 付费墙编辑工具 | ✅ 简单 | 您[在无代码编辑工具中创建完整的、可立即购买的付费墙](quickstart-paywalls)。Adapty 自动渲染付费墙,并在后台处理所有复杂的购买流程、收据验证和订阅管理。 |
| 手动创建的付费墙 | 🟡 中等 | 您在应用代码中实现付费墙 UI,但仍从 Adapty 获取付费墙对象以保持产品组合的灵活性。请参阅[指南](unity-quickstart-manual)。 |
| 观察者模式 | 🔴 困难 | 您已有自己的购买处理基础设施并希望继续使用。请注意,观察者模式在 Adapty 中有一定限制。请参阅[文章](observer-vs-full-mode)。 |
:::important
**以下步骤展示如何实现在 Adapty 付费墙编辑工具中创建的付费墙。**
如果您不想使用付费墙编辑工具,请参阅[处理手动创建付费墙中购买的指南](unity-making-purchases)。
:::
要展示在 Adapty 付费墙编辑工具中创建的付费墙,在应用代码中您只需:
1. **获取付费墙**:从 Adapty 获取付费墙。
2. **展示付费墙,Adapty 将为您处理购买流程**:在应用中显示您获取到的付费墙容器。
3. **处理按钮操作**:将用户与付费墙的交互与应用的响应关联起来。例如,当用户点击按钮时打开链接或关闭付费墙。
## 开始之前 \{#before-you-start\}
在开始之前,请完成以下步骤:
1. 在 Adapty 看板中将您的应用连接到 [App Store](initial_ios) 和/或 [Google Play](initial-android)。
2. 在 Adapty 中[创建产品](create-product)。
3. [创建付费墙并向其添加产品](create-paywall)。
4. [创建版位并将付费墙添加到其中](create-placement)。
5. 在应用代码中[安装并激活 Adapty SDK](sdk-installation-unity)。
:::tip
完成这些步骤最快的方式是按照[快速入门指南](quickstart)操作,或使用 [Developer CLI](developer-cli-quickstart) 创建付费墙和版位。
:::
## 1. 获取付费墙 \{#1-get-the-paywall\}
您的付费墙与在看板中配置的版位关联。版位允许您为不同目标受众运行不同的付费墙,或运行 [A/B 测试](ab-tests)。
要获取在 Adapty 付费墙编辑工具中创建的付费墙,您需要:
1. 使用 `GetPaywall` 方法通过[版位](placements) ID 获取 `paywall` 对象,并使用 `HasViewConfiguration` 属性检查它是否是在编辑工具中创建的付费墙。
2. 使用 `CreatePaywallView` 方法创建付费墙视图。该视图包含展示付费墙所需的 UI 元素和样式。
:::important
要获取视图配置,您必须在付费墙编辑工具中开启 **Show on device** 开关。否则,您将获得空的视图配置,付费墙将无法显示。
:::
```csharp showLineNumbers
Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => {
if(error != null) {
// handle the error
return;
}
// Create paywall view parameters
var parameters = new AdaptyUICreatePaywallViewParameters();
// Create the paywall view
AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => {
if(error != null) {
// handle the error
return;
}
// view - the paywall view ready to be presented
});
});
```
:::info
本快速入门提供展示付费墙所需的最低配置。有关高级配置详情,请参阅我们的[获取付费墙指南](unity-get-pb-paywalls)。
:::
## 2. 展示付费墙 \{#2-display-the-paywall\}
现在,当您已获得付费墙配置后,只需添加几行代码即可展示付费墙。
要展示付费墙,请对由 `CreatePaywallView` 方法创建的 `view` 调用 `view.Present()` 方法。每个 `view` 只能使用一次。如果需要再次展示付费墙,请再次调用 `CreatePaywallView` 创建新的 `view` 实例。
```csharp showLineNumbers title="Unity"
view.Present((error) => {
// handle the error
});
```
:::info
有关如何展示付费墙的更多详情,请参阅我们的[指南](unity-present-paywalls)。
:::
## 3. 处理按钮操作 \{#3-handle-button-actions\}
当用户点击付费墙中的按钮时,Unity SDK 会自动处理购买和恢复操作。但是,其他按钮具有自定义或预定义的 ID,需要在您的代码中处理相应操作。
例如,您的付费墙可能有一个关闭按钮和需要打开的 URL(如使用条款和隐私政策)。要处理这些操作,您的类需要实现 `AdaptyPaywallsEventsListener` 接口并注册为监听器。
:::tip
请阅读我们关于如何处理按钮[操作](unity-handle-paywall-actions)和[事件](unity-handling-events)的指南。
:::
```csharp showLineNumbers title="Unity"
public class YourClass : MonoBehaviour, AdaptyPaywallsEventsListener
{
void Start()
{
// Register this class as the paywall events listener
Adapty.SetPaywallsEventsListener(this);
}
// AdaptyPaywallsEventsListener method - handles button actions
public void PaywallViewDidPerformAction(
AdaptyUIPaywallView view,
AdaptyUIUserAction action
) {
switch (action.Type) {
case AdaptyUIUserActionType.Close:
view.Dismiss(null);
break;
case AdaptyUIUserActionType.OpenUrl:
Application.OpenURL(action.Value);
break;
default:
break;
}
}
}
```
## 后续步骤 \{#next-steps\}
:::tip
有疑问或遇到问题?欢迎访问我们的[支持论坛](https://adapty.featurebase.app/),在那里你可以找到常见问题的解答,也可以提出自己的问题。我们的团队和社区随时为你提供帮助!
:::
您的付费墙已准备好在应用中展示。在 [App Store 沙盒](test-purchases-in-sandbox)或 [Google Play Store](testing-on-android) 中测试您的购买,以确保可以从付费墙完成测试购买。
接下来,您需要[检查用户的访问等级](unity-check-subscription-status),以确保向正确的用户展示付费墙或授予付费功能的访问权限。
## 完整示例 \{#full-example\}
以下是如何将所有步骤整合到您的应用中的完整示例。
```csharp showLineNumbers
using System;
using UnityEngine;
using AdaptySDK;
public class PaywallManager : MonoBehaviour, AdaptyPaywallsEventsListener
{
[SerializeField] private string placementId = "YOUR_PLACEMENT_ID";
private AdaptyUIPaywallView currentPaywallView;
void Start()
{
// Register for paywall events
Adapty.SetPaywallsEventsListener(this);
GetAndDisplayPaywall();
}
private void GetAndDisplayPaywall()
{
Adapty.GetPaywall(placementId, (paywall, error) => {
if (error != null) {
Debug.LogError("Error getting paywall: " + error.Message);
return;
}
if (paywall.HasViewConfiguration) {
CreateAndPresentPaywallView(paywall);
} else {
Debug.LogWarning("Paywall was not created using the builder");
}
});
}
private void CreateAndPresentPaywallView(AdaptyPaywall paywall)
{
var parameters = new AdaptyUICreatePaywallViewParameters();
AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => {
if (error != null) {
Debug.LogError("Error creating paywall view: " + error.Message);
return;
}
currentPaywallView = view;
view.Present((presentError) => {
if (presentError != null) {
Debug.LogError("Error presenting paywall: " + presentError.Message);
return;
}
Debug.Log("Paywall presented successfully");
});
});
}
// AdaptyPaywallsEventsListener implementation
public void PaywallViewDidPerformAction(
AdaptyUIPaywallView view,
AdaptyUIUserAction action
) {
switch (action.Type) {
case AdaptyUIUserActionType.Close:
Debug.Log("Close button pressed");
view.Dismiss(null);
break;
case AdaptyUIUserActionType.OpenUrl:
Application.OpenURL(action.Value);
break;
default:
break;
}
}
// Required interface methods (implement as needed)
public void PaywallViewDidAppear(AdaptyUIPaywallView view) { }
public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { }
public void PaywallViewDidSelectProduct(AdaptyUIPaywallView view, string productId) { }
public void PaywallViewDidStartPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product) { }
public void PaywallViewDidFinishPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyPurchaseResult purchasedResult) { }
public void PaywallViewDidFailPurchase(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { }
public void PaywallViewDidStartRestore(AdaptyUIPaywallView view) { }
public void PaywallViewDidFinishRestore(AdaptyUIPaywallView view, AdaptyProfile profile) { }
public void PaywallViewDidFailRestore(AdaptyUIPaywallView view, AdaptyError error) { }
public void PaywallViewDidFailRendering(AdaptyUIPaywallView view, AdaptyError error) { }
public void PaywallViewDidFailLoadingProducts(AdaptyUIPaywallView view, AdaptyError error) { }
public void PaywallViewDidFinishWebPaymentNavigation(AdaptyUIPaywallView view, AdaptyPaywallProduct product, AdaptyError error) { }
public void ShowPaywall()
{
GetAndDisplayPaywall();
}
void OnDestroy()
{
if (currentPaywallView != null) {
currentPaywallView.Dismiss(null);
}
}
}
```
---
# File: unity-check-subscription-status
---
---
title: "在 Unity SDK 中检查订阅状态"
description: "了解如何在 Unity 应用中使用 Adapty 检查订阅状态。"
---
要判断用户是否可以访问付费内容或查看付费墙,您需要在用户画像中检查其[访问等级](access-level)。
本文介绍如何访问用户画像状态,以决定向用户展示什么内容——是显示付费墙还是授予付费功能的访问权限。
## 获取订阅状态 \{#get-subscription-status\}
当您需要决定是否向用户显示付费墙或付费内容时,需要检查其用户画像中的[访问等级](access-level)。您有两种选择:
- 如果需要立即获取最新的用户画像数据(例如在应用启动时)或希望强制更新,请调用 `GetProfile`。
- 设置**自动用户画像更新**,以在订阅状态发生变化时自动刷新本地副本。
### 获取用户画像 \{#get-profile\}
获取订阅状态最简单的方法是使用 `GetProfile` 方法访问用户画像:
```csharp showLineNumbers
Adapty.GetProfile((profile, error) => {
if (error != null) {
// handle the error
return;
}
// check the access
});
```
### 监听订阅更新 \{#listen-to-subscription-updates\}
要在应用中自动接收用户画像更新:
1. 继承 `AdaptyEventListener` 并实现 `OnLoadLatestProfile` 方法——每当用户的订阅状态发生变化时,Adapty 会自动调用此方法。
2. 在该方法被调用时存储更新后的用户画像数据,以便在整个应用中使用,无需发起额外的网络请求。
```csharp
public class SubscriptionManager : MonoBehaviour, AdaptyEventListener {
private AdaptyProfile currentProfile;
void Start() {
// Register this object as an Adapty event listener
Adapty.SetEventListener(this);
}
// Store the profile when it updates
public void OnLoadLatestProfile(AdaptyProfile profile) {
currentProfile = profile;
// Update UI, unlock content, etc.
}
public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { }
public void OnInstallationDetailsFail(AdaptyError error) { }
// Use stored profile instead of calling getProfile()
public bool HasAccess() {
if (currentProfile?.AccessLevels != null &&
currentProfile.AccessLevels.ContainsKey("premium")) {
return currentProfile.AccessLevels["premium"].IsActive;
}
return false;
}
}
```
:::note
每当应用启动时,Adapty 会自动调用 `OnLoadLatestProfile`,即使设备处于离线状态,也能提供缓存的订阅数据。
:::
## 将用户画像与付费墙逻辑关联 \{#connect-profile-with-paywall-logic\}
当您需要立即决定是否显示付费墙或授予付费功能访问权限时,可以直接检查用户的用户画像。此方法适用于以下场景:应用启动、进入付费区域,或在展示特定内容之前。
```csharp
private void CheckAccessLevel()
{
Adapty.GetProfile((profile, error) => {
if (error != null) {
Debug.LogError("Error checking access level: " + error.Message);
// Show paywall if access check fails
return;
}
var accessLevel = profile.AccessLevels["YOUR_ACCESS_LEVEL"];
if (accessLevel == null || !accessLevel.IsActive) {
// Show paywall if no access
}
});
}
private void InitializePaywall()
{
LoadPaywall();
CheckAccessLevel();
}
```
## 后续步骤 \{#next-steps\}
现在您已了解如何追踪订阅状态,接下来请学习如何[使用用户画像](unity-quickstart-identify),以确保用户能够访问其已付费的内容。
---
# File: unity-quickstart-identify
---
---
title: "在 Unity SDK 中识别用户"
description: "在 Unity 中设置 Adapty 进行应用内订阅管理的快速入门指南。"
---
:::important
本指南适用于有自己身份验证系统的开发者。你将了解如何在 Adapty 中管理用户画像,使其与你现有的身份验证系统保持一致。
:::
用户购买行为的管理方式取决于你的应用身份验证模型:
- 如果你的应用不使用后端身份验证且不存储用户数据,请参阅[匿名用户部分](#anonymous-users)。
- 如果你的应用已有(或将有)后端身份验证,请参阅[已识别用户部分](#identified-users)。
**核心概念**:
- **用户画像**是 SDK 运行所必需的实体,由 Adapty 自动创建。
- 用户画像可以是匿名的**(不含 customer user ID)**,也可以是已识别的**(含 customer user ID)**。
- 您提供 **customer user ID** 是为了将 Adapty 中的用户画像与您内部的身份认证系统进行关联。
以下是匿名用户与已识别用户的区别:
| | 匿名用户 | 已识别用户 |
|-------------------------|-----------------------------------|-----------------------------------------------|
| **购买管理** | 通过应用商店恢复购买 | 通过客户用户 ID 跨设备保留购买历史 |
| **用户画像管理** | 每次重新安装都会创建新的用户画像 | 跨会话和设备共享同一用户画像 |
| **数据持久性** | 匿名用户的数据与应用安装绑定 | 已识别用户的数据在应用重新安装后仍可保留 |
## 匿名用户 \{#anonymous-users\}
如果你没有后端身份验证,**则无需在应用代码中处理身份验证**:
1. 当 SDK 在应用首次启动时激活,Adapty 会**为该用户创建一个新的用户画像**。
2. 当用户在应用内购买任何商品时,该购买记录会**关联到其 Adapty 用户画像及其应用商店账户**。
3. 当用户**重新安装**应用或在**新设备**上安装时,Adapty 会**在激活时创建一个新的匿名用户画像**。
4. 如果用户之前在您的应用中有过购买记录,默认情况下,SDK 激活时会自动从 App Store 同步其购买历史。
因此,对于匿名用户,每次安装都会创建新的用户画像,但这不是问题,因为在 Adapty 分析中,你可以[配置什么会被视为新安装](general#4-installs-definition-for-analytics)。
对于匿名用户,你需要按**设备 ID** 统计安装量。在这种情况下,设备上的每次应用安装都会被计为一次安装,包括重新安装。
## 已识别用户 \{#identified-users\}
您有两种方式在应用中识别用户:
- [**在登录/注册时:**](#during-loginsignup) 如果用户在应用启动后才登录,请在他们完成身份验证时调用 `identify()`,并传入 customer user ID。
- [**在 SDK 激活时:**](#during-the-sdk-activation) 如果应用启动时已有存储的 customer user ID,请在调用 `activate()` 时直接传入。
:::important
默认情况下,当 Adapty 收到来自某个 Customer User ID 的购买请求,而该 ID 当前已与另一个 Customer User ID 关联时,访问等级将被共享,两个用户画像都拥有付费访问权限。你可以将此设置配置为将付费访问权从一个用户画像转移到另一个,或完全禁用共享。详情请参阅[文章](general#6-sharing-paid-access-between-user-accounts)。
:::
### 登录/注册期间 \{#during-loginsignup\}
如果你在应用启动后才识别用户身份(例如用户登录或注册之后),请使用 `identify` 方法设置其 customer user ID。
- 如果你**之前从未使用过该 customer user ID**,Adapty 会自动将其关联到当前用户画像。
- 如果你**之前已使用该 customer user ID 识别过该用户**,Adapty 会切换到与该 customer user ID 关联的用户画像。
:::important
Customer user ID 对每个用户必须唯一。如果将该参数硬编码为固定值,所有用户将被视为同一人。
:::
在调用其他 SDK 方法之前,请等待 `Identify` 的完成回调。并发调用会产生 `#3006 profileWasChanged` 错误,或导致操作落到匿名用户画像上。详见 [Unity SDK 调用顺序](unity-sdk-call-order)。
```csharp showLineNumbers
Adapty.Identify("YOUR_USER_ID", (error) => { // Unique for each user
if(error == null) {
// successful identify
}
});
```
### 在 SDK 激活期间 \{#during-the-sdk-activation\}
如果在激活 SDK 时已经知道用户 ID,可以直接在 `activate` 方法中传入,无需单独调用 `identify`。
如果知道用户 ID,但在激活后才进行设置,那么在激活时 Adapty 会先创建一个匿名用户画像,等到调用 `identify` 后才会切换到已有的用户画像。
您可以传入已有的客户用户 ID(即之前使用过的 ID),也可以传入新的 ID。若传入新 ID,激活时创建的新用户画像将自动与该客户用户 ID 关联。
:::note
默认情况下,创建匿名用户画像不会影响分析看板,因为安装量是基于设备 ID 来统计的。
设备 ID 代表从应用商店在设备上安装的一次应用实例,仅在重新安装应用后才会重新生成。
它与首次安装还是重复安装无关,也与是否使用了已有的客户用户 ID 无关。
创建用户画像(在 SDK 激活或退出登录时)、登录,或在不重新安装应用的情况下升级应用,均不会产生额外的安装事件。
如果您希望根据唯一用户而非设备来统计安装量,请前往 **App settings**,配置 [**Installs definition for analytics**](general#4-installs-definition-for-analytics)。
:::
```csharp showLineNumbers
using UnityEngine;
using AdaptySDK;
var builder = new AdaptyConfiguration.Builder("YOUR_API_KEY")
.SetCustomerUserId("YOUR_USER_ID"); // 每个用户的 Customer User ID 必须唯一。如果硬编码该参数值,所有用户将被视为同一个人。
Adapty.Activate(builder.Build(), (error) => {
if (error != null) {
// 处理错误
return;
}
});
```
### 用户退出登录 \{#log-users-out\}
如果您有供用户退出登录的按钮,请使用 `logout` 方法。
:::important
用户退出登录会为用户创建一个新的匿名用户画像。
:::
```csharp showLineNumbers
Adapty.Logout((error) => {
if(error == null) {
// successful logout
}
});
```
:::info
要让用户重新登录应用,请使用 `identify` 方法。
:::
### 允许未登录状态下进行购买 \{#allow-purchases-without-login\}
如果用户在登录前后都可以进行购买,你需要确保他们登录后仍能保留访问权限:
1. 当未登录用户发起购买时,Adapty 会将其关联到该用户的匿名用户画像 ID。
2. 当用户登录账号后,Adapty 会切换到使用其已识别的用户画像。
- 如果是新的 customer user ID(例如购买发生在注册之前),Adapty 会将该 customer user ID 分配给当前用户画像,从而保留所有购买历史记录。
- 如果是已存在的 customer user ID(该 customer user ID 已关联到某个用户画像),则需要在用户画像切换后获取实际的访问等级。你可以在识别完成后立即调用 [`getProfile`](unity-check-subscription-status),或[监听用户画像更新](unity-check-subscription-status)以使数据自动同步。
## 下一步 \{#next-steps\}
恭喜你!你已经在应用中成功实现了应用内付费逻辑!祝你的应用变现一切顺利!
想从 Adapty 获得更多价值,可以进一步探索以下内容:
- [**测试**](troubleshooting-test-purchases):确保一切按预期运行
- [**用户引导**](onboardings):通过用户引导吸引用户并提升留存
- [**集成**](configuration):只需一行代码即可与营销归因和数据分析服务完成集成
- [**设置自定义用户画像属性**](unity-setting-user-attributes):为用户画像添加自定义属性并创建市场细分,从而发起 A/B 测试或向不同用户展示不同的付费墙
---
# File: adapty-sdk-integration-skill-unity
---
---
title: "通过 SDK 集成技能将 Adapty 接入 Unity 应用"
description: "使用 adapty-sdk-integration 技能,借助 AI 编码工具将 Adapty SDK 端到端集成到你的 Unity 应用中。"
---
[adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill) 可以端到端地自动完成 Adapty 集成:看板配置、SDK 安装、付费墙设置以及各阶段验证。它会自动检测你的平台,并在每个阶段获取相关的 Adapty 文档。
**支持的工具**:Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。
安装时,请选择适合你所用工具的方式。完整列表请参阅 [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill)。
**Claude Code**
```
claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill
claude plugin install adapty-sdk-integration@adapty
```
**GitHub Copilot CLI**
```
gh skill install adaptyteam/adapty-sdk-integration-skill
```
**Gemini CLI**
```
gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill
```
**OpenAI Codex 或其他工具** — 使用 [skills CLI](https://skills.sh)(注意:通过此方式安装的 skill 不会自动更新):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
也可以克隆仓库,将 `skills/adapty-sdk-integration/` 复制到你所用工具的 skills 目录中。
安装完成后,在项目中运行该 skill:
```
/adapty-sdk-integration
```
skill 会提出几个配置问题,然后逐步引导你完成看板配置、SDK 安装、付费墙设置和验证。
:::important
该功能目前处于测试阶段。如果遇到卡顿或异常情况,请参考[分步集成指南](adapty-cursor-unity)——它会引导你的 AI 工具逐步完成每个阶段的正确文档操作。
:::
[adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill) 可以端到端地自动完成 Adapty 集成:看板配置、SDK 安装、付费墙设置以及各阶段验证。它会自动检测你的平台,并在每个阶段获取相关的 Adapty 文档。
**支持的工具**:Claude Code、GitHub Copilot CLI、OpenAI Codex、Gemini CLI。
安装时,请选择适合你所用工具的方式。完整列表请参阅 [skill README](https://github.com/adaptyteam/adapty-sdk-integration-skill)。
**Claude Code**
```
claude plugin marketplace add adaptyteam/adapty-sdk-integration-skill
claude plugin install adapty-sdk-integration@adapty
```
**GitHub Copilot CLI**
```
gh skill install adaptyteam/adapty-sdk-integration-skill
```
**Gemini CLI**
```
gemini skills install https://github.com/adaptyteam/adapty-sdk-integration-skill
```
**OpenAI Codex 或其他工具** — 使用 [skills CLI](https://skills.sh)(注意:通过此方式安装的 skill 不会自动更新):
```
npx skills add adaptyteam/adapty-sdk-integration-skill
```
也可以克隆仓库,将 `skills/adapty-sdk-integration/` 复制到你所用工具的 skills 目录中。
安装完成后,在项目中运行该 skill:
```
/adapty-sdk-integration
```
skill 会提出几个配置问题,然后逐步引导你完成看板配置、SDK 安装、付费墙设置和验证。
---
# File: adapty-cursor-unity
---
---
title: "借助 AI 将 Adapty 集成到 Unity 应用"
description: "使用 Cursor、Context7、ChatGPT、Claude 或其他 AI 工具,将 Adapty 集成到 Unity 应用的分步指南。"
---
本指南将带你一步一步地将 Adapty 集成到你的 Unity 应用中,借助 AI 编程工具——按正确的顺序向它提供合适的 Adapty 文档即可。
For a fully automated integration, use the [adapty-sdk-integration skill](https://github.com/adaptyteam/adapty-sdk-integration-skill): it runs the whole integration from your AI coding tool in one command.
## 开始之前:看板配置 \{#before-you-start-dashboard-setup\}
Adapty 在您编写任何 SDK 代码之前,需要先完成一些看板配置。您可以通过交互式 LLM 技能,或手动通过看板来完成配置。
### Skill 方法 \{#skill-approach\}
Adapty CLI skill 让你的 LLM 直接设置应用、产品、访问等级、付费墙和版位,无需为每个步骤打开看板。你只需要在看板中[连接你的商店](integrate-payments)。
```
npx skills add adaptyteam/adapty-cli --skill adapty-cli
```
添加 skill 后,在你的 agent 中运行 `/adapty-cli`。它将引导你完成每个步骤,包括何时需要打开看板连接你的商店。
### 看板配置方式 \{#dashboard-approach\}
如果你倾向于手动配置所有内容,以下是编写代码前需要准备的信息。LLM 无法自动查找看板中的配置值,需要你手动提供。
1. **连接应用商店**:在 Adapty 看板中,前往 **App settings → General**,连接 App Store 和 Google Play(如果你的 Unity 应用同时支持两个平台)。这是购买功能正常运行的必要条件。
[连接应用商店](integrate-payments)
2. **复制您的 Public SDK key**:在 Adapty 看板中,前往 **App settings → General**,找到 **API keys** 部分。在代码中,这是您传递给 Adapty 配置构建器的字符串。
3. **至少创建一个产品**:在 Adapty 看板中,前往 **Products** 页面。您无需在代码中直接引用产品——Adapty 会通过付费墙来分发它们。
[添加产品](quickstart-products)
4. **创建付费墙和版位**:在 Adapty 看板中,在 **Paywalls** 页面创建付费墙,然后在 **Placements** 页面将其分配到一个版位。在代码中,版位 ID 就是传递给 `Adapty.GetPaywall("YOUR_PLACEMENT_ID")` 的字符串。
[创建付费墙](quickstart-paywalls)
5. **设置访问等级**:在 Adapty 看板的 **Products** 页面中按产品进行配置。在代码中,通过 `profile.AccessLevels["premium"]?.IsActive` 检查对应字符串。默认的 `premium` 访问等级适用于大多数应用。如果付费用户根据所购产品获得不同功能的访问权限(例如 `basic` 方案与 `pro` 方案),请在开始编码前[创建额外的访问等级](assigning-access-level-to-a-product)。
:::tip
准备好这五项信息后,就可以开始写代码了。告诉你的 LLM:"我的 Public SDK key 是 X,我的版位 ID 是 Y",这样它就能生成正确的初始化和付费墙获取代码。
:::
### 准备就绪后进行设置 \{#set-up-when-ready\}
这些内容不是开始编码的必要条件,但随着集成的成熟,你会需要它们:
- **A/B 测试**:在 **Placements** 页面进行配置,无需更改代码。
[A/B 测试](ab-tests)
- **更多付费墙和版位**:添加更多使用不同版位 ID 的 `GetPaywall` 调用。
- **分析集成**:在 **Integrations** 页面进行配置,具体设置因集成而异。请参阅[分析集成](analytics-integration)和[归因集成](attribution-integration)。
## 将 Adapty 文档输入到您的 LLM \{#feed-adapty-docs-to-your-llm\}
### 使用 Context7(推荐)
[Context7](https://context7.com) 是一个 MCP 服务器,让你的 LLM 可以直接访问最新的 Adapty 文档。LLM 会根据你的提问自动获取相关文档,无需手动粘贴 URL。
Context7 支持 **Cursor**、**Claude Code**、**Windsurf** 以及其他兼容 MCP 的工具。运行以下命令即可完成配置:
```
npx ctx7 setup
```
该命令会自动检测你的编辑器并配置 Context7 服务器。如需手动配置,请参阅 [Context7 GitHub 仓库](https://github.com/upstash/context7)。
配置完成后,在提示词中引用 Adapty 库:
```
Use the adaptyteam/adapty-docs library to look up how to install the Unity SDK
```
:::warning
虽然 Context7 无需手动粘贴文档链接,但实现顺序很重要。请按照下方的[实现步骤](#implementation-walkthrough)逐步操作,以确保一切正常运行。
:::
### 使用纯文本文档 \{#use-plain-text-docs\}
您可以以纯文本 Markdown 格式访问任意 Adapty 文档。只需在 URL 末尾添加 `.md`,或点击文章标题下方的 **Copy for LLM**。例如:[adapty-cursor-unity.md](https://adapty.io/docs/zh/adapty-cursor-unity.md)。
下方[实施演练](#implementation-walkthrough)中的每个阶段都包含一个"Send this to your LLM"区块,其中附有可粘贴的 `.md` 链接。
如需一次性获取更多文档,请参阅下方的[索引文件与平台专属子集](#plain-text-doc-index-files)。
## 实施演练 \{#implementation-walkthrough\}
本指南的其余部分按实施顺序介绍 Adapty 集成流程。每个阶段包含需要发送给 LLM 的文档、完成后应看到的效果以及常见问题。
### 规划集成方案 \{#plan-your-integration\}
在开始写代码之前,先让 LLM 分析你的项目并制定实现计划。如果你的 AI 工具支持规划模式(例如 Cursor 或 Claude Code 的计划模式),建议先使用该模式,让 LLM 在生成代码前同时读取你的项目结构和 Adapty 文档。
告诉 LLM 你使用的购买方式——这会决定它应该参考哪些指南:
- [**Adapty 付费墙编辑工具**](adapty-paywall-builder):在 Adapty 的无代码编辑工具中创建付费墙,SDK 会自动渲染。
- [**手动创建付费墙**](unity-making-purchases):自行编写付费墙 UI 代码,但仍使用 Adapty 获取产品并处理购买流程。
- [**观察者模式**](observer-vs-full-mode):保留现有的购买基础设施,仅使用 Adapty 进行数据分析和集成。
不确定该选哪种?请查看[快速入门中的对比表格](unity-quickstart-paywalls)。
### 安装并配置 SDK \{#install-and-configure-the-sdk\}
通过 Unity Package Manager 添加 Adapty SDK 包,并使用你的公共 SDK 密钥激活它。这是一切的基础——没有它,其他功能都无法正常工作。
**指南:** [安装并配置 Adapty SDK](sdk-installation-unity)
将以下内容发送给你的 LLM:
```
Read these Adapty docs before writing code:
- https://adapty.io/docs/zh/sdk-installation-unity.md
```
:::tip[Checkpoint]
- **预期结果:** 项目成功构建并运行,Unity 控制台显示 Adapty 激活日志。
- **常见问题:** "Public API key is missing" → 检查是否已将占位符替换为 **App settings** 中的真实密钥。
:::
### 展示付费墙并处理购买 \{#show-paywalls-and-handle-purchases\}
通过版位 ID 获取付费墙、展示付费墙并处理购买事件。具体需要参考哪些指南,取决于你处理购买的方式。
每完成一步后,请在沙盒中测试购买流程,不要等到最后再测试。沙盒配置说明请参见[在沙盒中测试购买](test-purchases-in-sandbox)。
可选
默认值:`en`
|[付费墙本地化](add-paywall-locale-in-adapty-paywall-builder)的标识符。该参数应为语言代码,由一个或两个子标签组成,中间用连字符(**-**)分隔。第一个子标签表示语言,第二个子标签表示地区。
示例:`en` 表示英语,`pt-br` 表示巴西葡萄牙语。
有关语言代码及推荐使用方式,请参阅[本地化与语言代码](localizations-and-locale-codes)。
| | **fetchPolicy** | 默认值:`.reloadRevalidatingCacheData` |默认情况下,SDK 会尝试从服务器加载数据,若失败则返回缓存数据。我们推荐使用此方式,因为它能确保用户始终获取最新数据。
但如果你认为用户的网络连接不稳定,可以考虑使用 `.returnCacheDataElseLoad`——在缓存存在时直接返回缓存数据。这样用户获取的数据可能不是最新的,但无论网络状况如何,加载速度都会更快。缓存会定期更新,因此在会话期间使用缓存以避免网络请求是安全的。
请注意,缓存在应用重启后仍会保留,只有在重新安装应用或手动清除时才会被清空。
Adapty SDK 通过两层机制在本地存储付费墙:上述定期更新的缓存,以及[备用付费墙](fallback-paywalls)。我们还使用 CDN 加快付费墙的加载速度,并在 CDN 不可用时启用独立的备用服务器。该机制旨在确保你始终获取最新版本的付费墙,同时在网络连接受限的情况下也能保证可靠性。
| | **loadTimeout** | 默认值:5 秒 |该值用于限制此方法的超时时间。若超时,将返回缓存数据或本地备用数据。
请注意,在少数情况下,该方法的实际超时时间可能略晚于 `loadTimeout` 中指定的时间,因为底层操作可能包含多个请求。
| 响应参数: | 参数 | 说明 | | :-------- | :---------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | 一个 [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) 对象,包含产品 ID 列表、付费墙标识符、远程配置及其他若干属性。 | ## 获取使用付费墙编辑工具设计的付费墙视图配置 \{#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder\} :::important 请确保在付费墙编辑工具中启用了 **Show on device** 开关。如果未开启此选项,将无法获取视图配置。 ::: 获取付费墙后,检查其是否包含 `ViewConfiguration`——该字段表明该付费墙是通过付费墙编辑工具创建的,并将指引你如何展示该付费墙。如果存在 `ViewConfiguration`,则将其视为付费墙编辑工具付费墙;如果不存在,则[将其作为远程配置付费墙处理](present-remote-config-paywalls-unity)。 在 Unity SDK 中,直接调用 `CreatePaywallView` 方法,无需手动获取视图配置。 :::warning `CreatePaywallView` 方法的返回结果只能使用一次。如需再次使用,请重新调用 `CreatePaywallView` 方法。若不重新创建而直接调用两次,可能会导致 `AdaptyUIError.viewAlreadyPresented` 错误。 ::: ```csharp showLineNumbers var parameters = new AdaptyUICreatePaywallViewParameters() .SetPreloadProducts(preloadProducts) .SetLoadTimeout(new TimeSpan(0, 0, 3)); AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => { // handle the result }); ``` 参数: | 参数 | 是否必填 | 描述 | | :------------------ | :----------------- | :----------------------------------------------------------- | | **paywall** | 必填 | 一个 `AdaptyPaywall` 对象,用于获取目标付费墙的控制器。 | | **loadTimeout** | 默认值:5 秒 | 该值限制此方法的超时时间。若超时,将返回缓存数据或本地备用数据。请注意,在极少数情况下,此方法的实际超时时间可能略晚于 `loadTimeout` 中指定的值,因为该操作在底层可能包含多个请求。 | | **PreloadProducts** | 可选 | 提供一个 `AdaptyPaywallProducts` 数组,以优化产品在屏幕上的显示时机。若传入 `nil`,AdaptyUI 将自动获取所需产品。 | | **CustomTags** | 可选 | 定义一个自定义标签及其解析值的字典。自定义标签在付费墙内容中充当占位符,会被动态替换为特定字符串,从而在付费墙中实现个性化内容。详情请参阅付费墙编辑工具中的自定义标签相关说明。 | | **CustomTimers** | 可选 | 定义一个自定义计时器及其结束日期的字典。自定义计时器允许您在付费墙中展示倒计时。 | :::note 如果您使用多种语言,请了解如何添加[付费墙编辑工具本地化](add-paywall-locale-in-adapty-paywall-builder),以及如何正确使用语言区域代码([点击此处了解](localizations-and-locale-codes))。 ::: 获取视图后,[展示付费墙](unity-present-paywalls)。 ## 自定义资源 \{#customize-assets\} 要自定义付费墙中的图片和视频,请实现自定义资源。 主图和视频有预定义的 ID:`hero_image` 和 `hero_video`。在自定义资源包中,你通过这些 ID 来定位并自定义相应元素的行为。 对于其他图片和视频,你需要在 Adapty 看板中[设置自定义 ID](custom-media)。 例如,你可以: - 为部分用户展示不同的图片或视频。 - 在远程主图加载时显示本地预览图。 - 在播放视频前先显示预览图。 :::important 要使用此功能,请将 Adapty Unity SDK 更新至 3.8.0 或更高版本。 ::: 以下是如何通过简单字典提供自定义资源的示例: ```csharp showLineNumbers var customAssets = new Dictionary可选
默认值:`en`
|付费墙本地化的标识符。该参数应为由一个或两个子标签组成的语言代码,子标签之间以连字符(**-**)分隔。第一个子标签表示语言,第二个子标签表示地区。
示例:`en` 表示英语,`pt-br` 表示巴西葡萄牙语。
| | **fetchPolicy** | 默认值:`.reloadRevalidatingCacheData` |默认情况下,SDK 会尝试从服务器加载数据,如果失败则返回缓存数据。我们推荐使用此选项,因为它能确保用户始终获取最新数据。
但如果你认为用户的网络连接不稳定,可以考虑使用 `.returnCacheDataElseLoad`——在缓存数据存在时优先返回缓存。这种情况下,用户获取的数据可能不是最新的,但无论网络状况如何,加载速度都会更快。缓存会定期更新,因此在会话期间使用缓存以减少网络请求是安全的。
请注意,缓存在重启应用后仍会保留,只有在重新安装应用或手动清除时才会被清空。
Adapty SDK 通过两层机制在本地存储付费墙:上述定期更新的缓存,以及备用付费墙。我们还使用 CDN 加速付费墙的获取,并配备了独立的备用服务器以应对 CDN 不可用的情况。整套系统旨在确保你始终能获取最新版本的付费墙,同时在网络条件较差的情况下也能保证可靠性。
| --- # File: unity-present-paywalls --- --- title: "展示付费墙" description: "了解如何使用 Adapty SDK 在 Unity 应用中展示付费墙。" --- 如果你已经使用付费墙编辑工具自定义了付费墙,则无需在移动端代码中手动处理渲染逻辑来向用户展示它。这类付费墙已包含展示内容和展示方式的完整配置。 :::warning 本指南适用于**新版付费墙编辑工具**,需要 Adapty SDK 3.3.0 或更高版本。 如需展示远程配置付费墙,请参阅[渲染通过远程配置设计的付费墙](present-remote-config-paywalls)。 ::: 要展示付费墙,请对通过 [`CreatePaywallView`](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder) 方法创建的 `view` 调用 `view.Present()` 方法。每个 `view` 只能使用一次。如需再次展示同一付费墙,请重新调用 `CreatePaywallView` 以创建新的 `view` 实例。 :::warning 复用同一个 `view` 而不重新创建,可能会导致 `AdaptyUIError.viewAlreadyPresented` 错误。 ::: ```csharp showLineNumbers title="Unity" view.Present((error) => { // handle the error }); ``` :::tip 想看看 Adapty SDK 在移动应用中的实际集成示例吗?欢迎查看我们的[示例应用](sample-apps),其中演示了完整的集成流程,包括展示付费墙、完成购买以及其他基本功能。 ::: ## 显示对话框 \{#show-dialog\} 当付费墙视图在 Android 上展示时,请使用此方法代替原生弹窗。在 Android 上,普通弹窗会显示在付费墙视图后方,导致用户看不到。该方法可确保在所有平台上对话框正确显示于付费墙之上。 ```csharp showLineNumbers title="Unity" var dialog = new AdaptyUIDialogConfiguration() .SetTitle("Close paywall?") .SetContent("You will lose access to exclusive offers.") .SetDefaultActionTitle("Stay") .SetSecondaryActionTitle("Close"); AdaptyUI.ShowDialog(view, dialog, (action, error) => { if (error == null) { if (action == AdaptyUIDialogActionType.Secondary) { // User confirmed - close the paywall view.Dismiss(); } // If primary - do nothing, user stays } }); ``` ## 配置 iOS 展示样式 \{#configure-ios-presentation-style\} 通过向 `Present()` 方法传入 `iosPresentationStyle` 参数来配置付费墙在 iOS 上的展示方式。该参数接受 `AdaptyUIIOSPresentationStyle.FullScreen`(默认值)或 `AdaptyUIIOSPresentationStyle.PageSheet`。 ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` --- # File: unity-handle-paywall-actions --- --- title: "在 Unity SDK 中响应按钮操作" description: "使用 Adapty 在 Unity 中处理付费墙按钮操作,提升应用变现效果。" --- 如果您正在使用 Adapty 付费墙编辑工具构建付费墙,正确设置按钮至关重要: 1. 在付费墙编辑工具中[添加按钮](paywall-buttons),并为其分配预设操作或创建自定义操作 ID。 2. 在您的应用代码中编写处理每个已分配操作的逻辑。 本指南介绍如何在代码中处理自定义操作和预设操作。 :::warning **只有购买和恢复操作会被自动处理。** 其他所有按钮操作(例如关闭付费墙或打开链接)都需要在应用代码中实现相应的响应逻辑。 ::: ## 关闭付费墙 \{#close-paywalls\} 要添加一个可关闭付费墙的按钮: 1. 在付费墙编辑工具中,添加一个按钮并为其分配 **Close** 操作。 2. 在您的应用代码中,为 `close` 操作实现一个处理程序,用于关闭付费墙。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Close: view.Dismiss(null); break; default: // handle other events break; } } ``` ## 从付费墙打开 URL \{#open-urls-from-paywalls\} :::tip 如果您想添加一组链接(例如使用条款和购买恢复),可以在付费墙编辑工具中添加 **Link** 元素,并以与带有 **Open URL** 操作的按钮相同的方式进行处理。 ::: 要添加一个从付费墙打开链接的按钮(例如**使用条款**或**隐私政策**): 1. 在付费墙编辑工具中,添加一个按钮,为其分配 **Open URL** 操作,并输入您想打开的 URL。 2. 在您的应用代码中,为 `openUrl` 操作实现一个处理程序,用于在浏览器中打开收到的 URL。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.OpenUrl: var urlString = action.Value; if(!string.IsNullOrWhiteSpace(urlString)) { Application.OpenURL(urlString); } break; default: // handle other events break; } } ``` ## 登录应用 \{#log-into-the-app\} 要添加一个让用户登录应用的按钮: 1. 在付费墙编辑工具中,添加一个按钮,并为其分配 ID 为 `login` 的 **Custom** 操作。 2. 在您的应用代码中,为 `login` 自定义操作实现一个处理程序,用于识别您的用户身份。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "login") { // Navigate to login scene SceneManager.LoadScene("LoginScene"); } break; default: // handle other events break; } } ``` ## 处理自定义操作 \{#handle-custom-actions\} 要添加一个处理其他任意操作的按钮: 1. 在付费墙编辑工具中,添加一个按钮,为其分配 **Custom** 操作,并设置一个 ID。 2. 在您的应用代码中,为您创建的操作 ID 实现相应的处理程序。 例如,如果您有另一套订阅优惠或一次性购买,可以添加一个按钮来显示另一个付费墙: ```csharp showLineNumbers title="Unity" public void PaywallViewDidPerformAction( AdaptyUIPaywallView view, AdaptyUIUserAction action ) { switch (action.Type) { case AdaptyUIUserActionType.Custom: if (action.Value == "openNewPaywall") { // Display another paywall ShowAlternativePaywall(); } break; default: // handle other events break; } } private void ShowAlternativePaywall() { // Implement your logic to show alternative paywall } ``` --- # File: unity-handling-events --- --- title: "处理付费墙事件" description: "了解如何使用 Adapty SDK 在 Unity 应用中处理付费墙事件。" --- :::important 本指南涵盖购买、恢复、产品选择以及付费墙渲染的事件处理。你还必须实现按钮处理(关闭付费墙、打开链接等)。详情请参阅[处理按钮操作指南](unity-handle-paywall-actions)。 ::: 使用[付费墙编辑工具](adapty-paywall-builder)配置的付费墙无需额外代码即可完成购买和恢复操作。但它们会触发一些事件供应用响应,包括按钮点击(关闭按钮、URL、产品选择等)以及付费墙上购买相关操作的通知。以下介绍如何响应这些事件。 :::warning 本指南仅适用于**新版付费墙编辑工具付费墙**,需要 Adapty SDK v3.3.0 或更高版本。 ::: :::tip 想看看 Adapty SDK 在移动应用中的实际集成示例吗?欢迎查看我们的[示例应用](sample-apps),其中演示了完整的集成流程,包括展示付费墙、完成购买以及其他基本功能。 ::: ## 处理事件 \{#handling-events\} 要控制或监控应用付费墙界面上发生的流程,请实现 `AdaptyPaywallsEventsListener` 接口: ```csharp showLineNumbers title="Unity" using UnityEngine; using AdaptySDK; public class PaywallEventsHandler : MonoBehaviour, AdaptyPaywallsEventsListener { void Start() { Adapty.SetPaywallsEventsListener(this); } // Implement all required interface methods below } ``` ### 用户触发的事件 \{#user-generated-events\} #### 付费墙已显示 \{#paywall-appeared\} 当付费墙视图呈现到屏幕上时触发。 :::note 在 iOS 上,当用户点击付费墙内的[网页付费墙按钮](web-paywall#step-2a-add-a-web-purchase-button)并在应用内浏览器中打开网页付费墙时,也会触发此事件。 ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidAppear(AdaptyUIPaywallView view) { } ``` #### 付费墙已消失 \{#paywall-disappeared\} 当付费墙视图从屏幕上关闭时触发。 :::note 在 iOS 上,当从付费墙打开的[网页付费墙](web-paywall#step-2a-add-a-web-purchase-button)在应用内浏览器中消失时,也会触发此事件。 ::: ```csharp showLineNumbers title="Unity" public void PaywallViewDidDisappear(AdaptyUIPaywallView view) { } ``` #### 产品选择 \{#product-selection\} 当用户或系统选择要购买的产品时触发。 ```csharp showLineNumbers title="Unity" public void PaywallViewDidSelectProduct( AdaptyUIPaywallView view, string productId ) { } ```
## 付费墙视图数量过大 \{#the-paywall-view-number-is-too-big\}
**问题**:付费墙视图计数显示的数量是预期数量的两倍。
**原因**:您可能在代码中调用了 `LogShowPaywall`,如果您正在使用付费墙编辑工具,这会导致视图计数重复。对于使用付费墙编辑工具设计的付费墙,分析数据会自动追踪,因此您无需使用此方法。
**解决方案**:如果您正在使用付费墙编辑工具,请确保代码中未调用 `LogShowPaywall`。
## 其他问题 \{#other-issues\}
**问题**:您遇到了上述未涵盖的其他付费墙编辑工具相关问题。
**解决方案**:如有需要,请参照[迁移指南](unity-sdk-migration-guides)将 SDK 升级至最新版本。许多问题已在较新版本的 SDK 中得到解决。
---
# File: unity-quickstart-manual
---
---
title: "在 Unity SDK 的自定义付费墙中启用购买功能"
description: "将 Adapty SDK 集成到您的自定义 Unity 付费墙中,以启用应用内购买。"
---
本指南介绍如何将 Adapty 集成到您的自定义付费墙中。您可以完全掌控付费墙的实现,同时由 Adapty SDK 负责获取产品、处理新购买以及恢复历史购买。
:::important
**本指南面向正在实现自定义付费墙的开发者。** 如果您希望以最简便的方式启用购买功能,请使用 [付费墙编辑工具](unity-quickstart-paywalls)。使用付费墙编辑工具,您可以在无代码可视化编辑器中创建付费墙,Adapty 会自动处理所有购买逻辑,您无需重新发布应用即可测试不同的设计方案。
:::
## 开始之前 \{#before-you-start\}
### 设置产品 \{#set-up-products\}
要启用应用内购买,您需要了解三个核心概念:
- [**产品**](product) – 用户可以购买的任何内容(订阅、消耗型商品、永久授权)
- [**付费墙**](paywalls) – 定义要展示哪些产品的配置。在 Adapty 中,付费墙是获取产品的唯一途径,但这种设计使您无需修改应用代码即可调整产品、价格和优惠。
- [**版位**](placements) – 在应用中展示付费墙的位置和时机(例如 `main`、`onboarding`、`settings`)。您在看板中为版位设置付费墙,然后在代码中通过版位 ID 请求它们。这使得运行 A/B 测试以及向不同用户展示不同付费墙变得轻而易举。
即使您使用自定义付费墙,也请确保理解这些概念。它们本质上只是您管理应用内销售产品的方式。
要实现自定义付费墙,您需要创建一个**付费墙**并将其添加到**版位**中。此设置使您能够获取产品。如需了解在看板中需要执行哪些操作,请参阅[此处](quickstart)的快速入门指南。
### 管理用户 \{#manage-users\}
您可以选择使用或不使用后端身份验证。
但请注意,Adapty SDK 对匿名用户和已识别用户的处理方式有所不同。请阅读[用户识别快速入门指南](unity-quickstart-identify),了解具体差异并确保您正确地管理用户。
## 第一步:获取产品 \{#step-1-get-products\}
要获取自定义付费墙的产品,您需要:
1. 通过将[版位](placements) ID 传递给 `getPaywall` 方法来获取 `paywall` 对象。
2. 使用 `getPaywallProducts` 方法获取该付费墙的产品数组。
```csharp showLineNumbers
using AdaptySDK;
void LoadPaywall() {
Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => {
if (error != null) {
// Handle the error
return;
}
Adapty.GetPaywallProducts(paywall, (products, productsError) => {
if (productsError != null) {
// Handle the error
return;
}
// Use products to build your custom paywall UI
});
});
}
```
## 第二步:接受购买 \{#step-2-accept-purchases\}
当用户在自定义付费墙中点击某个产品时,调用 `makePurchase` 方法并传入所选产品。该方法将处理购买流程并返回更新后的用户画像。
```csharp showLineNumbers
using AdaptySDK;
void PurchaseProduct(AdaptyPaywallProduct product) {
Adapty.MakePurchase(product, (result, error) => {
if (error != null) {
// Handle the error
return;
}
switch (result.Type) {
case AdaptyPurchaseResultType.Success:
var profile = result.Profile;
// Purchase successful, profile updated
break;
case AdaptyPurchaseResultType.UserCancelled:
// User canceled the purchase
break;
case AdaptyPurchaseResultType.Pending:
// Purchase is pending (e.g., user will pay offline with cash)
break;
}
});
}
```
## 第三步:恢复购买 \{#step-3-restore-purchases\}
应用商店要求所有包含订阅的应用为用户提供恢复购买的途径。
当用户点击恢复按钮时,调用 `restorePurchases` 方法。该方法将把用户的购买历史与 Adapty 同步,并返回更新后的用户画像。
```csharp showLineNumbers
using AdaptySDK;
void RestorePurchases() {
Adapty.RestorePurchases((profile, error) => {
if (error != null) {
// Handle the error
return;
}
// Restore successful, profile updated
});
}
```
## 后续步骤 \{#next-steps\}
:::tip
有疑问或遇到问题?欢迎访问我们的[支持论坛](https://adapty.featurebase.app/),在那里你可以找到常见问题的解答,也可以提出自己的问题。我们的团队和社区随时为你提供帮助!
:::
您的付费墙已准备好在应用中展示。请在 [App Store 沙盒](test-purchases-in-sandbox)或 [Google Play Store](testing-on-android) 中测试您的购买流程,以确保能够从付费墙完成测试购买。
接下来,[检查用户是否已完成购买](unity-check-subscription-status),以决定是否展示付费墙或授予付费功能的访问权限。
---
# File: fetch-paywalls-and-products-unity
---
---
title: "在 Unity SDK 中获取远程配置付费墙的付费墙和产品"
description: "在 Adapty Unity SDK 中获取付费墙和产品,以提升用户变现效果。"
---
在展示远程配置和自定义付费墙之前,您需要先获取相关信息。请注意,本主题涉及远程配置和自定义付费墙。如需获取付费墙编辑工具自定义付费墙的指导,请参阅[获取付费墙编辑工具付费墙及其配置](unity-get-pb-paywalls)。
:::tip
想看看 Adapty SDK 在移动应用中的实际集成示例吗?欢迎查看我们的[示例应用](sample-apps),其中演示了完整的集成流程,包括展示付费墙、完成购买以及其他基本功能。
:::
可选
默认值:`en`
|[付费墙本地化](add-remote-config-locale)的标识符。该参数应为由一个或多个子标签组成的语言代码,子标签之间用减号(**-**)分隔。第一个子标签表示语言,第二个表示地区。
示例:`en` 表示英语,`pt-br` 表示巴西葡萄牙语。
有关语言环境代码及推荐使用方式的更多信息,请参阅[本地化与语言环境代码](unity-localizations-and-locale-codes)。
| | **fetchPolicy** | 默认值:`.reloadRevalidatingCacheData` |默认情况下,SDK 将尝试从服务器加载数据,若失败则返回缓存数据。我们推荐此方式,因为它可确保用户始终获取最新数据。
但是,如果您认为用户的网络连接不稳定,可以考虑使用 `.returnCacheDataElseLoad`,在缓存数据存在时返回缓存数据。在这种情况下,用户可能无法获取绝对最新的数据,但无论网络状况如何,他们都会获得更快的加载速度。缓存会定期更新,因此在会话期间使用缓存以避免网络请求是安全的。
请注意,缓存在应用重启后仍然有效,只有在应用卸载重装或手动清理时才会被清除。
Adapty SDK 将付费墙存储在两个层级中:上述定期更新的缓存和[备用付费墙](unity-use-fallback-paywalls)。我们还使用 CDN 加速付费墙的获取,并在 CDN 不可用时使用独立的备用服务器。该系统旨在确保您始终获得最新版本的付费墙,同时即使在网络连接稀缺的情况下也能保证可靠性。
| | **loadTimeout** | 默认值:5 秒 |该值限制此方法的超时时间。若达到超时时间,将返回缓存数据或本地备用数据。
请注意,在极少数情况下,此方法的超时时间可能略晚于 `loadTimeout` 中指定的时间,因为该操作在底层可能包含多个不同的请求。
| 不要硬编码产品 ID!由于付费墙是远程配置的,可用产品、产品数量以及特殊优惠(如免费试用)可能随时发生变化。请确保您的代码能够处理这些情况。 例如,如果您最初获取到 2 个产品,您的应用应显示这 2 个产品。但如果您后来获取到 3 个产品,您的应用应显示所有 3 个产品,而无需修改任何代码。唯一需要硬编码的是版位 ID。 响应参数: | 参数 | 描述 | | :-------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------- | | Paywall | 一个 [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) 对象,包含:产品 ID 列表、付费墙标识符、远程配置及其他多个属性。 | ## 获取产品 \{#fetch-products\} 获取付费墙后,您可以查询与之对应的产品数组: ```csharp showLineNumbers Adapty.GetPaywallProducts(paywall, (products, error) => { if(error != null) { // handle the error return; } // products - the requested products array }); ``` 响应参数: | 参数 | 描述 | | :-------- | :------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ | | Products | [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) 对象列表,包含:产品标识符、产品名称、价格、货币、订阅时长及其他多个属性。 | 在实现自定义付费墙设计时,您可能需要访问 [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) 对象中的这些属性。以下列出了最常用的属性,但请参阅链接文档以获取所有可用属性的完整详情。 | 属性 | 描述 | |-------------------------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Title** | 要显示产品标题,请使用 `product.LocalizedTitle`。请注意,本地化基于用户在商店所选的国家/地区,而非设备本身的语言环境。 | | **Price** | 要显示本地化的价格,请使用 `product.Price.LocalizedString`。此本地化基于设备的语言环境信息。您也可以通过 `product.Price.Amount` 以数字形式访问价格,该值将以本地货币提供。要获取对应的货币符号,请使用 `product.Price.CurrencySymbol`。 | | **Subscription Period** | 要显示订阅周期(如周、月、年等),请使用 `product.Subscription?.LocalizedPeriod`。此本地化基于设备语言环境。要以编程方式获取订阅周期,请使用 `product.Subscription?.Period`。从中您可以访问 `Unit` 枚举以获取时长(即 `AdaptySubscriptionPeriodUnit.Day`、`AdaptySubscriptionPeriodUnit.Week`、`AdaptySubscriptionPeriodUnit.Month`、`AdaptySubscriptionPeriodUnit.Year` 或 `AdaptySubscriptionPeriodUnit.Unknown`)。`NumberOfUnits` 值将为您提供周期单位的数量。例如,对于季度订阅,Unit 属性中显示 `AdaptySubscriptionPeriodUnit.Month`,NumberOfUnits 属性中显示 `3`。 | | **Introductory Offer** | 要显示徽章或其他指示符以表明订阅包含新用户优惠,请查看 `product.Subscription?.Offer?.Phases` 属性。这是一个最多包含两个折扣阶段的列表:免费试用阶段和新用户优惠价格阶段。每个阶段对象包含以下有用属性:可选
默认值:`en`
|付费墙本地化的标识符。该参数应为由一个或两个子标签组成的语言代码,子标签之间用减号(**-**)分隔。第一个子标签表示语言,第二个表示地区。
示例:`en` 表示英语,`pt-br` 表示巴西葡萄牙语。
| | **fetchPolicy** | 默认值:`.reloadRevalidatingCacheData` |默认情况下,SDK 将尝试从服务器加载数据,若失败则返回缓存数据。我们推荐此选项,因为它可确保用户始终获取最新数据。
但是,如果您认为用户的网络连接不稳定,可以考虑使用 `.returnCacheDataElseLoad`,在缓存数据存在时返回缓存数据。在这种情况下,用户可能无法获取绝对最新的数据,但无论网络状况如何,他们都会获得更快的加载速度。缓存会定期更新,因此在会话期间使用缓存以避免网络请求是安全的。
请注意,缓存在应用重启后仍然有效,只有在应用卸载重装或手动清理时才会被清除。
Adapty SDK 在本地将付费墙存储在两个层级中:上述定期更新的缓存和备用付费墙。我们还使用 CDN 加速付费墙的获取,并在 CDN 不可用时使用独立的备用服务器。该系统旨在确保您始终获得最新版本的付费墙,同时即使在网络连接稀缺的情况下也能保证可靠性。
| --- # File: present-remote-config-paywalls-unity --- --- title: "在 Unity SDK 中渲染通过远程配置设计的付费墙" description: "了解如何在 Adapty Unity SDK 中展示远程配置付费墙,以个性化用户体验。" --- 如果您使用远程配置自定义了付费墙,则需要在移动应用代码中实现渲染逻辑,以便向用户展示它。由于远程配置提供了高度灵活性,您可以完全掌控付费墙视图中包含的内容及其显示方式。我们提供了获取远程配置的方法,让您能够自主展示通过远程配置配置的自定义付费墙。 ## 获取付费墙远程配置并展示 \{#get-paywall-remote-config-and-present-it\} 要获取付费墙的远程配置,请访问 `remoteConfig` 属性并提取所需的值。 ```csharp showLineNumbers Adapty.GetPaywall("YOUR_PLACEMENT_ID", (paywall, error) => { if (error != null) { // handle the error return; } // Access remote config dictionary var dictionary = paywall.RemoteConfig?.Dictionary; var headerText = dictionary?["header_text"] as string; // Or access raw JSON data var jsonData = paywall.RemoteConfig?.Data; }); ``` 此时,一旦您获取到所有必要的值,就可以将它们渲染并组合成一个美观的页面。请确保设计能够适配各种手机屏幕尺寸和方向,为不同设备上的用户提供流畅且友好的体验。 :::warning 请务必按照下文所述[记录付费墙浏览事件](present-remote-config-paywalls-unity#track-paywall-view-events),以便 Adapty 分析系统能够为漏斗和 A/B 测试采集相关数据。 ::: 展示付费墙完成后,请继续设置购买流程。当用户发起购买时,只需使用付费墙中的产品调用 `.MakePurchase()`。有关 `.MakePurchase()` 方法的详细信息,请参阅[发起购买](unity-making-purchases)。 我们建议[创建一个备用付费墙作为备份](unity-use-fallback-paywalls)。当用户没有网络连接或缓存不可用时,将向其展示此备用付费墙,确保在这些情况下也能提供流畅的体验。 ## 追踪付费墙浏览事件 \{#track-paywall-view-events\} Adapty 可帮助您衡量付费墙的表现。虽然我们会自动收集购买数据,但付费墙浏览记录需要您手动上报,因为只有您才知道用户何时看到了付费墙。 要记录付费墙浏览事件,只需调用 `.LogShowPaywall(paywall)`,该事件将反映在漏斗和 A/B 测试的付费墙数据图表中。 :::important 如果您展示的是通过[付费墙编辑工具](adapty-paywall-builder)创建的付费墙,则无需调用 `.LogShowPaywall(paywall)`。 ::: ```csharp showLineNumbers Adapty.LogShowPaywall(paywall, (error) => { // handle the error }); ``` 请求参数: | 参数 | 是否必填 | 描述 | | :---------- | :------- |:------------------------------------------------------------------| | **paywall** | 必填 | 一个 [`AdaptyPaywall`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) 对象。 | --- # File: unity-making-purchases --- --- title: "在 Unity SDK 的移动应用中进行购买" description: "使用 Adapty 处理应用内购买和订阅的指南。" --- 在您的移动应用中展示付费墙是向用户提供高级内容或服务访问权限的重要步骤。但是,仅仅展示付费墙只有在您使用[付费墙编辑工具](adapty-paywall-builder)自定义付费墙时,才足以支持购买。 如果您没有使用付费墙编辑工具,则必须使用一个单独的方法 `.makePurchase()` 来完成购买并解锁所需内容。该方法是用户与付费墙交互并完成所需交易的入口。 如果你的付费墙为用户正在购买的产品设置了有效的促销活动,Adapty 会在购买时自动应用该优惠。 :::warning 请注意,只有使用付费墙编辑工具搭建的付费墙,新用户优惠才会自动应用。 在其他情况下,您需要[验证用户在 iOS 上是否符合新用户优惠的条件](fetch-paywalls-and-products#check-intro-offer-eligibility-on-ios)。跳过此步骤可能导致应用在发布审核时被拒绝,还可能向本应享受新用户优惠的用户收取全价。 ::: 请确保您已[完成初始配置](quickstart),且没有跳过任何步骤。否则,我们将无法验证购买。 ## 进行购买 \{#make-purchase\} :::note **使用[付费墙编辑工具](adapty-paywall-builder)?** 购买会自动处理——可以跳过此步骤。 **需要分步指引?** 请查看[快速入门指南](unity-implement-paywalls-manually),其中包含完整的端到端实现说明。 ::: ```csharp showLineNumbers using AdaptySDK; void MakePurchase(AdaptyPaywallProduct product) { Adapty.MakePurchase(product, (result, error) => { switch (result.Type) { case AdaptyPurchaseResultType.Pending: // handle pending purchase break; case AdaptyPurchaseResultType.UserCancelled: // handle purchase cancellation break; case AdaptyPurchaseResultType.Success: var profile = result.Profile; // handle successfull purchase break; default: break; } }); } ``` 请求参数: | 参数 | 是否必填 | 描述 | | :---------- | :------- |:------------------------------------------------------------------------------------------------------| | **Product** | 必填 | 从付费墙中获取的 [`AdaptyPaywallProduct`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall_product.html) 对象。| 响应参数: | 参数 | 描述 | |---------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **Profile** |请求成功后,响应中会包含此对象。[AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) 对象提供了用户在应用内的访问等级、订阅及一次性购买的完整信息。
请检查访问等级状态,以确认用户是否拥有所需的应用访问权限。
| :::warning **注意:** 如果你使用的 Apple StoreKit 版本低于 v2.0,且 Adapty SDK 版本低于 v2.9.0,则需要提供 [Apple App Store 共享密钥](app-store-connection-configuration#step-5-enter-app-store-shared-secret)。此方法目前已被 Apple 弃用。 ::: ## 购买时更改订阅 \{#change-subscription-when-making-a-purchase\} 当用户选择新订阅而非续订当前订阅时,具体行为取决于所使用的应用商店: - 对于 App Store,订阅会在同一订阅组内自动更新。如果用户在已有某个订阅组的订阅的情况下,又购买了另一个订阅组的订阅,则两个订阅将同时处于激活状态。 - 对于 Google Play,订阅不会自动更新。你需要按照下方说明,在移动应用代码中手动处理订阅切换逻辑。 在 Android 上将订阅替换为另一个订阅,请在调用 `.makePurchase()` 方法时传入额外参数: ```csharp showLineNumbers // Create subscription update parameters var subscriptionUpdateParams = new AdaptySubscriptionUpdateParameters( "old_product_id", // Product ID of the current subscription AdaptySubscriptionUpdateReplacementMode.WithTimeProration ); Adapty.MakePurchase(product, subscriptionUpdateParams, (profile, error) => { if(error != null) { // Handle the error return; } // successful cross-grade }); ``` 额外请求参数: | 参数 | 是否必填 | 描述 | | :--------------------------- | :------- |:-------------------------------------------------------------------------------------------------------| | **subscriptionUpdateParams** | 必填 | 一个 [`AdaptySubscriptionUpdateParameters`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_subscription_update_parameters.html) 对象。 | 如需了解更多关于订阅和替换模式的内容,请参阅 Google 开发者文档: - [关于替换模式](https://developer.android.com/google/play/billing/subscriptions#replacement-modes) - [Google 针对替换模式的建议](https://developer.android.com/google/play/billing/subscriptions#replacement-recommendations) - 替换模式 [`CHARGE_PRORATED_PRICE`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#CHARGE_PRORATED_PRICE())。注意:此方法仅适用于订阅升级,不支持降级。 - 替换模式 [`DEFERRED`](https://developer.android.com/reference/com/android/billingclient/api/BillingFlowParams.SubscriptionUpdateParams.ReplacementMode#DEFERRED())。注意:实际的订阅变更仅在当前订阅计费周期结束时生效。 ## 在 iOS 中兑换优惠码 \{#redeem-offer-codes-in-ios\}一个 [`AdaptyProfile`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) 对象。该模型包含有关访问等级、订阅和非订阅购买的信息。
请检查**访问等级状态**以确定用户是否有权访问该应用。
| :::tip 想看看 Adapty SDK 在移动应用中的实际集成示例吗?欢迎查看我们的[示例应用](sample-apps),其中演示了完整的集成流程,包括展示付费墙、完成购买以及其他基本功能。 ::: --- # File: implement-observer-mode-unity --- --- title: "在 Unity SDK 中实现观察者模式" description: "在 Adapty 中实现观察者模式,以在 Unity SDK 中追踪用户订阅事件。" --- 如果您已经拥有自己的购买基础设施,并且尚未准备好完全切换到 Adapty,您可以了解[观察者模式](observer-vs-full-mode)。在其基本形式下,观察者模式提供高级分析功能以及与归因和分析系统的无缝集成。 如果这满足您的需求,您只需: 1. 在配置 Adapty SDK 时将 `observerMode` 参数设置为 `true` 来启用它。请参照 [Unity](sdk-installation-unity#activate-adapty-module-of-adapty-sdk) 的设置说明。 2. 将现有购买基础设施中的[交易上报](report-transactions-observer-mode-unity)给 Adapty。 ### 观察者模式设置 \{#observer-mode-setup\} 如果您自行处理购买和订阅状态,并使用 Adapty 发送订阅事件和分析数据,请启用观察者模式。 :::important 在观察者模式下运行时,Adapty SDK 不会关闭任何交易,请确保您自行处理这一事项。 ::: ```csharp showLineNumbers title="C#" using UnityEngine; using AdaptySDK; public class AdaptyListener : MonoBehaviour, AdaptyEventListener { void Start() { DontDestroyOnLoad(this.gameObject); Adapty.SetEventListener(this); var builder = new AdaptyConfiguration.Builder("YOUR_PUBLIC_SDK_KEY") .SetObserverMode(true); // Enable observer mode Adapty.Activate(builder.Build(), (error) => { if (error != null) { // handle the error return; } }); } public void OnLoadLatestProfile(AdaptyProfile profile) { } public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { } public void OnInstallationDetailsFail(AdaptyError error) { } } ``` 参数: | 参数 | 描述 | |--------------|-------------------------------------------------------------------------------------------------------------| | observerMode | 用于控制[观察者模式](observer-vs-full-mode)的布尔值。默认值为 `false`。 | ## 在观察者模式下使用 Adapty 付费墙 \{#using-adapty-paywalls-in-observer-mode\} 如果您还想使用 Adapty 的付费墙和 A/B 测试功能,也是可以的——但在观察者模式下需要一些额外的设置。除了上述步骤之外,您还需要: 1. 按照[远程配置付费墙](present-remote-config-paywalls-unity)的常规方式展示付费墙。 3. 将付费墙与购买交易进行[关联](report-transactions-observer-mode-unity)。 --- # File: report-transactions-observer-mode-unity --- --- title: "在 Unity SDK 的观察者模式下上报交易" description: "在 Adapty 观察者模式下上报购买交易,用于用户洞察和收入追踪(Unity SDK)。" ---iOS,StoreKit 1:一个 [SKPaymentTransaction](https://developer.apple.com/documentation/storekit/skpaymenttransaction) 对象。
iOS,StoreKit 2:[Transaction](https://developer.apple.com/documentation/storekit/transaction) 对象。
Android:购买的字符串标识符(purchase.getOrderId),其中 purchase 是计费库 [Purchase](https://developer.android.com/reference/com/android/billingclient/api/Purchase) 类的实例。
| | variationId | 必填 | 实验变体的字符串标识符。可通过 [AdaptyPaywall](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_paywall.html) 对象的 `variationId` 属性获取。 |phoneNumber
firstName
lastName
| String | | gender | 枚举,允许的值为:`female`、`male`、`other` | | birthday | Date | ### 自定义用户属性 \{#custom-user-attributes\} 您可以设置自定义属性,这些属性通常与您的应用使用情况相关。例如,对于健身应用,可以是每周锻炼次数;对于语言学习应用,可以是用户的知识水平等。您可以在市场细分中使用这些属性来创建有针对性的付费墙和优惠,也可以在分析中使用它们来确定哪些产品指标对收入影响最大。 ```csharp showLineNumbers try { builder = builder.SetCustomStringAttribute("string_key", "string_value"); builder = builder.SetCustomDoubleAttribute("double_key", 123.0f); } catch (Exception e) { // handle the exception } ``` 要删除现有键,请使用 `.withRemoved(customAttributeForKey:)` 方法: ```csharp showLineNumbers try { builder = builder.RemoveCustomAttribute("key_to_remove"); } catch (Exception e) { // handle the exception } ``` 有时您需要查看已设置的自定义属性。为此,请使用 `AdaptyProfile` 对象的 `customAttributes` 字段。 :::warning 请注意,`customAttributes` 的值可能并非最新,因为用户属性可以随时从不同设备发送,因此服务器上的属性可能在上次同步后已发生变化。 ::: ### 限制 \{#limits\} - 每位用户最多 30 个自定义属性 - 键名最多 30 个字符,可包含字母数字字符及以下任意字符:`_` `-` `.` - 值可以是字符串或浮点数,最多 50 个字符。 --- # File: unity-listen-subscription-changes --- --- title: "在 Unity SDK 中检查订阅状态" description: "在 Adapty 中追踪和管理用户订阅状态,提升 Unity 应用的用户留存率。" --- 借助 Adapty,追踪订阅状态变得轻而易举。您无需在代码中手动插入产品 ID,只需检查用户是否拥有有效的[访问等级](access-level),即可确认其订阅状态。[AdaptyProfile](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_profile.html) 对象。通常,您只需检查用户画像的访问等级状态,即可判断用户是否拥有应用的高级权限。
`.getProfile` 方法始终会尝试请求 API,因此可提供最新的结果。如果由于某些原因(如无网络连接)Adapty SDK 无法从服务器获取信息,则会返回缓存中的数据。值得注意的是,Adapty SDK 会定期更新 `AdaptyProfile` 缓存,以尽可能保持信息的最新状态。
| `.getProfile()` 方法会返回用户画像,您可以从中获取访问等级状态。每个应用可以设置多个访问等级。例如,如果您有一个新闻应用,并针对不同主题独立销售订阅,可以创建"sports"和"science"等访问等级。但大多数情况下,您只需要一个访问等级,此时直接使用默认的"premium"访问等级即可。 以下是检查默认"premium"访问等级的示例: ```csharp showLineNumbers Adapty.GetProfile((profile, error) => { if (error != null) { // handle the error return; } // "premium" is an identifier of default access level var accessLevel = profile.AccessLevels["premium"]; if (accessLevel != null && accessLevel.IsActive) { // grant access to premium features } }); ``` ### 监听订阅状态更新 \{#listening-for-subscription-status-updates\} 每当用户的订阅发生变化时,Adapty 都会触发相应事件。 要接收来自 Adapty 的消息,您需要进行一些额外配置: ```csharp showLineNumbers // Extend `AdaptyEventListener ` with `OnLoadLatestProfile ` method: public class AdaptyListener : MonoBehaviour, AdaptyEventListener { public void OnLoadLatestProfile(AdaptyProfile profile) { // handle any changes to subscription state } } ``` Adapty 也会在应用启动时触发事件,此时将传递缓存的订阅状态。 ### 订阅状态缓存 \{#subscription-status-cache\} Adapty SDK 中实现的缓存会存储用户画像的订阅状态。这意味着即使服务器不可用,也可以访问缓存数据以获取用户画像的订阅状态信息。 但需要注意的是,无法直接从缓存中请求数据。SDK 会每分钟定期向服务器查询,以检查用户画像是否有任何更新或变更。如果存在任何修改(如新的交易记录或其他更新),这些变更将同步至缓存数据,以确保其与服务器保持一致。 --- # File: unity-deal-with-att --- --- title: "在 Unity SDK 中处理 ATT" description: "在 Unity 上开始使用 Adapty,简化订阅设置与管理。" --- 如果您的应用使用了 AppTrackingTransparency 框架,并向用户展示应用跟踪授权请求,则应将[授权状态](https://developer.apple.com/documentation/apptrackingtransparency/attrackingmanager/authorizationstatus/)发送给 Adapty。 ```csharp showLineNumbers var builder = new Adapty.ProfileParameters.Builder() .SetAppTrackingTransparencyStatus(IOSAppTrackingTransparencyStatus.Authorized); Adapty.UpdateProfile(builder.Build(), (error) => { if(error != null) { // handle the error } }); ``` :::warning 我们强烈建议您在该值发生变化时尽早发送,只有这样,数据才能及时传送到您已配置的集成渠道。 ::: --- # File: kids-mode-unity --- --- title: "Unity SDK 中的儿童模式" description: "轻松启用儿童模式以符合 Apple 和 Google 的政策。Unity SDK 中不收集 IDFA、GAID 或广告数据。" --- 如果您的 Unity 应用面向儿童,则必须遵守 [Apple](https://developer.apple.com/kids/) 和 [Google](https://support.google.com/googleplay/android-developer/answer/9893335) 的政策。如果您使用的是 Adapty SDK,只需几个简单的步骤即可将其配置为符合这些政策,并通过应用商店审核。 ## 需要做什么? \{#whats-required\} 您需要配置 Adapty SDK 以禁止收集以下信息: - [IDFA(广告标识符)](https://en.wikipedia.org/wiki/Identifier_for_Advertisers)(iOS) - [Android 广告 ID(AAID/GAID)](https://support.google.com/googleplay/android-developer/answer/6048248)(Android) - [IP 地址](https://www.ftc.gov/system/files/ftc_gov/pdf/p235402_coppa_application.pdf) 此外,我们建议谨慎使用客户用户 ID。`可选
默认值:`en`
|用户引导本地化的标识符。该参数应为由减号(**-**)分隔的一个或两个子标签组成的语言代码。第一个子标签表示语言,第二个子标签表示地区。
示例:`en` 表示英语,`pt-br` 表示巴西葡萄牙语。
有关区域设置代码及推荐使用方式的更多信息,请参阅[本地化与区域设置代码](flutter-localizations-and-locale-codes)。
| | **fetchPolicy** | 默认值:`.reloadRevalidatingCacheData` |默认情况下,SDK 会尝试从服务器加载数据,若失败则返回缓存数据。我们推荐此选项,因为它能确保用户始终获取最新数据。
但是,如果您认为用户的网络连接不稳定,可以考虑使用 `.returnCacheDataElseLoad`,在缓存存在时返回缓存数据。在这种情况下,用户可能无法获取绝对最新的数据,但无论网络连接多么不稳定,都能体验到更快的加载速度。缓存会定期更新,因此在会话期间使用缓存以避免网络请求是安全的。
请注意,缓存在应用重启后保持不变,仅在重新安装应用或手动清理时才会清除。
Adapty SDK 在本地以两个层次存储用户引导:上述定期更新的缓存以及备用用户引导。我们还使用 CDN 更快地获取用户引导,并在 CDN 无法访问时使用独立的备用服务器。该系统旨在确保您始终获得最新版本的用户引导,同时在网络连接不佳的情况下也能保证可靠性。
| | **loadTimeout** | 默认值:5 秒 |此值限制该方法的超时时间。如果达到超时时间,将返回缓存数据或本地备用内容。
请注意,在极少数情况下,此方法可能比 `loadTimeout` 中指定的时间稍晚超时,因为该操作在内部可能由多个不同请求组成。
| 响应参数: | 参数 | 描述 | |:----------|:------------------------------------------------------------------------------------------------------------------------------------------------------------------| | Onboarding | 一个 [`AdaptyOnboarding`](https://unity.adapty.io/class_adapty_s_d_k_1_1_adapty_onboarding.html) 对象,包含:用户引导标识符和配置、远程配置以及其他几个属性。 | 获取用户引导后,调用 `CreateOnboardingView` 方法。 :::warning `CreateOnboardingView` 方法的结果只能使用一次。如果需要再次使用,请重新调用 `CreateOnboardingView` 方法。在不重新创建的情况下调用两次可能会导致 `AdaptyUIError.viewAlreadyPresented` 错误。 ::: ```csharp showLineNumbers AdaptyUI.CreateOnboardingView(onboarding, (view, error) => { // handle the result }); ``` 参数: | 参数 | 是否必填 | 描述 | |:---------------| :------------- |:-----------------------------------------------------------------------------| | **onboarding** | 必填 | 用于获取所需用户引导视图的 `AdaptyOnboarding` 对象。 | | **externalUrlsPresentation** |可选
默认值:`InAppBrowser`
|控制用户引导中链接的打开方式。可用选项:
- `AdaptyWebPresentation.InAppBrowser` - 在应用内浏览器中打开链接(默认)
- `AdaptyWebPresentation.ExternalBrowser` - 在设备外部浏览器中打开链接
使用示例请参阅[自定义用户引导中链接的打开方式](unity-present-onboardings#customize-how-links-open-in-onboardings)。
| 成功加载用户引导及其视图配置后,您可以[在移动应用中展示它](unity-present-onboardings)。 ## 使用默认目标受众用户引导加速获取 \{#speed-up-onboarding-fetching-with-default-audience-onboarding\} 通常情况下,用户引导几乎可以即时获取,因此您无需担心加速此过程。但是,如果您拥有大量目标受众和用户引导,且用户的网络连接较弱,获取用户引导可能需要比预期更长的时间。在这种情况下,您可能希望显示默认用户引导,以确保流畅的用户体验,而不是完全不显示用户引导。 为此,您可以使用 `GetOnboardingForDefaultAudience` 方法,该方法为**所有用户**目标受众获取指定版位的用户引导。但是,务必理解,推荐的方式是通过 `getOnboarding` 方法获取用户引导,详见上方[获取用户引导](#fetch-onboarding)部分。 :::warning 建议使用 `GetOnboarding` 而非 `GetOnboardingForDefaultAudience`,因为后者有以下重要限制: - **兼容性问题**:在支持多个应用版本时可能产生问题,需要向后兼容的设计,否则较旧版本可能显示不正确。 - **无个性化**:仅显示"所有用户"目标受众的内容,无法根据国家、归因或自定义属性进行定向。 如果对您的使用场景而言,更快的获取速度超过了这些缺点,请按如下所示使用 `GetOnboardingForDefaultAudience`。否则,请按[上方](#fetch-onboarding)所述使用 `GetOnboarding`。 ::: ```csharp showLineNumbers Adapty.GetOnboardingForDefaultAudience("YOUR_PLACEMENT_ID", (onboarding, error) => { if (error != null) { // handle the error return; } // the requested onboarding }); ``` 参数: | 参数 | 是否必填 | 描述 | |---------|--------|----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| | **placementId** | 必填 | 所需[版位](placements)的标识符。这是您在 Adapty 看板中创建版位时指定的值。 | | **locale** |可选
默认值:`en`
|用户引导本地化的标识符。该参数应为由减号(**-**)分隔的一个或两个子标签组成的语言代码。第一个子标签表示语言,第二个子标签表示地区。
示例:`en` 表示英语,`pt-br` 表示巴西葡萄牙语。
| | **fetchPolicy** | 默认值:`.reloadRevalidatingCacheData` |默认情况下,SDK 会尝试从服务器加载数据,若失败则返回缓存数据。我们推荐此选项,因为它能确保用户始终获取最新数据。
但是,如果您认为用户的网络连接不稳定,可以考虑使用 `.returnCacheDataElseLoad`,在缓存存在时返回缓存数据。在这种情况下,用户可能无法获取绝对最新的数据,但无论网络连接多么不稳定,都能体验到更快的加载速度。缓存会定期更新,因此在会话期间使用缓存以避免网络请求是安全的。
请注意,缓存在应用重启后保持不变,仅在重新安装应用或手动清理时才会清除。
Adapty SDK 在本地以两个层次存储用户引导:上述定期更新的缓存以及备用用户引导。我们还使用 CDN 更快地获取用户引导,并在 CDN 无法访问时使用独立的备用服务器。该系统旨在确保您始终获得最新版本的用户引导,同时在网络连接不佳的情况下也能保证可靠性。
| --- # File: unity-present-onboardings --- --- title: "在 Unity SDK 中展示用户引导" description: "了解如何有效地展示用户引导以提升转化率。" --- 如果你已经在编辑工具中自定义了用户引导,就不需要在 Unity 应用代码中另行处理渲染逻辑——该用户引导已经包含了展示内容和展示方式的完整配置。 开始之前,请确保: 1. 已安装 [Adapty Unity SDK](sdk-installation-unity) 3.14.0 或更高版本。 2. 已[创建用户引导](create-onboarding)。 3. 已将用户引导添加到[版位](placements)。 要展示用户引导,请对 `CreateOnboardingView` 方法创建的 `view` 调用 `view.Present()` 方法。每个 `view` 只能使用一次。如需再次展示付费墙,请重新调用 `CreateOnboardingView` 创建新的 `view` 实例。 :::warning 在未重新创建 `view` 的情况下复用同一个 `view`,可能会导致 `AdaptyUIError.viewAlreadyPresented` 错误。 ::: ```csharp showLineNumbers title="Unity" view.Present((presentError) => { if (presentError != null) { // handle the error } }; ``` ## 配置 iOS 展示样式 \{#configure-ios-presentation-style\} 通过将 `iosPresentationStyle` 参数传递给 `Present()` 方法,可配置用户引导在 iOS 上的展示方式。该参数接受 `AdaptyUIIOSPresentationStyle.FullScreen`(默认值)或 `AdaptyUIIOSPresentationStyle.PageSheet` 值。 ```csharp showLineNumbers title="Unity" view.Present(AdaptyUIIOSPresentationStyle.PageSheet, (error) => { // handle the error }); ``` ## 自定义用户引导中链接的打开方式 \{#customize-how-links-open-in-onboardings\} :::important 自定义用户引导中链接打开方式的功能从 Adapty SDK v3.15 开始支持。 ::: 默认情况下,用户引导中的链接会在应用内浏览器中打开,让用户无需切换应用即可直接查看网页内容,体验更加流畅。 如需改为在外部浏览器中打开链接,请将 `AdaptyWebPresentation.ExternalBrowser` 传入 `CreateOnboardingView` 方法: ```csharp showLineNumbers title="Unity" AdaptyUI.CreateOnboardingView( onboarding, AdaptyWebPresentation.ExternalBrowser, // default — InAppBrowser (view, error) => { if (error != null) { // handle the error return; } // present the onboarding view view.Present((presentError) => { if (presentError != null) { // handle the error } }); } ); ``` 可用选项: - `AdaptyWebPresentation.InAppBrowser` - 在应用内浏览器中打开链接(默认) - `AdaptyWebPresentation.ExternalBrowser` - 在设备的外部浏览器中打开链接 --- # File: unity-handling-onboarding-events --- --- title: "在 Unity SDK 中处理用户引导事件" description: "使用 Adapty 在 Unity 中处理用户引导相关事件。" --- 在开始之前,请确保: 1. 您已安装 [Adapty Unity SDK](sdk-installation-unity) 3.14.0 或更高版本。 2. 您已[创建用户引导](create-onboarding)。 3. 您已将用户引导添加到[版位](placements)。 使用编辑工具配置的用户引导会生成应用可以响应的事件。请参阅以下内容了解如何响应这些事件。 要在 Unity 应用中控制或监控用户引导界面上发生的流程,请实现 `AdaptyOnboardingsEventsListener` 接口。 ## 自定义动作 \{#custom-actions\} 在编辑工具中,您可以为按钮添加**自定义**动作并为其分配一个 ID。
然后,您可以在代码中使用此 ID 并将其作为自定义动作处理。例如,当用户点击自定义按钮(如**登录**或**允许通知**)时,将触发 `OnboardingViewOnCustomAction` 方法,其中 `actionId` 参数为编辑工具中的 **Action ID**。您可以创建自己的 ID,例如 "allowNotifications"。
要处理用户引导事件,请实现 `AdaptyOnboardingsEventsListener` 接口:
```csharp showLineNumbers title="Unity"
public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener
{
void Start()
{
Adapty.SetOnboardingsEventsListener(this);
}
public void OnboardingViewOnCustomAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
string actionId
)
{
if (actionId == "allowNotifications") {
// request notification permissions
}
}
public void OnboardingViewDidFailWithError(
AdaptyUIOnboardingView view,
AdaptyError error
)
{
// handle errors
}
// Implement other required interface methods (see examples below)
}
```
:::important
请注意,您需要自行管理用户关闭用户引导后发生的事情。例如,您需要停止显示用户引导本身。
:::
在您的类中实现 `OnboardingViewOnCloseAction` 方法:
```csharp showLineNumbers title="Unity"
public class OnboardingManager : MonoBehaviour, AdaptyOnboardingsEventsListener
{
public void OnboardingViewOnCloseAction(
AdaptyUIOnboardingView view,
AdaptyUIOnboardingMeta meta,
string actionId
)
{
view.Dismiss((error) => {
if (error != null) {
// handle the error
}
});
}
// ... other interface methods
}
```
2. 点击订阅组名称,你将在 **Subscriptions** 区域看到所有产品。
3. 确认你要测试的产品已标记为 **Ready to Submit**。
4. 将表格中的产品 ID 与 Adapty 看板中 [**Products**](https://app.adapty.io/products) 标签页里的产品 ID 进行比对。如果 ID 不匹配,请从表格中复制该产品 ID,然后在 Adapty 看板中[创建产品](create-product)。
## 第 3 步:检查产品可用性 \{#step-4-check-product-availability\}
1. 返回 **App Store Connect**,打开同一个 **Subscriptions** 页面。
2. 点击订阅组名称,查看你的产品。
3. 选择您要测试的产品。
4. 滚动至 **Availability** 部分,确认所有所需国家和地区均已列出。
## 第 4 步:检查产品价格 \{#step-5-check-product-prices\}
1. 再次前往 **App Store Connect** 中的 **Monetization** → **Subscriptions** 部分。
2. 点击订阅组名称。
3. 选择您要测试的产品。
4. 向下滚动至 **Subscription Pricing**,展开 **Current Pricing for New Subscribers** 部分。
5. 确保所有必填价格均已填写。
## 第 5 步:确认应用付费状态、银行账户及税务表格均已生效 \{#step-5-check-app-paid-status-bank-account-and-tax-forms-are-active\}
1. 在 [**App Store Connect**](https://appstoreconnect.apple.com/) 主页,点击 **Business**。
2. 选择你的公司名称。
3. 向下滚动,确认你的 **Paid Apps Agreement**、**Bank Account** 和 **Tax forms** 均显示为 **Active**。
按照以上步骤,您应该能够解决 `InvalidProductIdentifiers` 警告,并让您的产品在商店中上线。
## 第 6 步:若产品卡住,请重新创建 \{#step-6-recreate-the-product-if-its-stuck\}
即使第 1–5 步全部通过——状态为 `Approved`、Bundle ID 匹配、API 密钥有效——SDK 仍然可能返回 `1000 noProductIDsFound`。这种情况下,产品可能卡在了 Apple 的注册表中。Apple 的产品注册表偶尔会进入一种状态:产品在 App Store Connect 界面中存在,但无法通过 StoreKit 的查找路径被识别。
在 App Store Connect 中删除该产品,然后用相同的产品 ID 重新创建。重新创建后,最长需要等待 24 小时才能完成同步。
---
# File: cantMakePayments-unity
---
---
title: "修复 Unity SDK 中 Code-1003 cantMakePayment 错误"
description: "解决在 Adapty 中管理订阅时出现的支付错误。"
---
1003 错误 `cantMakePayments` 表示该设备无法进行应用内购买。
如果你遇到了 `cantMakePayments` 错误,通常是由以下原因之一导致的:
- 设备限制:该错误与 Adapty 无关。请参阅下方的修复方法。
- 观察者模式配置:`makePurchase` 方法与观察者模式不能同时使用。请参阅下方相关章节。
## 问题:设备限制 \{#issue-device-restrictions\}
| 问题 | 解决方案 |
|---------------------------|---------------------------------------------------------|
| 屏幕使用时间限制 | 在 [Screen Time](https://support.apple.com/en-us/102470) 中关闭应用内购买限制 |
| 账户被暂停 | 联系 Apple 支持以解决账户问题 |
| 地区限制 | 使用受支持地区的 App Store 账户 |
## 问题:同时使用观察者模式和 makePurchase \{#issue-using-both-observer-mode-and-makepurchase\}
如果你使用 `makePurchases` 来处理购买,则无需启用观察者模式。[观察者模式](observer-vs-full-mode) 仅在你自行实现购买逻辑时才需要使用。
因此,如果你正在使用 `makePurchase`,可以安全地从 SDK 激活代码中移除对观察者模式的启用。
---
# File: migration-to-unity-sdk-314
---
---
title: "迁移 Adapty Unity SDK 至 v3.14"
description: "迁移至 Adapty Unity SDK v3.14,获得更好的性能和新的变现功能。"
---
Adapty SDK 3.14.0 是一个主要版本,带来了一些改进,但可能需要你执行一些迁移步骤:
1. 为付费墙事件添加独立的事件监听器。
2. 将 `AdaptyUI.CreateView` 重命名为 `AdaptyUI.CreatePaywallView` 及相关方法。
3. 更新 `MakePurchase` 方法,改用 `AdaptyPurchaseParameters` 替代单独参数。
4. 将 `SetFallbackPaywalls` 替换为 `SetFallback` 方法。
5. 更新付费墙属性访问方式,改用 `AdaptyPlacement`。
6. 更新远程配置访问方式,改用 `AdaptyRemoteConfig` 对象。
7. 将 `AdaptyPaywall` 模型中的 `VendorProductIds` 替换为 `ProductIdentifiers`。
8. 更新 `GetPaywall` 的获取策略,改用 `AdaptyFetchPolicy`。
## 付费墙事件的独立事件监听器 \{#separate-event-listener-for-paywall-events\}
如果你展示的付费墙是通过[付费墙编辑工具](adapty-paywall-builder)设计的,付费墙视图事件现在使用专用的 `AdaptyPaywallsEventsListener` 接口和 `SetPaywallsEventsListener` 方法。核心 `AdaptyEventListener` 接口仍用于用户画像更新和安装详情。
```diff showLineNumbers
using UnityEngine;
using AdaptySDK;
public class AdaptyListener : MonoBehaviour,
- AdaptyEventListener {
+ AdaptyEventListener,
+ AdaptyPaywallsEventsListener {
void Start() {
Adapty.SetEventListener(this);
+ Adapty.SetPaywallsEventsListener(this);
}
// AdaptyEventListener methods
public void OnLoadLatestProfile(AdaptyProfile profile) { }
public void OnInstallationDetailsSuccess(AdaptyInstallationDetails details) { }
public void OnInstallationDetailsFail(AdaptyError error) { }
+ // AdaptyPaywallsEventsListener methods
+ // Implement paywall event handlers here
}
```
[了解有关处理付费墙事件的更多信息](unity-handling-events)。
## 重命名视图创建与展示方法 \{#rename-view-creation-and-presentation-methods\}
视图创建和展示方法已重命名:
```diff showLineNumbers
using AdaptySDK;
- AdaptyUI.CreateView(paywall, parameters, (view, error) => {
+ AdaptyUI.CreatePaywallView(paywall, parameters, (view, error) => {
if (error != null) {
// handle the error
return;
}
- AdaptyUI.PresentView(view, (error) => {
+ AdaptyUI.PresentPaywallView(view, (error) => {
// handle the error
});
});
}
```
同样,关闭方法也已重命名:
```diff showLineNumbers
- AdaptyUI.DismissView(view, (error) => {
+ AdaptyUI.DismissPaywallView(view, (error) => {
// handle the error
});
```
## 更新 MakePurchase 方法 \{#update-makepurchase-method\}
`MakePurchase` 方法现在使用 `AdaptyPurchaseParameters`,替代了原来独立的 `subscriptionUpdateParams` 和 `isOfferPersonalized` 参数。这样做可以提升类型安全性,并为未来扩展购买参数预留空间。
```diff showLineNumbers
using AdaptySDK;
void MakePurchase(
AdaptyPaywallProduct product,
AdaptySubscriptionUpdateParameters subscriptionUpdate,
bool? isOfferPersonalized
) {
- Adapty.MakePurchase(product, subscriptionUpdate, isOfferPersonalized, (result, error) => {
+ var parameters = new AdaptyPurchaseParametersBuilder()
+ .SetSubscriptionUpdateParams(subscriptionUpdate)
+ .SetIsOfferPersonalized(isOfferPersonalized)
+ .Build();
+
+ Adapty.MakePurchase(product, parameters, (result, error) => {
switch (result.Type) {
case AdaptyPurchaseResultType.Pending:
// handle pending purchase
break;
case AdaptyPurchaseResultType.UserCancelled:
// handle purchase cancellation
break;
case AdaptyPurchaseResultType.Success:
var profile = result.Profile;
// handle successful purchase
break;
default:
break;
}
});
}
```
如果不需要额外参数,可以直接使用:
```csharp showLineNumbers
using AdaptySDK;
void MakePurchase(AdaptyPaywallProduct product) {
Adapty.MakePurchase(product, (result, error) => {
// handle purchase result
});
}
```
## 更新备用付费墙方法 \{#update-fallback-method\}
:::important
升级到 Unity SDK 3.14 时,你需要从 Adapty 看板下载新的备用文件,并替换项目中的现有文件。
:::
设置备用付费墙的方法已更新。`SetFallbackPaywalls` 方法已重命名为 `SetFallback`:
```diff showLineNumbers
using AdaptySDK;
void SetFallBackPaywalls() {
#if UNITY_IOS
var assetId = "adapty_fallback_ios.json";
#elif UNITY_ANDROID
var assetId = "adapty_fallback_android.json";
#else
var assetId = "";
#endif
- Adapty.SetFallbackPaywalls(assetId, (error) => {
+ Adapty.SetFallback(assetId, (error) => {
// handle the error
});
}
```
请查看 [在 Unity 中使用备用付费墙](unity-use-fallback-paywalls) 页面中的完整代码示例。
## 更新付费墙属性访问方式 \{#update-paywall-property-access\}
以下属性已从 `AdaptyPaywall` 移至 `AdaptyPlacement`:
```diff showLineNumbers
using AdaptySDK;
void ProcessPaywall(AdaptyPaywall paywall) {
- var abTestName = paywall.ABTestName;
- var audienceName = paywall.AudienceName;
- var revision = paywall.Revision;
- var placementId = paywall.PlacementId;
+ var abTestName = paywall.Placement.ABTestName;
+ var audienceName = paywall.Placement.AudienceName;
+ var revision = paywall.Placement.Revision;
+ var placementId = paywall.Placement.Id;
}
```
## 更新远程配置访问方式 \{#update-remote-config-access\}
远程配置属性已被重构为 `AdaptyRemoteConfig` 对象,以提供更好的组织结构:
```diff showLineNumbers
using AdaptySDK;
void ProcessRemoteConfig(AdaptyPaywall paywall) {
- var remoteConfigString = paywall.RemoteConfigString;
- var locale = paywall.Locale;
- var remoteConfigDict = paywall.RemoteConfig;
+ var remoteConfigString = paywall.RemoteConfig.Data;
+ var locale = paywall.RemoteConfig.Locale;
+ var remoteConfigDict = paywall.RemoteConfig.Dictionary;
}
```
## 更新 AdaptyPaywall 模型用法 \{#update-adaptypaywall-model-usage\}
`VendorProductIds` 属性已被弃用,请改用 `ProductIdentifiers`。新属性返回 `AdaptyProductIdentifier` 对象,而非简单的字符串,能提供更结构化的产品信息。
```diff showLineNumbers
using AdaptySDK;
void ProcessPaywallProducts(AdaptyPaywall paywall) {
- var productIds = paywall.VendorProductIds;
- foreach (var vendorId in productIds) {
- // use vendorId
- }
+ var productIdentifiers = paywall.ProductIdentifiers;
+ foreach (var productId in productIdentifiers) {
+ var vendorId = productId.VendorProductId;
+ // use vendorId
+ }
}
```
`AdaptyProductIdentifier` 对象通过 `VendorProductId` 属性提供对厂商产品 ID 的访问,在保持原有功能的同时,为未来的功能扩展提供了更清晰的结构。
## 更新 GetPaywall 获取策略 \{#update-getpaywall-fetch-policy\}
`GetPaywall` 方法中的 `fetchPolicy` 参数类型已从 `AdaptyPaywallFetchPolicy` 更改为 `AdaptyPlacementFetchPolicy`。此更改统一了 SDK 中获取策略的使用方式。
```diff showLineNumbers
using AdaptySDK;
void GetPaywall(string placementId) {
- Adapty.GetPaywall(placementId, AdaptyPaywallFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => {
+ Adapty.GetPaywall(placementId, AdaptyPlacementFetchPolicy.ReloadRevalidatingCacheData, null, (paywall, error) => {
// handle the result
});
}
```
---
# File: migration-to-unity-sdk-34
---
---
title: "迁移 Adapty Unity SDK 至 v3.4"
description: "迁移至 Adapty Unity SDK v3.4,获得更好的性能与全新的变现功能。"
---
Adapty SDK 3.4.0 是一个重要版本,引入了需要你进行迁移操作的改进内容。
## 更新备用付费墙文件 \{#update-fallback-paywall-files\}
更新您的备用付费墙文件,以确保与新 SDK 版本的兼容性:
1. 从 Adapty 看板[下载更新后的备用付费墙文件](fallback-paywalls)。
2. 将移动应用中的现有备用付费墙[替换为新文件](unity-use-fallback-paywalls)。
## 更新 Observer Mode 的实现方式 \{#update-implementation-of-observer-mode\}
如果你正在使用 Observer Mode,请确保更新其实现方式。
之前,向 Adapty 上报交易时使用的是不同的方法。在新版本中,Android 和 iOS 应均统一使用 `reportTransaction` 方法。该方法会明确地将每笔交易上报给 Adapty,确保其被正确识别。如果使用了付费墙,请传入 variation ID 以将交易与付费墙关联。
:::warning
**不要跳过交易上报!**
如果不调用 `reportTransaction`,Adapty 将无法识别该交易,它不会出现在分析数据中,也不会发送到集成渠道。
:::
```diff showLineNumbers
- #if UNITY_ANDROID && !UNITY_EDITOR
- Adapty.RestorePurchases((profile, error) => {
- // handle the error
- });
- #endif
Adapty.ReportTransaction(
"YOUR_TRANSACTION_ID",
"PAYWALL_VARIATION_ID", // optional
(error) => {
// handle the error
});
```
---
# File: migration-to-unity330
---
---
title: "迁移 Adapty Unity SDK 至 v3.3"
description: "迁移至 Adapty Unity SDK v3.3,获得更好的性能和全新的变现功能。"
---
Adapty SDK 3.3.0 是一个重要版本,带来了一些改进,但可能需要你执行一些迁移步骤。
1. 升级至 Adapty SDK v3.3.x。
2. 重命名了 Adapty SDK 中 Adapty 和 AdaptyUI 模块的多个类、属性和方法。
3. 从现在起,`SetLogLevel` 方法接受一个回调作为参数。
4. 从现在起,`PresentCodeRedemptionSheet` 方法接受一个回调作为参数。
5. 更改付费墙视图的创建方式。
6. 移除 `GetProductsIntroductoryOfferEligibility` 方法。
7. 将备用付费墙保存为独立文件(每个平台一个),放在 `Assets/StreamingAssets/` 目录下,并将文件名传递给 `SetFallbackPaywalls` 方法。
8. 更新购买流程。
9. 更新付费墙编辑工具事件的处理方式。
10. 更新付费墙编辑工具付费墙错误的处理方式。
11. 更新 Adjust、Amplitude、AppMetrica、Appsflyer、Branch、Firebase 和 Google Analytics、Mixpanel、OneSignal、Pushwoosh 的集成配置。
13. 更新观察者模式的实现方式。
14. 使用显式 `Activate` 调用更新 Unity 插件初始化。
## 将 Adapty Unity SDK 升级到 3.3.x \{#upgrade-adapty-unity-sdk-to-33x\}
在此版本之前,Adapty SDK 是确保 Adapty 在应用中正常运行所必需的核心 SDK,而 AdaptyUI SDK 则是可选 SDK,仅在使用 Adapty 付费墙编辑工具时才需要安装。
从 3.3.0 版本开始,AdaptyUI SDK 已被弃用,AdaptyUI 已作为模块合并到 Adapty SDK 中。由于此变更,您需要移除 AdaptyUI SDK 并重新安装 Adapty SDK。
1. 从项目中移除 **AdaptySDK** 和 **AdaptyUISDK** 的包依赖项。
2. 删除 **AdaptySDK** 和 **AdaptyUISDK** 文件夹。
3. 按照 [Unity 的 Adapty SDK 安装与配置](sdk-installation-unity) 页面的说明,重新导入 AdaptySDK 包。
## 重命名 \{#renamings\}
1. 在 Adapty 模块中重命名:
| 旧版本 | 新版本 |
| ------------------------- | ------------------------ |
| Adapty.sdkVersion | Adapty.SDKVersion |
| Adapty.LogLevel | AdaptyLogLevel |
| Adapty.Paywall | AdaptyPaywall |
| Adapty.PaywallFetchPolicy | AdaptyPaywallFetchPolicy |
| PaywallProduct | AdaptyPaywallProduct |
| Adapty.Profile | AdaptyProfile |
| Adapty.ProfileParameters | AdaptyProfileParameters |
| ProfileGender | AdaptyProfileGender |
| Error | AdaptyError |
2. 在 AdaptyUI 模块中重命名:
| 旧版本 | 新版本 |
| ------------------ | ------------------ |
| CreatePaywallView | CreateView |
| PresentPaywallView | PresentView |
| DismissPaywallView | DismissView |
| AdaptyUI.View | AdaptyUIView |
| AdaptyUI.Action | AdaptyUIUserAction |
## 更改 SetLogLevel 方法 \{#change-the-setloglevel-method\}
从现在起,`SetLogLevel` 方法接受回调作为参数。
```diff showLineNumbers
- Adapty.SetLogLevel(Adapty.LogLevel.Verbose);
+ Adapty.SetLogLevel(Adapty.LogLevel.Verbose, null); // or you can pass the callback to handle the possible error
```
## 更改 PresentCodeRedemptionSheet 方法 \{#change-the-presentcoderedemptionsheet-method\}
从现在起,`PresentCodeRedemptionSheet` 方法接受回调作为参数。
```diff showLineNumbers
- Adapty.PresentCodeRedemptionSheet();
+ Adapty.PresentCodeRedemptionSheet(null); // or you can pass the callback to handle the possible error
```
## 更改付费墙视图的创建方式 \{#change-how-the-paywall-view-is-created\}
完整代码示例请参阅[获取使用付费墙编辑工具设计的付费墙视图配置](unity-get-pb-paywalls#fetch-the-view-configuration-of-paywall-designed-using-paywall-builder)。
```diff showLineNumbers
+ var parameters = new AdaptyUICreateViewParameters()
+ .SetPreloadProducts(true);
- AdaptyUI.CreatePaywallView(
+ AdaptyUI.CreateView(
paywall,
- preloadProducts: true,
+ parameters,
(view, error) => {
// use the view
});
```
## 移除 GetProductsIntroductoryOfferEligibility 方法 \{#remove-the-getproductsintroductoryoffereligibility-method\}
在 Adapty iOS SDK 3.3.0 之前,无论用户是否符合资格,产品对象始终包含优惠信息。您必须在使用优惠之前手动检查资格。
现在,产品对象仅在用户符合资格时才包含优惠信息。这意味着您不再需要检查资格——如果存在优惠,则用户符合资格。
## 备用付费墙的传入方式更新 \{#update-method-for-providing-fallback-paywalls\}
在此版本之前,备用付费墙以序列化 JSON 的形式传入。从 v 3.3.0 开始,机制发生了变化:
1. 将备用付费墙保存到 `/Assets/StreamingAssets/` 目录下的文件中,Android 和 iOS 各一个文件。
2. 将文件名传入 `SetFallbackPaywalls` 方法。
你的代码需要做如下修改:
```diff showLineNumbers
using AdaptySDK;
void SetFallBackPaywalls() {
+ #if UNITY_IOS
+ var assetId = "adapty_fallback_ios.json";
+ #elif UNITY_ANDROID
+ var assetId = "adapty_fallback_android.json";
+ #else
+ var assetId = "";
+ #endif
- Adapty.SetFallbackPaywalls("FALLBACK_PAYWALLS_JSON_STRING", (error) => {
+ Adapty.SetFallbackPaywalls(assetId, (error) => {
// handle the error
});
}
```
完整代码示例请参阅 [在 Unity 中使用备用付费墙](unity-use-fallback-paywalls) 页面。
## 更新购买功能 \{#update-making-purchase\}
之前,取消的购买和待处理的购买被视为错误,分别返回 `PaymentCancelled` 和 `PendingPurchase` 错误码。
现在引入了新的 `AdaptyPurchaseResultType` 类,用于处理已取消、成功和待处理的购买。请按以下方式更新购买相关代码:
```diff showLineNumbers
using AdaptySDK;
void MakePurchase(AdaptyPaywallProduct product) {
- Adapty.MakePurchase(product, (profile, error) => {
- // handle successfull purchase
+ Adapty.MakePurchase(product, (result, error) => {
+ switch (result.Type) {
+ case AdaptyPurchaseResultType.Pending:
+ // handle pending purchase
+ break;
+ case AdaptyPurchaseResultType.UserCancelled:
+ // handle purchase cancellation
+ break;
+ case AdaptyPurchaseResultType.Success:
+ var profile = result.Profile;
+ // handle successful purchase
+ break;
+ default:
+ break;
}
});
}
```
查看[在移动应用中进行购买](unity-making-purchases)页面中的最终代码示例。
## 更新付费墙编辑工具事件处理方式 \{#update-handling-of-paywall-builder-events\}
取消和待处理的购买不再被视为错误,所有这些情况现在通过 `PaywallViewDidFinishPurchase` 方法处理。
1. 删除对取消购买事件的处理。
2. 按以下方式更新成功购买事件的处理:
```diff showLineNumbers
- public void OnFinishPurchase(
- AdaptyUI.View view,
- Adapty.PaywallProduct product,
- Adapty.Profile profile
- ) { }
+ public void PaywallViewDidFinishPurchase(
+ AdaptyUIView view,
+ AdaptyPaywallProduct product,
+ AdaptyPurchaseResult purchasedResult
+ ) { }
```
3. 更新操作处理方式:
```diff showLineNumbers
- public void OnPerformAction(
- AdaptyUI.View view,
- AdaptyUI.Action action
- ) {
+ public void PaywallViewDidPerformAction(
+ AdaptyUIView view,
+ AdaptyUIUserAction action
+ ) {
switch (action.Type) {
- case AdaptyUI.ActionType.Close:
+ case AdaptyUIUserActionType.Close:
view.Dismiss(null);
break;
- case AdaptyUI.ActionType.OpenUrl:
+ case AdaptyUIUserActionType.OpenUrl:
var urlString = action.Value;
if (urlString != null {
Application.OpenURL(urlString);
}
default:
// handle other events
break;
}
}
```
4. 更新已开始购买的处理方式:
```diff showLineNumbers
- public void OnSelectProduct(
- AdaptyUI.View view,
- Adapty.PaywallProduct product
- ) { }
+ public void PaywallViewDidSelectProduct(
+ AdaptyUIView view,
+ string productId
+ ) { }
```
5. 更新购买失败的处理方式:
```diff showLineNumbers
- public void OnFailPurchase(
- AdaptyUI.View view,
- Adapty.PaywallProduct product,
- Adapty.Error error
- ) { }
+ public void PaywallViewDidFailPurchase(
+ AdaptyUIView view,
+ AdaptyPaywallProduct product,
+ AdaptyError error
+ ) { }
```
6. 更新成功恢复购买事件的处理方式:
查看 [处理付费墙事件](unity-handling-events) 页面中的完整代码示例。
## 更新付费墙编辑工具付费墙错误的处理方式 \{#update-handling-of-paywall-builder-paywall-errors\}
错误处理方式也有所变更,请根据以下指引更新你的代码。
1. 更新产品加载错误的处理方式:
```diff showLineNumbers
- public void OnFailLoadingProducts(
- AdaptyUI.View view,
- Adapty.Error error
- ) { }
+ public void PaywallViewDidFailLoadingProducts(
+ AdaptyUIView view,
+ AdaptyError error
+ ) { }
```
2. 更新渲染错误的处理方式:
```diff showLineNumbers
- public void OnFailRendering(
- AdaptyUI.View view,
- Adapty.Error error
- ) { }
+ public void PaywallViewDidFailRendering(
+ AdaptyUIView view,
+ AdaptyError error
+ ) { }
```
## 更新第三方集成 SDK 配置 \{#update-third-party-integration-sdk-configuration\}
从 Adapty Unity SDK 3.3.0 开始,我们更新了 `updateAttribution` 方法的公共 API。之前,它接受 `[AnyHashable: Any]` 字典,允许您直接从各种服务传递归因对象。现在,它需要 `[String: any Sendable]`,因此您需要在传递之前转换归因对象。
为确保集成在 Adapty Unity SDK 3.3.0 及更高版本中正常运行,请按以下各节所述更新以下集成的 SDK 配置。
### Adjust
按照以下方式更新您的移动应用代码。完整代码示例请参阅 [Adjust 集成的 SDK 配置](adjust#connect-your-app-to-adjust)。
```diff showLineNumbers
- using static AdaptySDK.Adapty;
using AdaptySDK;
Adjust.GetAdid((adid) => {
- Adjust.GetAttribution((attribution) => {
- Dictionary