# seeg-sdk-v2-unity **Repository Path**: csseeg/seeg-sdk-v2-unity ## Basic Information - **Project Name**: seeg-sdk-v2-unity - **Description**: 指色 Seeg SDK v2 发行包(Unity / 团结引擎),v1 请使用 seeg-sdk-unity。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-10-21 - **Last Updated**: 2026-11-02 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Seeg SDK for Unity 版本约定:版本号变动允许包含 API 破坏性调整,不承诺次版本升级保持兼容。升级前请核对该版本的接口变更并迁移调用方;2.0.3 已删除旧的四个复访奖励接口,不提供同名兼容包装。 指色(Seeg)一体化 Unity SDK,封装登录、存档、变现(横幅 / 插屏 / 激励视频)、应用内购、排行榜、打点统计等常用能力,统一对接微信、抖音、快手、Bilibili、TikTok、支付宝、京东小游戏及 Android、iOS、WebGL 等平台。 > 包名:`com.seeg.sdk` | 当前版本:`2.0.6` | Unity 最低版本:`2021.3` ## 直玩加载、订阅与数据 游戏完成资源与场景加载、可以开始游玩时调用现有 `Seeg.TrackLoadComplete(new LoadCompleteEventParam { first = true, duration = 8 })`。保留统计与京东启动留存、TikTok `loading_complete` 上报,同时抖音上报 `sceneId=7001`、微信上报 `sceneId=7`;不等待账号登录、统计初始化或 `feedEnter`。加载就绪上报异常不会阻断原有统计。 直玩订阅与数据接口当前支持抖音。申请直玩能力并获得 `contentID` 后,在宿主登录完成的业务流程中调用;订阅请求须直接放在用户点击回调内,SDK 不异步等待登录。其他平台或宿主不具备能力时执行 `fail` 和 `complete`。支持的接口直接同步转发宿主,回调由平台触发,同步异常直接透传。业务只调用 Seeg 接口,SDK 内部固定订阅 `type="play"`。 ```csharp Seeg.CheckFeedSubscribeStatus(new CheckFeedSubscribeStatusParam { scene = 1, success = result => Debug.Log($"已订阅:{result.status}") }); // 在用户点击回调中调用;全场景订阅可只传 allScene = true。 Seeg.RequestFeedSubscribe(new RequestFeedSubscribeParam { scene = 1, contentIDs = new[] { "已申请的 contentID" }, success = result => Debug.Log($"用户同意:{result.success}"), fail = error => Debug.LogWarning(error.errMsg) }); // 公式演示:30 秒后就绪;实际 readyAt 应按业务条件计算。 Seeg.StoreFeedData(new StoreFeedDataParam { scene = 1, contentID = "已申请的 contentID", status = 1, @operator = ">=", rightValue = (DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() + 30000).ToString(), extra = "业务补充数据" }); Seeg.GetFeedData(new GetFeedDataParam { scene = 1, contentID = "已申请的 contentID", success = result => Debug.Log($"状态:{result.status},数据:{result.extra}") }); ``` 查询参数 `scene` 可选,`allScene` 默认 `false`;请求在非全场景时须提供 `scene` 和 `contentIDs`。查询结果为 `status: bool`,请求结果为 `success: bool`,用户拒绝仍进入成功回调并返回 `success=false`。 存储参数 `status` 为 `0`(未就绪)或 `1`(就绪),`leftValue` 默认 `timeStampMs`,`@operator` 支持 `=`、`>`、`>=`、`<`、`<=`、`!=`,`rightValue` 为字符串毫秒时间戳,`extra` 可选。读取结果为 `status: int` 与 `extra: string`,缺省 `extra` 为空字符串。 回调沿用 `success/fail/complete` 与 `ErrorInfo`,业务回调抛出的异常继续向上传递。C# 核心与 Unity 桥接须同步更新。 官方参考:[抖音直玩 C# API](https://developer.open-douyin.com/docs/resource/zh-CN/mini-game/develop/api/c-api/open-ability/direct-play)。 ## 小游戏启动文件 微信、抖音、快手、Bilibili 的构建后处理将配置与附加 SDK 初始化写入 `seeg-bootstrap.js`,`game.js` 仅保留固定加载语句。支付宝同样生成该文件, 但在 `my.loadUnity(options)` 前调用其导出函数,将配置写入 `options.customEnv.seeg.implCfg`, 保留已有的 `customEnv` 与 `seeg` 其他属性。分发时须保留启动文件。 重复处理会更新配置,不重复注入;通用小游戏升级后须重新导出,旧内联入口会报错。 支付宝原有带标记的配置区块会被替换为函数调用。构建前请保存或丢弃开发者工具中的 未保存编辑,并关闭入口编辑页;拆分文件不能防止 IDE 强制保存旧入口造成覆盖。 原生端与普通 WebGL 的配置方式不变。 启动文件回归测试(需要 .NET 10 与 Node.js,并已检出同级 `seeg-cs`): `dotnet run --project Tests~/Bootstrap.Tests/Bootstrap.Tests.csproj`。 独立工作树可通过 `-p:SeegJsonDir=/seeg_cs/Scripts/Json` 指定实际 JSON 源码目录。 ## SDK 更新与构建版本要求 编辑器启动时检查公共版本规则,每次编辑器会话只自动检查一次,脚本域重载会恢复有效缓存供面板展示。打开 `SeegSdk/设置面板`,底部版本信息只显示当前 SDK 版本和最新 SDK 版本,最底部并排显示「提交反馈」和「检查更新」,更新按钮在反馈按钮右侧。规则由 game-server 后台「基础配置 → SDK 版本」统一管理并发布到 CDN;更新及异常详情保留在控制台日志中,同一结果在同一编辑器会话内不重复提醒。升级说明见 [Unity 版本记录](https://docs.zaml2018.com/v2.0/version/unity.html)。 每次构建会主动刷新版本规则,请求和完整响应读取共用最多 5 秒等待。最低要求只使用当前 SDK 所属的 `主版本.次版本` 系列:低于最低版本会在构建预处理的最前面终止构建;等于最低版本允许构建。更高系列的最新版只提供升级提醒。 规则来自 `https://global.qwpo2018.com/mp/config/sdk-version-policy.json`,不需要登录或游戏密钥。有效规则缓存于工程的 `Library/SeegSdk/sdk-version-policy.json`;请求失败或远程规则无效时保留并使用有效缓存,无有效缓存时允许构建并告警。缓存写入失败不会取消本次有效规则的最低版本拦截。实际包版本无法识别时显示未知并告警,不使用默认版本冒充。完整操作与升级流程见 [SDK 更新与最低版本](https://docs.zaml2018.com/v2.0/settings/sdk-version.html)。 ## 引力停用与缓存清理 小游戏成功加载远程 `common` 配置后,若原先 `reportGE=true`,但 `common.geClientToken` 已缺失或为空,则将 `reportGE` 改为 `false`,停止引力上报,并按 `Gravity_EventIndexID` 与 `Gravity_EventAutoIncrementingID` 的索引范围删除 `gravity_event_<序号>` 缓存;事件删除成功后再清理这两个索引。清理只在 `reportGE` 从 `true` 转为 `false` 时执行一次。原先已关闭、远程仍启用或配置加载失败时不清理,也不会自动重新启用引力上报。 ## 特性 - **统一 API**:一套 `Seeg.*` 接口覆盖原生与小游戏平台,业务侧无需为每个渠道写分支代码。 - **多平台构建**:内置 WX / TT / KS / BL / TK / Ali / JD / WebGL / Android / iOS 构建处理,自动注入对应的 `SEEG_PF_*` 宏。 - **可视化配置面板**:`SeegSdk/设置面板` 菜单,按 GID 维护多套渠道配置,支持一键拉取最新平台资源。 - **变现能力**:横幅、插屏、激励视频统一接口,支持 SDK 内部插屏事件回调。 - **应用内购**:查询失败订单、拉起支付、消耗订单、恢复购买。 - **排行榜**:省份排行榜与个人排行榜,支持永久 / 周 / 日等多种刷新周期。 - **分享邀请**:小游戏消息卡片支持配置素材、房间参数和邀请人绑定。 - **打点统计**:内置数数(ThinkingData)、TalkingData、引力引擎(Gravity)、腾讯广告等渠道打点的可选集成。 - **关卡与引导打点**:开始、失败、通关、复活、道具使用、关键操作、退出、重玩、进度等关卡事件,以及多步骤新手引导事件。 - **存档**:按调用显式选择远程、本地或两端,支持 merge 差异保存、cover 整档覆盖与受控实时同步。 - **纯本地模式**:配置 `onlyLocal: true` 后跳过账号登录,通过所有游戏均具备的静态配置清单启动,存档固定保存在本地。 - **复访能力**:抖音、TikTok、快手、Bilibili 和支付宝小游戏按平台能力支持侧边栏、添加到桌面、启动来源识别及复访奖励状态。 支付宝核心 DLL 与桥接源码位于 `Runtime/Sdk/MG/MY/`,由 `SEEG_PF_MY` 控制导入。小游戏导出路径由用户在官方打包面板指定,Seeg 不修改官方的 `alipaygame` 目录。Android 渠道 `gp` 使用 `SEEG_PF_ANDROID`,与核心 DLL 的导入条件一致。 京东小游戏使用京东对接提供的 `JDSDK-20260920.unitypackage`(包内版本 1.1.8)。开启平台自动管理后从 Gitee 固定原包安装,使用 `SEEG_PF_JD` 宏;京东模板保留官方 `WXTemplate*` 名称,与微信(含 Bilibili 复用)同名模板按平台隔离;手动接入可参考[官方指南](https://mp-docs.jd.com/doc/minigame/gamdedev/gameguide/3034)。`JDMiniBridge` 直接调用该 SDK 的 `WX.InitSDK`、`WX.Login`、`WX.OnShow`、`WX.OnHide` 和启动参数接口。游戏主动调用 `Seeg.ReportJDTask` 上报关卡、得分任务;SDK 在冷启动时缓存任务参数并校验类型。广告、分享和发奖暂未接入。 游戏完成资源加载、进入核心玩法(例如新手引导或大厅)时主动调用: ```csharp // 完成加载并进入新手引导或大厅后调用,不要仅因 SDK 初始化成功就提前上报。 Seeg.TrackLoadComplete(new LoadCompleteEventParam { duration = loadDuration, first = isFirstLoad }); ``` **京东平台调用 `Seeg.TrackLoadComplete(...)`,就会同时调用平台 SDK 的 `WX.ReportGameStart()`,业务无需再单独调用平台方法。** 原有加载完成统计保持不变。`first` 仅作为统计参数,`false` 也会上报;SDK 不在初始化、登录或关卡事件中自动触发,也不额外去重。业务应在每次启动完成加载、首次进入核心玩法时调用。 ## 安装 通过 Unity Package Manager 以 Git URL 方式引入: ``` https://gitee.com/csseeg/seeg-sdk-v2-unity.git ``` 或在工程 `Packages/manifest.json` 中添加: ```json { "dependencies": { "com.seeg.sdk": "https://gitee.com/csseeg/seeg-sdk-v2-unity.git" } } ``` 如需锁定到指定版本,可在 URL 后追加 `#`,例如 `https://gitee.com/csseeg/seeg-sdk-v2-unity.git#2.0.3`。 2.0 内置轻量 JSON 实现,不再安装或依赖 `com.unity.nuget.newtonsoft-json`。 ## 目录结构 ``` Editor/ 编辑器扩展 ├─ SeegEditor.cs 设置面板(菜单:SeegSdk/设置面板) ├─ Process/ 各平台构建预/后处理 │ ├─ SeegBuild.cs 通用构建钩子 │ ├─ SeegWXBuild.cs ├─ SeegTTBuild.cs ├─ SeegKSBuild.cs │ ├─ SeegBiliBuild.cs ├─ SeegAndroidBuild.cs │ ├─ SeegIOSBuild.cs └─ SeegWebGLBuild.cs └─ Res/ 各打点 SDK 的 JS 资源(dn/ge/td) Runtime/ ├─ Sdk/ │ ├─ Android/ iOS/ WebGL/ Standalone/ 分平台核心 dll │ ├─ MG/<平台>/ 小游戏平台桥接与核心 dll │ └─ Standalone/SeegEnvInit.cs Editor 模拟环境初始化 └─ Plugins/ WebGL 通用插件 Samples~/SeegTest.cs 全功能演示场景脚本 ``` ## 配置面板 打开 Unity 菜单 `SeegSdk/设置面板`,按以下步骤建立或切换一套渠道配置: 1. 在「选择」下拉选择 `新增`,填写后台分配的 **gameId**;平台由后台的 `platform` 字段返回,与 gameId 相互独立。 - 小游戏平台码:`wx`、`tt`、`ks`、`bl`、`my`、`tk`、`jd` - 原生平台码:`gp`(Android)、`iOS` - 旧配置中的 `bili`、`ali`、`htt` 会在读取时分别迁移为 `bl`、`my`、`tk`。 2. 填写配置版本、日志级别(0 关闭、5 全开);需要纯本地运行时可勾选「纯本地模式」。手动值与后台 SDK 参数中的 `onlyLocal` 取 OR,任一为 `true` 即生效。2.0.x 存档目标仍由每次 API 调用的 `target` 决定。 3. 按平台类型填写相应字段: - 小游戏:`appId`、`geClientToken`(引力引擎,可选)、`tdAppKey`(TalkingData,可选)、数数打点开关。 - 微信:外部跳微开关、腾讯广告数据源 ID 与密钥(可选)。 - 抖音:仅支持新版包体格式。 - 原生:应用名、包名、版本名、版本号;iOS 可选执行 `pod install`。 4. 点击「保存」写入 `Assets/Seeg/Editor/Cfg/sdk_config.json`,并自动同步对应 `SEEG_PF_*` 脚本宏。 5. 点击「拉取SDK参数」会更新当前游戏参数。小游戏参数直接保存到 `sdk_config.json`; 原生端附加的 `seeg_sdk_param.json` 按游戏保存到 `Assets/Seeg/Editor/Cfg/`, `.gradle` 文件保存到 `Assets/Plugins/Android`。 旧版为小游戏生成的 `Cfg//cn`、`global` 不参与 Unity 构建或运行,可以直接删除; 新版再次拉取参数或从面板删除游戏配置时会自动清理。 切换平台 GID 时若与当前 Unity 平台不匹配,面板会提示并提供「切换平台」按钮。 ## 快速开始 最小可运行示例(完整可参考 `Samples~/SeegTest.cs`): ```csharp using System.Collections.Generic; using UnityEngine; using ZhiSe; public class Bootstrap : MonoBehaviour { void Start() { // 1. 尽早初始化 SDK;尽量把后续逻辑放到 success 回调内,避免触发隐私协议前的访问 Seeg.InitSdk(new SdkInitParam { success = () => { #if UNITY_ANDROID || UNITY_IOS // 原生平台:初始化完成后可立即初始化广告 Seeg.InitBannerAd(); Seeg.InitInterstitialAd(); Seeg.InitRewardedVideoAd(); #endif // 拉取登录态 Seeg.GetLoginData(new GetLoginDataParam { success = ret => Debug.Log($"登录成功: {JsonUtility.ToJson(ret)}") }); } }); // 2. 注册 SDK 事件回调 Seeg.SetSdkEvent(new SdkEventParam { appReview = callback => callback?.Invoke(5), appUpdate = callback => callback?.Invoke(new ModalParam { title = "更新", content = "有新版本", confirmText = "立即更新" }), sdkInterstitial = status => Debug.Log($"SDK 内部插屏: {status}") }); } } ``` 小游戏平台登录收到 `2011 / platform_code2session_timeout` 时,SDK 会重新获取平台 code 并自动 重试一次;`2010` 等其他错误不会重试。失败回调中的 `ErrorInfo.errMsg` 只包含服务端脱敏消息, 例如 `platform_code_invalid(code=40029)`,可通过 `ErrorInfo.traceId` 关联服务端日志。 `confirmText` 和 `cancelText` 分别用于设置确认、取消按钮文案;两个字段均可不传,未传或为空时桥接层不补默认文案,由平台决定默认行为。`ShowModalParam.showCancel` 控制是否显示取消按钮,默认值为 `true`。 > 2.0 破坏性变更:`submitText` 已从公共模型和原生协议删除且不提供兼容层,必须同步升级 seeg-cs、Android 与 iOS SDK。 微信、抖音、快手、Bilibili、TikTok 与支付宝的非广告能力由对应 C# SDK 适配;广告统一经 `BridgeAds_` 调用 `Runtime/Plugins/Seeg2JS.jslib`,直接使用平台 JS API。支付宝可由平台管理器下载官方 `ALIPAY-SDK` 1.16.26091715(提供 `AlipaySDKRuntime` 程序集);未启用自动处理时需手动导入。 ### 剪贴板 ```csharp Seeg.SetClipboardData(new SetClipboardDataParam { data = "邀请码", success = () => Debug.Log("复制成功"), fail = error => Debug.LogError(error) }); Seeg.GetClipboardData(new GetClipboardDataParam { success = result => Debug.Log($"剪贴板内容:{result.data}"), fail = error => Debug.LogError(error) }); ``` 所有平台通过 `seeg-cs` 的统一 `IBridge` 契约提供该接口。Android / iOS 的 `NativeBridge_` 与 Editor 的 `StandaloneBridge_` 保留在 `seeg-cs`,使用 Unity 系统剪贴板;微信、抖音、快手、Bilibili、 TikTok、支付宝小游戏由本仓库的对应桥接调用平台 SDK。 宿主事件上报统一由内部 `IBridge.ReportEvent` 接收 JSON 对象字符串,再适配各平台官方 C# SDK: | 平台 | 官方接口与当前适配 | | --- | --- | | 微信 | `WX.ReportEvent`,通过 `WX.CanIUse("ReportEvent")` 检查;官方接口要求字符串字典,非字符串字段转为 JSON 文本。 | | 抖音 | `TT.ReportAnalytics`,通过 `CanIUse.ReportAnalytics` 检查;保留字段的数值、字符串和布尔类型,事件及字段须先在平台后台配置。 | | TikTok | `TT.ReportEvent`,通过 `CanIUse.ReportEvent` 检查;参数转换为官方 `JsonData`。 | | 支付宝 | `AP.ReportCustomEvent`,参数转换为官方 `JsonData`;要求客户端 10.5.70+、基础库 2.1.15+。 | | 快手 | 当前固定的 Unity SDK 1.0.11 虽有 `KS.ReportEvent`,底层仅输出不支持日志,暂不接入。 | | Bilibili | 当前官方包未公开通用事件上报,适配层可能提供空函数,暂不复用微信接口。 | | 京东 | 官方 `WX.ReportEvent` 额外要求业务 `type`,缺少类型定义时不猜测默认值,暂不映射通用事件。 | TikTok 的 `loading_complete`、`complete_section`、`exit_game` 仍仅在 TikTok 触发,通过上述桥接调用官方 C# SDK,不再经过 Seeg 自有的 JS 事件转发。该内部桥接不改变公开 `Seeg.ReportEvent` 原有的统计分发;实际可上报的事件与字段仍以各平台配置和接口约束为准。 WebGL 的剪贴板读写实现在本仓库的 `Runtime/Plugins/Seeg2JS.jslib` 中,直接调用浏览器 Clipboard API。 `seeg-cs` 的 `StandaloneBridge_` 通过 `DllImport` 转发,由 `SeegSdkUnityMono` 接收异步结果。 请先初始化 SDK,在 HTTPS 页面中由点击等用户操作触发读写;不支持该 API 或权限被拒绝时, 会触发 `fail` 和 `complete`。`data` 可传空字符串,不可传 `null`。 `seeg-cs` 与 `seeg-unity` 始终同步发布,各平台 DLL 由构建和发行流程生成。源码提交和 MR 不包含 `Runtime/Sdk` 下生成的 DLL;没有实际源码、配置或文档改动时,不创建 `seeg-unity` MR。 ### 分享(小游戏) ```csharp Seeg.ShareAppMessage(new ShareAppMessageParam { title = "一起来玩", imageUrl = "https://example.com/share.png", // 微信可传 imageUrlId,抖音可传 templateId。 roomId = "room-1001", success = () => Debug.Log("分享成功"), fail = error => Debug.LogError(error), complete = () => Debug.Log("分享结束") }); ``` 调用参数优先于 SDK 分享配置,缺少标题或图片时会从配置数组随机补齐;配对的标题与平台首选图片使用同一下标。SDK 会自动追加当前用户的 `inviter`,传入 `roomId` 时同时追加房间参数,两个参数值都会进行 URL 编码。 微信默认在游戏返回前台时按 `judgeTime`(默认 2 秒)判断分享结果;设置为 `0` 时不等待返回前台,成功拉起分享后即完成回调。右上角菜单分享会在 SDK 初始化时根据分享配置自动注册。 ### 字体(小游戏) 业务需要动态字体时,应把字体文件地址传给 `Seeg.GetFont`: ```csharp Seeg.GetFont("https://example.com/fonts/game.ttf", font => { title.font = font; }); ``` 微信和快手小游戏会把 `url` 原样交给平台字体加载接口;使用系统字体或 Unity 内置字体的平台 仍保持原有行为。 > 2.0 破坏性变更:`GetFont(Action)` 已删除且不提供兼容重载,必须改为传入字体地址; > 核心 DLL 与平台桥接源码需要同步升级。 ### 变现 ```csharp Seeg.ShowBannerAd(); Seeg.HideBannerAd(); Seeg.ShowInterstitialAd(new InterstitialAdShowParam { positionTag = "main" }); Seeg.ShowRewardedVideoAd(new RewardedAdShowParam { positionTag = "revive", success = res => Debug.Log($"激励完成 次数={res.count}"), fail = err => Debug.Log($"激励失败 {err}") }); ``` > 小游戏需在 `GetGameConfig` 成功后再调用 `InitBannerAd/InitInterstitialAd/InitRewardedVideoAd`,并确保后台已配置广告位 ID。 > 小游戏内部桥接统一使用 `JSCreateAd`、`JSLoadAd`、`JSShowAd`、`JSHideAd`、`JSDestroyAd` 和 `JSSetAdStyle`。创建参数中的 `type`(1 横幅、2 插屏、3 激励)用于选择平台 API 和生命周期规则,后续按 UUID 操作;隐藏和样式设置仅作用于横幅。业务层仍使用各广告类型的接口。加载或展示时实例不存在或已销毁,会携带原 UUID 和请求号返回失败,不静默丢弃请求。 > 广告统一由 seeg-cs 的 `BridgeAds_` 创建,`IBridge` 和各 MiniBridge 不再声明或实现广告。Android 保留 JNI,iOS 保留原生 UUID 桥接;小游戏共用本包的 `Seeg2JS.jslib`,无需依赖 seeg-js。 > 横幅支持微信、快手、Bilibili、支付宝小游戏,抖音和 TikTok 不提供横幅,京东广告仍未接入。Editor 保留模拟视频广告,普通 WebGL 不提供广告。 > `AdManager_` 负责预加载、并发加载合并和已加载结果复用,实际加载延后到下一次 Unity 调度。`OnLoad` 是对象事件,有 Promise 的平台须等待本次 `load()` 结果;无独立 load 的平台按创建或展示语义适配,不伪造 `OnLoad`。 > 加载与展示互斥,播放期间的错误仍会触发本次展示的 `fail` / `complete`,正常关闭才发奖。小游戏回调通过 UUID 和请求号关联对象及本次操作,销毁后忽略迟到回调。 > 抖音插屏、TikTok 插屏和激励广告只能展示一次,SDK 内部自动管理平台实例:抖音插屏关闭后由平台销毁,SDK 仅解绑并丢弃旧实例;TikTok 由 SDK 释放旧实例。展示失败且没有关闭事件时,在下次加载前清理。新实例在下次加载时创建,与旧实例释放至少间隔 300ms,对外广告对象和 UUID 保持不变。业务无需每轮调用 `Destroy()`;显式销毁表示彻底停用广告对象,并取消等待中的重建。 > 小游戏桥接是 SDK 内部接口。安全区域六个坐标及尺寸字段使用 `double` 保留小数;微信、Bilibili、快手和支付宝按官方结果映射。微信、快手和支付宝构建直接调用 `IBridge.DownloadFile(param)`;其它平台由核心宏选择通用下载,不通过桥接返回值判断能力。`FileSystemManager` 已统一包含 `UnlinkSync`,本包需与同步更新后的 seeg-cs 核心 DLL 配套使用。 ### 支付宝激励下单奖励 激励下单与礼包是两个独立流程。后台“复制回调地址”提供礼包 SPI 和下单完成通知两个地址;下单地址填在流量主广告位完成通知配置中,游戏平台参数填写回调管理中的 Base64 TOKEN。后台 SDK 配置需填写并发布该游戏的 `ad.rewardedVideoIds`,服务端只接收其中广告位的完成通知,未配置返回 1005。不同游戏应使用不同广告位。 登录成功、回到前台或用户手动刷新时调用 `Seeg.GetAlipayAdRewards`。游戏按 `bizId` 幂等发放道具并持久化后,传 `bizIds = new[] { bizId }` 调用 `Seeg.ConfirmAlipayAdReward`;单笔也传数组,确认结果从 `list` 逐项读取。同一游戏与玩家的订单重复确认成功。`rewardNumber` 保留平台字符串,可能包含小数。SDK 不自动发奖或确认。 ```csharp Seeg.GetAlipayAdRewards(new GetAlipayAdRewardsParam { success = list => { // 按 bizId 去重,按游戏规则发奖并保存。 // 发奖保存成功后: // Seeg.ConfirmAlipayAdReward(new ConfirmAlipayAdRewardParam { bizIds = new[] { reward.bizId } }); }, fail = error => Debug.LogWarning(error.errMsg) }); ``` 这两个接口是 Seeg 服务端的奖励查询与领取确认接口,仅支持支付宝,需部署配套服务端。确认只记录领取状态,不执行道具发放。支付宝官方提供的是[下单完成通知](https://opendocs.alipay.com/admedia/0i5c5r?pathHash=fd402c48),游戏自行发放道具;激励视频关闭回调仅表示观看结果,不能作为下单完成的依据。 Unity 的支付宝激励广告创建时固定开启 `multiton: true`,基础库需 `my.env.version >= 2.0.5`;不同广告位创建各自实例,同一广告位复用。初始化接口无需媒体透传参数。 ### 存档 存档接口统一使用 `ZhiSe.Json.SeegJsonObject`。读取目标使用 `GetArchiveTarget.Remote` (默认)或 `Local`,比较两端时分别读取两次;写入目标使用 `SetArchiveTarget.Remote`、 `Local` 或 `Both`。远程请求失败会进入 `fail`,不会用空对象冒充远程空档。 参数类型仍为 `GetArchiveDataParam` / `SetArchiveDataParam`;成功回调和 `data` 已统一为 `SeegJsonObject`。旧 Dictionary 回调、便捷重载及 `local` / `overLocal` 字段均已移除。 `type` 只接受 `merge` 或 `cover`;其它值会进入 `fail`,且本次不写入任何一端。 ```csharp using ZhiSe.Json; // 差异上报(默认每分钟批量上报一次) Seeg.SetArchiveData(new SetArchiveDataParam { target = SetArchiveTarget.Both, data = new SeegJsonObject { ["coin"] = 100, ["level"] = new SeegJsonObject { ["progress"] = 0.5 } }, success = () => Debug.Log("存档成功") }); // 关键数据请求实时上报;超出 sync 配额时自动按普通批量存档处理,不会报错 Seeg.SetArchiveData(new SetArchiveDataParam { sync = true, data = new SeegJsonObject { ["purchase_id"] = "p_001" } }); // 远程和本地分别读取;判优后只用 cover 覆盖较弱的一端,后续增量存档再写 Both Seeg.GetArchiveData(new GetArchiveDataParam { target = GetArchiveTarget.Local, success = local => Seeg.GetArchiveData(new GetArchiveDataParam { target = GetArchiveTarget.Remote, success = remote => Debug.Log($"远程金币: {remote.Get(\"coin\")},本地档: {local}") }) }); ``` `sync` 配额从本会话第一次接受的实时请求开始计算:首分钟最多 3 次、前 5 分钟累计最多 10 次,之后采用滚动 60 秒间隔。只写本地时 `sync` 不生效,也不消耗配额。 当配置面板手动勾选、后台 SDK 参数或宿主初始化参数中的任一 `onlyLocal` 为 `true` 时, SDK 不调用账号登录接口,而是从 `/mp/config/manifest/{gameId}/{configVersion}.json` 获取静态配置清单;测试环境使用 `/test/mp/config/manifest/{gameId}/{configVersion}.json`。该静态清单所有游戏均具备。请求成功后按当前游戏和环境保存最近一次有效清单; 后续请求失败或响应无效时使用该缓存。`GetLoginData` 返回本地缓存的用户字段与当前有效配置字段, 无缓存时用户字段使用匿名默认值。 普通模式显式传入 `local = true` 时也使用相同的本地登录逻辑,但不覆盖当前在线运行态。 登录缓存仅来自当前游戏应用的独立设备存储;此模式只读该缓存,不覆盖缓存,也不上报登录或注册事件。 此模式下读取和写入存档均强制使用本地存储,调用方传入的 `target`、`sync` 与 `oldArchive` 不会触发远程存档请求。 ### 动态 JSON 需要直接解析动态 JSON 时,可使用 SDK 公开的 `ZhiSe.Json`: ```csharp using ZhiSe.Json; var data = SeegJsonObject.Parse("{\"level\":3,\"items\":[\"coin\",\"key\"]}"); var level = data.Get("level"); var items = data.Get("items"); ``` 存档、动态配置与协议对象均可直接使用 `SeegJsonObject`,无需依赖 Newtonsoft.Json。 ### 应用内购 ```csharp Seeg.Pay(new SeegPayParam { productId = "gem_60", success = ret => Seeg.ConsumeOrder(new SeegConsumeParam { orderId = ret.orderId }), fail = ret => Debug.LogError($"支付失败 {ret.errCode}/{ret.errMsg}") }); // 启动时建议查询一次失败订单并尝试恢复 Seeg.QueryFailOrder(new SeegQueryOrderParam { success = list => { /* ... */ } }); Seeg.RestoreOrder (new SeegQueryOrderParam { success = list => { /* ... */ } }); ``` ### 排行榜 ```csharp using ZhiSe.Json; // 先取省份城市(current=当前实时,first=首次快照),再上报 / 拉取 Seeg.GetGeoData(new GetGeoDataParam { success = geo => Debug.Log($"{geo.current.province} {geo.current.city}") }); // 省份榜 Seeg.SetProvinceRankData(new SetProvinceRankDataParam { type = "season1", num = 1, timeType = TimeType.All }); Seeg.GetProvinceRankData(new GetProvinceRankDataParam { type = "season1", timeType = TimeType.All, success = list => { /* 需自行补齐缺失省份,否则平台审核易被打回 */ } }); // 个人榜;extra 为公开展示用的自定义数据(最多 32 个字段、单个 key 最长 64 字节,序列化后最多 4KB) Seeg.SetPersonRankData(new SetPersonRankDataParam { type = "weekly", num = 1234, timeType = TimeType.Week, extra = new SeegJsonObject { ["tier"] = "diamond", ["weapon"] = "ak47" } }); Seeg.GetPersonRankData(new GetPersonRankDataParam { type = "weekly", timeType = TimeType.Week, withRank = true, success = result => { /* result.entries 为榜单,result.self 为自己的排名 */ } }); ``` > 2.0 破坏性变更:`GetPersonRankData` 的 `success` 参数已从 `List` 调整为 `PersonRankListResult`。旧代码需将列表访问改为 `result.entries`;需要自己的实时排名时传入 `withRank = true` 并读取 `result.self`。 ### 打点 ```csharp // 通用事件 Seeg.SetSuperProperties(new Dictionary { { "hp", 1 } }); Seeg.ReportEvent("custom_event", new Dictionary { { "key", "val" } }); Seeg.ReportUserInfo(UserInfoType.SET, new Dictionary { { "max_level", 12 } }); // 业务已捕获但仍需关注的错误(小游戏需开启 reportSa) Seeg.ReportBug("订单状态异常", new Dictionary { { "orderId", "1001" }, { "scene", "pay" } }); // 引导(首步 first=true,末步 last=true) Seeg.TrackGuideStart(new GuideStartEventParam { id = 1, first = true }); Seeg.TrackGuideEnd (new GuideEndEventParam { id = 3, last = true }); // 关卡 Seeg.TrackLevelStart (new LevelStartEventParam { level = 10 }); Seeg.TrackLevelPass (); Seeg.TrackLevelLose (); Seeg.TrackLevelRevive (); Seeg.TrackLevelPropUse (new LevelPropUseEventParam { prop = "hammer" }); Seeg.TrackLevelOperate (new LevelOperateEventParam { operate = "tap_combo" }); Seeg.TrackLevelQuit (new LevelQuitEventParam { quitType = "home_btn" }); Seeg.TrackLevelReplay (new LevelReplayEventParam { replayType = "fail_panel" }); Seeg.TrackLevelProgress(new LevelProgressEventParam{ progress = 75 }); ``` `ReportBug` 复用自动异常上报的会话内去重与限流;非小游戏构建保留同名接口,但当前不走 此 SA 上报通道。 ### 冷启动与热启动参数 ```csharp var enterOptions = Seeg.GetEnterOptionsSync(); Debug.Log($"本次进入场景:{enterOptions.scene}"); ``` `GetEnterOptionsSync` 返回最近一次冷启动或热启动的进入参数,平台桥接会把首次进入参数与最近进入参数分开保存。微信小游戏直接适配 `wx.getEnterOptionsSync`(基础库 2.13.2 起支持);低版本不可用时自动回退到 `OnShow` 回调参数或冷启动参数。抖音、快手、Bilibili、TikTok 和支付宝桥接通过各自同步接口或最近一次 `OnShow` 参数保持同一语义。 各平台会把侧边栏和桌面来源归一化到 `LaunchOptions.launchFrom` / `location`,复访状态由核心层直接读取进入参数,不再通过独立的来源判断桥接方法。 ### 侧边栏与桌面复访 2.0.3 移除旧的侧边栏与桌面异步奖励查询、分入口领取标记接口,以及对应的异步参数类型。 入口操作(检查、跳转和添加桌面)仍可使用,但不代表业务奖励已发放。 所有平台统一使用下述两个新接口;历史同步查询与通用领取标记接口仍保留,新业务不再使用。 ### 其他平台的统一复访任务 其他平台也使用这两个 API,由 SDK 实现资格判断与领取记录: | 任务 | 返回的 rewardScene | 资格及次数 | | --- | --- | --- | | 首次加桌 | `ADD_TO_DESKTOP` | 当前进程已收到加桌成功回调,永久领取一次 | | 侧边栏复访 | `REVISIT_EDUCATION` | 最近一次进入参数被识别为侧边栏,每个自然日一次 | | 桌面复访 | `ADD_TO_DESKTOP` | 最近一次进入参数被识别为桌面,每个自然日一次 | 首次加桌优先,其次侧边栏,最后桌面复访;一次只返回一个任务,上报完成后可再次查询下一项。 沿用 SDK 已有的平台入口识别和基础档记录;没有有效入口、没有首次加桌成功或奖励已经领取时, 查询成功返回 `canReceiveReward=false` 和空 `rewardScene`,不会把普通启动当成复访奖励。 查询本身不消耗资格。发奖失败时不调用完成接口,之后可以重新查询并重试业务发奖。 完成接口仅记录上次查询锁定的任务,不发放业务奖励,也不弹平台到账提示。 未查到可领取任务就调用完成接口会失败;重复上报不会再次写领取记录。 SDK 保留待确认任务,重复查询不会被另一入口覆盖。每日任务跨日后,查询或完成上报会失败并清除旧资格, 不会扣减新一天的次数,业务随后重新查询。重新初始化 SDK 也会清除待确认任务和本进程加桌信号。 业务应串行执行“查询 → 幂等发奖 → 完成上报”,不要在发奖处理中并发查询或重新初始化; 新一轮前台刷新可以等本轮结束后执行。客户端记录用于常规领取控制,不代替业务端的稳定业务键去重。 SDK 本地任务额外返回 `rewardId`:首次加桌固定为 `shortcut:first_add`,每日任务由入口和当天起始时间组成。 业务可用“账号 ID + rewardId”作为幂等键,区分首次加桌与当日桌面复访;无资格时为空。 TikTok 官方结果不含任务 ID,`rewardId` 不提供值,仍按平台业务规则设计幂等键。 ### TikTok 新复访奖励(46.0.0+) 新流程使用 `Seeg.GetRevisitMissionReward` 和 `Seeg.ReportMissionRewardGranted`, 宿主能力声明在 `seeg-cs` 的 `IBridge`,由 `seeg-unity` 的 `TKMiniBridge` 直接调用 官方 `TT.GetRevisitMissionReward` 和 `TT.ReportMissionRewardGranted` C# 接口。 须使用支持这两个接口的最新 TikTok Unity 插件;宿主版本须为 46.0.0+,分别通过对应的 `CanIUse` 属性检查能力,不可用时返回失败。 TikTok 只要求官方 `TT.InitSDK` 成功,不等待 Seeg 账号登录或基础档加载;桥接检查平台初始化状态及 API 能力。 其他平台的 SDK 自行判定流程仍须基础档就绪,以读取并保存领取记录。 通常在 `Seeg.InitSdk` 成功后查询一次,之后每次回到前台重新查询(Unity 可在 SDK 已就绪时通过 `OnApplicationFocus(true)` 触发)。TikTok 桥接分别检查两个平台能力,其他平台按下述 SDK 规则实现。 查询结果包含 `canReceiveReward`、`rewardScene`、`scene`,不叠加本地每日领取限制。 `rewardScene` 支持 `REVISIT_EDUCATION`(侧边栏)和 `ADD_TO_DESKTOP`(桌面)。 ```csharp Seeg.GetRevisitMissionReward(new GetRevisitMissionRewardParam { success = async result => { if (!result.canReceiveReward) return; try { // 业务实现:校验场景,用稳定业务键幂等发奖。 // 返回 true 表示“本次已发放”或“此前已发放”。 // 两个业务方法均须结合账号 ID:本地任务按 rewardId 去重, // TikTok 按其任务周期和奖励场景制定稳定业务键。 var granted = string.IsNullOrEmpty(result.rewardId) ? await GrantTikTokRewardIdempotently(result.rewardScene) : await GrantLocalRewardIdempotently(result.rewardId, result.rewardScene); if (granted) Seeg.ReportMissionRewardGranted(new ReportMissionRewardGrantedParam { fail = error => Debug.LogWarning(error.errMsg) }); } catch (Exception error) { Debug.LogException(error); } }, fail = error => Debug.LogWarning(error.errMsg) }); ``` 仅在 `canReceiveReward == true` 时发奖,失败或结果不明确时不要通知。 业务必须使用稳定业务键防止重复发奖;通知接口不负责发奖,不接收业务参数。 通知使用官方 Unity API,`success`、`fail`、`complete` 分别由官方对应回调触发;`success` 表示平台通知成功,不代表业务发奖,`complete` 仅表示调用结束,不能当作成功信号。 平台奖励展示需事先由服务端通过 TikTok OpenAPI 分场景配置并启用。 2.0.3 不再提供旧的四个入口奖励接口,请迁移到上述流程,不要套用旧的本地每日领取限制。 参考:[TikTok 小游戏复访奖励接入指南](https://bytedance.larkoffice.com/wiki/HXzKwjozJiEtEekFdClcV7ZUn7f)。 小游戏生命周期在核心层统一通过 `SEEG_MG` 调用 `IBridge.OnShow` / `OffShow` / `OnHide` / `OffHide`,不再枚举具体平台;平台适配器会等待平台 `InitSDK` 回调后再订阅生命周期,TikTok 要求初始化回调码为 0,失败码会返回核心层;其他平台保留原初始化约定,平台 API 抛出异常仍会返回失败。抖音由构建脚本缓存 Unity 启动前的进入事件,桥接初始化后补发冷启动参数,热启动时继续刷新进入参数及侧边栏和桌面启动来源。 ## 构建说明 - 切换至与 GID 匹配的目标平台后再执行构建;面板会按 GID 平台把 `SEEG_PF_*` 宏写入对应构建组,不依赖 Build Settings 窗口的临时选中状态。 - 需要构建普通网页版本时,可在面板勾选 **构建 Web**(写入 `SEEG_PF_WEB`);关闭后恢复当前配置对应的渠道宏。 - Bilibili 使用官方新版“微信插件导出 + B 站 CLI 转换”方案:固定微信 Git 依赖与 `BilibiliMiniGameSdk` 补充原包共同安装,仅启用 `SEEG_PF_BL`。旧 SDK 和模板先备份隔离。转换工具由用户执行 `pnpm add -g bili-sgame-cli@2.1.22` 安装;微信完整导出后检测本机 CLI,版本至少 `2.1.13` 时自动转换为 `biligame`,未安装或不满足要求则提示并跳过,保留微信产物;AppId 取面板配置,游戏版本取 Unity `PlayerSettings.bundleVersion`。B 站客户端需 8.93 及以上。 - 勾选 **自动处理平台SDK** 后,保存配置会先准备对应平台依赖,成功后再更新 `SEEG_PF_*` 宏。微信、快手使用官方 Git 固定提交;Bilibili、TikTok、支付宝、京东使用独立 Gitee 资源仓库中的官方原包并以 SHA-256 锁定文件;官方来源保留在清单中。抖音可接管已有 `ByteGame`,自动下载尚需提供 TTSDK 本体。七个平台统一由 `Editor/SeegPlatformSdks.json` 管理,配置随 Seeg SDK 发行。 - `SeegSdk/手动同步一次平台SDK` 重试最近保存的平台;`更新当前平台SDK` 按配置中的固定版本重新安装(不会追踪上游 latest);`编辑平台SDK来源` 将默认配置复制到游戏工程的 `ProjectSettings/SeegPlatformSdks.json`,可把下载地址换为 Gitee Releases。 - 首次接管旧微信模板时,会核对实际已安装 Git 包的来源、锁文件及模板正文;旧提交可用于确认归属,切换时保留模板和 `.meta`,安装与构建仍要求清单中的固定提交。无法确认归属时保留原文件并停止处理。 - 详细来源、目录、更新与镜像步骤见 [平台 SDK 管理](Documentation~/平台SDK管理.md)。 - TikTok 使用官方 `1.1.6-Release` Unity 插件,登录及主动分享已适配其公开接口,剪贴板使用公开的 `TTClipboardImpl` 服务。该版未公开弹窗、分享菜单及菜单监听接口:弹窗调用 `fail/complete`,菜单相关方法给出提示;请使用游戏内 UI 和主动分享。主动分享支持 `title/imageUrl/query`,暂不映射其他平台的 `templateId`。国内抖音 ByteGame SDK(包括 `TTSDK_MIX_ENGINE` 模式)不能替代 TikTok SDK。 - 小游戏构建会把 `sdkParams` 平铺到 `GameGlobal.seeg.implCfg`,不会保留嵌套的 `sdkParams` 层,也不会把仅供编辑器拉取配置使用的 `gameSecret` 写入包体;`onlyLocal` 使用面板手动值与后台值的 OR 结果。 - 微信、抖音、快手、Bilibili、TikTok 和支付宝核心程序集分别通过对应 `JS*EnvInit` 入口读取随包配置。 - 支付宝请在官方打包面板执行“生成并转换”;Seeg 订阅转换完成事件,将当前配置写入最终 `alipaygame/game.js` 的 `my.loadUnity` 参数 `customEnv.seeg.implCfg`,随 Unity 运行环境加载。自动化构建调用 `ZhiSe.Editor.SeegAliBuild.BuildAndConvert()`,同步完成官方构建、转换及配置注入;仅调用官方核心转换 API 不会触发面板事件。重复处理会更新原 Seeg 配置区块;最终产物缺失或启动模板不匹配时明确报错。 - 各小游戏桥接程序集由构建管线显式保留,`RuntimeInitializeOnLoadMethod` 会在首个场景前自动完成 `IBridge` 注入。 - `IBridge` 是小游戏运行时的必需依赖;缺少对应平台桥接程序集或自动注册失败时 SDK 会立即抛出配置异常,不会返回默认数据或切换其它实现。 - iOS 首次 `pod install` 较慢,可关闭面板的「执行 pod」开关,构建后手动执行。 - Android 平台资源(gradle 等)会在「刷新资源」时下载至 `Assets/Plugins/Android`。 ## 反馈 设置面板底部内置反馈入口,可针对当前 GID 提交评分(0–5)与文字建议,反馈直达官方。 更多文档详见: ### 本地存储 SDK 初始化入口先赋值 `gameId`,之后再初始化平台和本地数据。各平台 Bridge 的 `SetStorageSync` / `GetStorageSync` 直接处理 JSON 序列化和反序列化,并通过 `Seeg.GameId + key` 添加游戏前缀;已移除中间的 `SqlUtil`。原生、Editor、WebGL 和六个小游戏平台的存储 key 及数据格式保持不变。 旧版由 `SqlUtil` 添加 `gameId` 和序列化数据后交给 Bridge,新版将相同处理移到 Bridge;不需要迁移存储数据。 ## 统一支付 包含七个小游戏 IBridge 的统一命令实现及独立 SeegPayment.jslib。配套核心为 seeg-cs 2.0.6,Runtime/Sdk 生成 DLL 不纳入源码提交。 详见 [统一支付接入](docs/PAYMENTS.md)。