This is the full developer documentation for IGP Developer Docs
# IGP Developer Docs
> IGP 官方开发者文档入口。建议先按功能了解 SDK 的能力范围,再按项目所用引擎查看 Unity / GameMaker / Godot 的接入细节。
## 先了解功能范围
[Section titled “先了解功能范围”](#先了解功能范围)
功能总览
查看每项能力在 Unity、GameMaker、Godot 上的支持状态。
[按功能使用 SDK →](/features/overview/)
启动与连接
接入 SDK 前,先确认 appId、桌面客户端连接,以及需要时的房间启动流程。
[启动与连接 →](/features/startup-connection/)
正版校验
校验玩家是否在 IGP 平台上合法持有游戏。
[正版校验 →](/features/game-authorization/)
实名认证与防沉迷
读取当前可玩状态、限制原因和状态变化。
[实名认证与防沉迷 →](/features/compliance/)
成就
解锁成就和上报成就进度。
[成就 →](/features/achievements/)
联机大厅
统一了解房间、实时消息、状态与 RPC、Mirror 传输层的接入顺序。
[联机大厅 →](/features/multiplayer-lobby/)
## 引擎接入细节
[Section titled “引擎接入细节”](#引擎接入细节)
细节总览
确认目标功能后,再按项目所用引擎查看安装、Quick Start 和调试说明。
[引擎接入细节 →](/getting-started/choose-engine/)
Unity
首选交付引擎。能力覆盖最全,适合正式接入和完整联调。
[Unity 概览 →](/unity/overview/)
Godot
Godot 适配层当前处于开发中,可用于评估启动、房间、消息和成就流程。
[Godot 概览 →](/godot/overview/)
GameMaker
首期面向 GameMaker(Windows 10 及以上),支持正版校验、实名认证与防沉迷和成就。
[GameMaker 概览 →](/gamemaker/overview/)
联调与测试
按功能和引擎检查本地联调结果。
[联调与测试 →](/testing/overview/)
发行说明
查看当前公开的下载包、版本与校验值。
[Release Notes →](/release-notes/)
Changelog
查看每个版本的具体变更。
[Changelog →](/changelog/)
## AI Agent 提示
[Section titled “AI Agent 提示”](#ai-agent-提示)
本站点内置 [`llms.txt`](/llms.txt) 和 [`llms-full.txt`](/llms-full.txt),便于 Cursor、Claude、ChatGPT 等工具读取完整文档内容。
# 页面找不到
> 404 · 当前访问的页面不存在,或者已被移动。
# Changelog
> 按版本记录 IGP SDK 的实际变更。
本页记录各版本的**实际变更**。
如需查看下载包、版本号和校验值,请查看 [Release Notes](/release-notes/)。
## 0.1.6 - 2026-06-12
[Section titled “0.1.6 - 2026-06-12”](#016---2026-06-12)
* Unity hosted data-plane attach 改为同一 `roomId + playerId` single-flight,避免并发重复请求 descriptor 和重复替换 KCP session。
* Unity Direct KCP data-plane 现在只有收到 `kcp_handshake_ack` 后才进入 connected;重连前会先关闭旧 KCP,并按 `500ms -> 1s -> 2s` 退避重试,同时丢弃过期 attempt 的回调。
* Unity runtime 将 `STATE_NOT_FOUND`、`INVALID_STATE_SCOPE`、`INVALID_REQUEST`、`FORBIDDEN` 分类为业务错误;`STATE_NOT_FOUND` 会为常见 global state key 写入默认值,不再触发连接服务不可用提示。
* `bridge/contracts/data-plane.md` 补充 data-plane single-flight、重连关闭顺序、handshake ack 和 stale attempt 处理语义。
* Unity / Godot / GameMaker SDK Environment 新增 `PREVIEW`,自动连接 IndieGamesPass Preview 桌面端与 `\\.\pipe\igp-desktop-sdk-preview`。
* Unity MirrorTransportDemo 调试面板新增 Rematch 按钮;Unity / Godot hosted session 增加 rematch 发送回归测试,锁定 `RematchGame` command code 为 `16`。
## 0.1.5 - 2026-06-12
[Section titled “0.1.5 - 2026-06-12”](#015---2026-06-12)
* Unity reliable data 发送改为按 KCP `WaitSnd` 可用容量 drain,不再受固定字节率/token bucket 限制;当 `WaitSnd` 不可用时保留每次 drain 的兜底上限。
* Unity reliable 发送队列满时返回 `kErrorSendQueueFull`;Mirror transport 会将其视为可靠通道丢失并断开对应 peer,便于重连后重建状态。
* Unity Mirror transport 优先发送小 reliable payload,不再静默丢弃已接收但未派发的 inbound transport 消息,并新增 10 秒入站静默断线和 shutdown disconnect best-effort flush。
* Unity reliable reassembly 在 inflight/buffer 压力下驱逐最旧 partial 消息而不是抛异常,并在网络诊断中输出 `reassemblyEvicted`。
* Unity hosted data-plane 状态在 KCP 仍 alive 时会从陈旧 `error` 状态恢复,避免 transient transport error 后状态误报。
## 0.1.4 - 2026-06-10
[Section titled “0.1.4 - 2026-06-10”](#014---2026-06-10)
* Unity SDK 新增独立版本可选 Cloud Archive 模块 `cn.indiegp.sdk.unity.cloud-archive` `0.1.4`,通过 desktop session 转发云存档读取和保存请求,`slot` 固定为 `"1"` 到 `"5"`,并暴露 `version` / `baseVersion` 与 409 冲突时的 `currentVersion`。
* Unity desktop session 能力集新增 `cloudArchive`,`cloudArchiveForward` 在能力缺失时会提前报错;Cloud Archive API 失败响应会解析 Desktop 归一化错误体,并兼容旧版 API envelope。
* Unity 发布新增 Cloud Archive 可选 `.unitypackage`,发布脚本、Unity 包测试清单、安装页和下载表已纳入 `cn.indiegp.sdk.unity.cloud-archive-.unitypackage`。
## 0.1.3 - 2026-06-09
[Section titled “0.1.3 - 2026-06-09”](#013---2026-06-09)
* Unity KCP RTT 统计新增稳定/原始双口径:发送心跳时若 KCP 已有排队,样本会标记为拥塞,只进入 `LastRTT` / `RawAvgRTT` 和诊断日志,不再污染常规 `AvgRTT` 延迟显示。
* Unity 网络诊断补充 `rttLastMs`、`rttAvgMs`、`rttRawAvgMs`、`rttCongested`、`pingQueueDepth`,用于判断瞬时高延迟是业务包排队、真实网络波动还是接收侧积压。
* Unity 网络诊断日志和屏幕 overlay 改为独立开关:`EnableNetworkDiagnostics` 只开启采样/日志,`ShowNetworkDiagnosticsOverlay` 才显示屏幕面板,避免测试或正式包开启日志时自动出现调试 UI。
* Unity 点对点可靠消息新增出站调度器,按 token bucket、每帧 payload 上限和 `WaitSnd` 高低水位逐帧释放可靠分片,降低 Mirror / 大 payload 瞬时灌入 KCP 的风险;诊断补充 `netOutQueue`、`netOutSent`、`netOutThrottle`。
* Unity KCP 接收侧提高 burst drain 上限,并在需要时扩容 KCP receive buffer,避免合法较大消息因固定缓冲过小卡在接收队列头;诊断补充 `recvLimit`、`recvBufGrow`、`recvOversize`。
* Unity KCP 心跳 pong 不再每次输出普通 RTT 日志,避免高频日志在短时网络 burst 时放大 Unity 主线程抖动。
## 0.1.2 - 2026-06-09
[Section titled “0.1.2 - 2026-06-09”](#012---2026-06-09)
* Unity SDK 新增可选网络诊断采样,输出 `WaitSnd`、Mirror produced、KCP out/recv、`hit64`、`pktQueue`、`reassembly` 等指标,并提供诊断 overlay。
* Unity P2P 轮询兼容队列改为有界队列,避免只使用事件回调的游戏让 SDK 内部队列无限增长。
* Unity hosted data-plane 协商会自动钳制可靠分片大小,避免 JSON/base64 包装超过 KCP frame 上限。
* Unity 网络回调改为在 SDK 网络状态锁外触发,降低游戏回调执行重活时对 SDK 接收链路的放大影响。
* Unity SDK 运行时上报版本改为显式包版本,避免接入侧误判 SDK 版本。
## 0.1.1 - 2026-06-09
[Section titled “0.1.1 - 2026-06-09”](#011---2026-06-09)
* Unity hosted session 在同一房间 rematch 回到 waiting 时会重置 KCP data plane 和 P2P 会话状态,避免下一局复用上一局的数据面状态。
## 0.1.0 - 2026-06-08
[Section titled “0.1.0 - 2026-06-08”](#010---2026-06-08)
* Unity SDK 新增可选 Lying Bottle 模块 `cn.indiegp.sdk.unity.lying-bottle`,提供类型化 desktop-session 转发入口,用于玩家资料、背包、商店、订单等桥接调用。
* Unity desktop session 增加 request/response 调用支持,`IGPRuntimeManager` 可通过 desktop session 转发 Lying Bottle 请求。
* 补充 Lying Bottle quickstart、README 和中文开发者指南,并按最新 bridge guide 收口接口字段、路由和购买数量范围。
## 0.0.8 - 2026-06-05
[Section titled “0.0.8 - 2026-06-05”](#008---2026-06-05)
* Unity SDK 在 desktop session 建联阶段新增 hosted bootstrap 请求,`IGPRuntimeManager` 可从桌面端拉取托管房间的初始化参数,简化托管模式接入。
* `IGPDesktopSessionClient` / `IGPDesktopSessionProtocol` 同步补充 hosted bootstrap 请求、响应模型和协议常量,相关协议契约由根目录 `igp-proto` 统一生成。
## 0.0.7 - 2026-05-27
[Section titled “0.0.7 - 2026-05-27”](#007---2026-05-27)
* Unity SDK 新增同一房间内运行中换地图事件,游戏可通过 `IGPRuntimeManager.onMapChanged` 或 `IGPEventManager.onMapChanged` 接收地图变化。
* 新增 `IGPMapChangeData`,包含变更前后的 `mapPublicId` / `mapVersionId` 和已更新的房间快照。
* Unity 快速接入、事件说明、房间生命周期示例、问题排查和官网房间文档已补充运行中换地图接入说明。
## 0.0.6 - 2026-05-13
[Section titled “0.0.6 - 2026-05-13”](#006---2026-05-13)
* Unity / GameMaker / Godot 成就模块新增清除当前游戏全部成就的调用入口,并返回清除结果。
* Unity Mirror 传输层默认兼容 Mirror `v89.0.0` 之后的版本,`v90.0.0` 以上仍作为推荐版本。
## 0.0.5 - 2026-05-12
[Section titled “0.0.5 - 2026-05-12”](#005---2026-05-12)
* desktop session 连接阶段新增协议版本校验,desktop 过旧或协议不兼容时会立即给出清晰错误。
* SDK 会根据 desktop 返回的能力清单判断功能是否可用,避免后续调用时才失败。
## 0.0.4 - 2026-05-12
[Section titled “0.0.4 - 2026-05-12”](#004---2026-05-12)
* SDK 主动启动桌面端时,正式环境只允许启动官方可信的 IndieGamesPass;开发环境仍支持显式指定本机调试桌面端。
* Unity Editor 中未配置游戏 exe 调试路径时,SDK 会自动带上 Unity Editor 当前进程路径,并通过桌面端 SDK 联调规则按 appId 联调。
* Unity SDK 改为显式初始化,游戏需要主动调用 `InitializeAsync()`。
* Unity Editor 中 `IGPRuntimeManager` 会自动挂载项目里的 `IGPConfig`,缺失时自动创建配置。
* desktop session、host bridge 和 hosted session 的协议常量改为统一生成,减少协议结构漂移。
* Unity SDK 文档已同步最新接入方式和 Editor 联调说明。
## 0.0.2 - 2026-04-29
[Section titled “0.0.2 - 2026-04-29”](#002---2026-04-29)
* Unity SDK 新增可选合规模块 `cn.indiegp.sdk.unity.compliance`,用于实名认证和防沉迷功能的事件读取和状态变化通知。
* 合规模块新增实名认证和防沉迷功能的年龄段和剩余可玩时长读取入口,游戏无需自行换算。
* 实名认证和防沉迷功能遇到网络或服务异常时,会在合规模块内按不允许进入处理,默认提示为「网络或服务异常」。
* Unity SDK 加强本地通信、编辑器联调和离线授权缓存的安全处理,降低本机异常输入与调试信息残留风险。
* Unity SDK 发布包调整为 `.unitypackage`,便于在 Unity Editor 中通过 `Import Package` 直接导入。
## 0.0.1 - 2026-03-31
[Section titled “0.0.1 - 2026-03-31”](#001---2026-03-31)
SDK 初始化版本。
* 提供 Unity SDK 基础能力,支持启动连接、成就、房间联机大厅、实时消息、状态与 RPC 等核心功能。
* 提供 Unity Mirror 传输层可选包,用于接入基于 Mirror 的联机场景。
* 提供基础发布包、示例工程和接入说明,便于开发者完成首轮集成与验证。
# 成就
> 在不同引擎中解锁成就和上报成就进度。
## 功能说明
[Section titled “功能说明”](#功能说明)
成就能力分为三类:解锁成就、上报成就进度、清除当前游戏全部成就。成就 key 必须与后台配置一致,示例中的 key 仅用于说明调用方式。
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | --------------------------------- |
| Unity | Preview | 主包提供公开调用入口。 |
| GameMaker | Preview | Windows runtime 提供解锁、进度上报和清除全部成就。 |
| Godot | 开发中 | 预览 runtime 已有成就调用入口。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已完成 [启动与连接](/features/startup-connection/)。
* 后台已经创建对应成就。
* 游戏代码中的成就 key 和后台配置一致。
* Unity / GameMaker / Godot 当前都通过本机 IGP 桌面客户端完成成就调用。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
```csharp
using UnityEngine;
using IGP.UnitySDK;
public sealed class IGPAchievementButtons : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
public async void UnlockFirstSession()
{
var result = await IGPSDK.UnlockAchievementAsync(
runtimeManager,
"first_session");
Debug.Log($"Unlock success={result.success}, duplicated={result.duplicated}");
}
public async void AddMatchProgress()
{
var result = await IGPSDK.ReportAchievementProgressAsync(
runtimeManager,
"matches_played",
1,
"match_complete");
Debug.Log($"Progress success={result.success}, duplicated={result.duplicated}");
}
public async void ClearAllAchievements()
{
var result = await IGPSDK.ClearAchievementsAsync(runtimeManager);
Debug.Log($"Clear success={result.success}, deleted={result.deletedCount}");
}
}
```
* GameMaker
```txt
// 解锁成就
igp_unlock_achievement(
"first_session",
"",
0,
global.igp_app_id);
// 上报进度
igp_report_achievement_progress(
"matches_played",
1,
"match_complete",
"",
0,
global.igp_app_id);
// 清除当前游戏全部成就
igp_clear_achievements(global.igp_app_id);
```
结果从事件队列读取。
```txt
var evt = igp_poll_event();
while (!is_undefined(evt))
{
if (evt.type == "achievement_result")
{
show_debug_message("Achievement success: " + string(evt.success));
}
else if (evt.type == "achievement_clear_result")
{
show_debug_message("Cleared achievements: " + string(evt.deleted_count));
}
evt = igp_poll_event();
}
```
* Godot
Godot 当前建议通过 autoload 调用成就接口。
```csharp
using Godot;
using IGP.GodotSDK.Autoload;
public partial class AchievementPanel : Control
{
private IGPGodotAutoload IGP =>
GetNode("/root/IGP");
public async void UnlockFirstSession()
{
await IGP.UnlockAchievementAsync("first_session");
}
public async void AddMatchProgress()
{
await IGP.ReportAchievementProgressAsync(
"matches_played",
1,
"match_complete");
}
public async void ClearAllAchievements()
{
await IGP.ClearAchievementsAsync();
}
}
```
Godot 仍处于开发中,正式项目不应将当前 API 视为稳定承诺。
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 检查点 |
| --------- | ---------------------------------------------------------------- |
| Unity | 调用后日志中出现 `success`、`duplicated`、`message`;清除时会返回 `deletedCount`。 |
| GameMaker | 事件队列中收到 `achievement_result` 或 `achievement_clear_result`。 |
| Godot | 调用后触发 `AchievementReported` 或 `AchievementsCleared` signal。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* `success=false`:先检查成就 key 是否存在。
* `duplicated=true`:表示该成就之前已经解锁,不一定是错误。
* 清除全部成就只影响当前游戏下当前登录用户的成就记录,通常只建议用于调试、测试或后台明确允许的重置流程。
* 没有任何结果:先确认 IGP 桌面客户端已连接,再确认游戏代码是否在轮询或监听事件。
* 分步成就进度异常:确认后台成就类型和进度上报值是否匹配。
# 实名认证与防沉迷
> 在不同引擎中读取实名认证与防沉迷状态。
## 功能说明
[Section titled “功能说明”](#功能说明)
实名认证与防沉迷用于让游戏判断当前玩家是否可以继续游玩,以及是否需要根据平台返回状态执行限制、提示或退出。SDK 只提供状态,不代替游戏决定弹窗、存档、退出或切换账号流程。
IGP 支持两种处理方式:由平台在启动前拦截,或由游戏在游戏内处理登录与实名流程。希望用户不跳出游戏时,推荐使用“游戏内实名”方式:游戏调用 SDK 申请认证入口,在游戏内 WebView 打开;用户未登录时先完成 IGP 登录或注册,登录后如果尚未实名,页面会继续进入实名信息填写。游戏只承载 WebView 和处理回调,不接触用户身份凭证、姓名或身份证号。
## 处理方式
[Section titled “处理方式”](#处理方式)
* **启动拦截**:适用于希望平台在游戏启动前完成实名与防沉迷判断的项目。在开发者后台选择该方式后,不符合条件的用户会在进入游戏前被拦截,游戏通常不需要主动打开实名 WebView。
* **游戏内实名**:适用于希望用户留在游戏内完成登录、注册和实名的项目。游戏启动后读取状态;需要实名时调用 SDK 获取认证入口,在游戏内 WebView 打开;收到完成回调后刷新状态。
两种方式应在开发者后台按项目选择,不建议在同一版本中同时设计两套互相冲突的拦截流程。下方代码示例主要面向“游戏内实名”方式;如果项目选择“启动拦截”,游戏侧重点是正常启动后的状态读取和提示,不再自行拉起实名 WebView。
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | ------------------------------------------------- |
| Unity | Preview | 通过可选实名认证与防沉迷模块读取状态、监听变化,并处理游戏内实名流程。 |
| GameMaker | Preview | GameMaker Windows 版已提供当前状态、刷新和事件队列,适合配合启动拦截或状态展示。 |
| Godot | 暂不支持 | 当前 Godot 侧未提供实名认证与防沉迷入口。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已完成 [启动与连接](/features/startup-connection/)。
* 本机 IGP 桌面客户端可用。
* IGP 开发者后台已开启实名认证与防沉迷,并选择“启动拦截”或“游戏内实名”。
* Unity 项目需要额外安装 `cn.indiegp.sdk.unity.compliance`。
* 游戏需要自行处理不可玩状态,例如提示、返回主菜单或退出。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
Unity 需要在主包外额外安装 `cn.indiegp.sdk.unity.compliance`。下面示例面向“游戏内实名”方式;如果项目选择“启动拦截”,通常只需要保留状态刷新和阻断提示逻辑。
```csharp
using UnityEngine;
using IGP.UnitySDK;
using IGP.UnitySDK.Compliance;
public sealed class IGPComplianceDriver : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
private System.IDisposable subscription;
private void OnEnable()
{
subscription = IGPCompliance.SubscribeAntiAddictionEvents(
runtimeManager,
HandleComplianceEvent);
}
private void OnDisable()
{
subscription?.Dispose();
}
public async void Refresh()
{
var ev = await IGPCompliance.RefreshAntiAddictionEventAsync(runtimeManager);
HandleComplianceEvent(ev);
}
public async void OpenAccountVerification()
{
var webSession = await runtimeManager.CreateAntiAddictionRealNameWebSessionAsync();
OpenGameWebView(webSession.url);
}
public async void OnWebViewNavigation(string url)
{
if (!url.StartsWith("igp://anti-addiction/real-name-complete"))
{
return;
}
CloseGameWebView();
var ev = await IGPCompliance.RefreshAntiAddictionEventAsync(runtimeManager);
HandleComplianceEvent(ev);
}
private void HandleComplianceEvent(IGPAntiAddictionComplianceEvent ev)
{
if (ev.action == IGPAntiAddictionComplianceActions.Block)
{
// 根据 ev.reasonMessage 展示提示,或回到主菜单。
}
}
private void OpenGameWebView(string url) {}
private void CloseGameWebView() {}
}
```
* GameMaker
GameMaker 侧可以读取本地最近状态,也可以主动刷新状态。当前 GameMaker 版尚未提供游戏内实名 WebView 入口,更适合配合“启动拦截”方式做状态读取和提示。
```txt
// Step 或按钮触发
var status = igp_refresh_anti_addiction_status(global.igp_app_id);
if (!is_undefined(status) && !status.canPlayNow)
{
show_debug_message("IGP anti-addiction blocked: " + string(status.reasonMessage));
}
```
也可以从事件队列中接收状态变化。
```txt
var evt = igp_poll_event();
while (!is_undefined(evt))
{
if (evt.type == "anti_addiction_state_changed")
{
var status = evt.anti_addiction_status;
show_debug_message("IGP anti-addiction: " + string(status.state));
}
evt = igp_poll_event();
}
```
* Godot
Godot 当前暂不支持实名认证与防沉迷入口。
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 检查点 |
| --------- | -------------------------------------------------------------------------------------------------- |
| Unity | 启动拦截方式下,不符合条件的用户不会进入游戏主流程;游戏内实名方式下,未实名时能在游戏内 WebView 打开认证入口,完成后刷新状态。 |
| GameMaker | 能读取 `anti_addiction_status`,刷新后能收到 `anti_addiction_state_changed`;如使用启动拦截方式,需要确认不符合条件的用户不会进入游戏主流程。 |
| Godot | 当前不做实名认证与防沉迷验收。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* Unity 找不到 `IGPCompliance`:确认已安装实名认证与防沉迷模块包。
* 状态为空或保持默认值:先确认 IGP 桌面客户端是否连接成功。
* 用户不应跳出游戏:使用游戏内 WebView 打开 SDK 返回的 `url`,不要直接交给系统浏览器。
* 收到阻断状态:游戏应按返回原因处理,不要在 SDK 层硬编码放行逻辑。
* GameMaker 没有状态变化事件:确认调用了 `igp_update()` 并轮询事件队列。
# 正版校验
> 在不同引擎中接入 IGP 正版校验。
## 功能说明
[Section titled “功能说明”](#功能说明)
正版校验用于确认当前玩家是否在 IGP 平台上合法持有这款游戏。建议尽早接入启动流程,避免玩家进入主要玩法后才处理失败结果。
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | -------- | ---------------------------------------- |
| Unity | Preview | 通过 `IGPRuntimeManager` 自动接入桌面客户端授权流程。 |
| GameMaker | Preview | 通过 Windows runtime 和本机桌面客户端完成授权。 |
| Godot | 暂未暴露独立入口 | 当前 Godot 侧主要覆盖启动票据、房间和成就,尚未提供独立正版校验 API。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已完成 [启动与连接](/features/startup-connection/)。
* 已配置 IGP 分配的 `appId`。
* 本机 IGP 桌面客户端可用。
* 需要验证正式游戏时,后台授权配置必须和当前 `appId` 对齐。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
Unity 项目通常只需配置 `appId`,运行时会处理授权流程。业务侧主要监听状态变化。
```csharp
using UnityEngine;
using IGP.UnitySDK;
public sealed class IGPAuthorizationView : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
private void OnEnable()
{
runtimeManager.onAuthorizationStateChanged.AddListener(OnAuthorizationChanged);
runtimeManager.onAuthorizationFailed.AddListener(OnAuthorizationFailed);
}
private void OnDisable()
{
runtimeManager.onAuthorizationStateChanged.RemoveListener(OnAuthorizationChanged);
runtimeManager.onAuthorizationFailed.RemoveListener(OnAuthorizationFailed);
}
private void OnAuthorizationChanged(IGPAuthorizationState state)
{
Debug.Log($"IGP authorization: {state}");
if (runtimeManager.IsAuthorized)
{
// 允许进入主菜单或继续游戏。
}
}
private void OnAuthorizationFailed(string message)
{
Debug.LogError($"IGP authorization failed: {message}");
}
}
```
如需完成最小验证,请先执行 [Unity Quick Start](/unity/quickstart/)。
* GameMaker
GameMaker 侧需要先初始化 runtime,再在每帧更新并读取授权状态。
```txt
// Create
global.igp_app_id = YOUR_APP_ID;
igp_init(global.igp_app_id, {
desktop_auto_attach: true
});
```
```txt
// Step
igp_update();
var state = igp_get_authorization_state();
if (state == "authorized_online" || state == "authorized_offline")
{
// 允许进入游戏。
}
var evt = igp_poll_event();
while (!is_undefined(evt))
{
if (evt.type == "authorization_state_changed")
{
show_debug_message("IGP authorization: " + string(evt.state));
}
evt = igp_poll_event();
}
```
完整接入顺序见 [GameMaker Quick Start](/gamemaker/quickstart/)。
* Godot
Godot 当前没有独立正版校验入口。开发中版本可以从命令行读取启动票据并进入联机流程,但不应将其视为正式的正版校验 API。
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 检查点 |
| --------- | --------------------------------------------------------------------------------------------------- |
| Unity | 监听到 `AuthorizedOnline` 或 `AuthorizedOffline`,失败时能看到失败原因。 |
| GameMaker | `igp_get_authorization_state()` 从 `pending` 进入 `authorized_online`、`authorized_offline` 或 `failed`。 |
| Godot | 当前不做独立正版校验验收。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* 授权持续处于 `pending`:先确认桌面客户端连接是否已成功。
* 授权失败但连接正常:检查 `appId` 和后台配置是否匹配。
* Unity Editor 中验证桌面能力失败:按 [Unity 调试](/unity/debugging/) 配置 Editor 调试项。
* GameMaker 没有事件:确认每帧调用了 `igp_update()`,并持续轮询 `igp_poll_event()`。
# Mirror 传输层
> 在 Unity Mirror 项目中使用 IGP 传输层。
## 功能说明
[Section titled “功能说明”](#功能说明)
Mirror 传输层属于 [联机大厅](/features/multiplayer-lobby/) 的 Unity 专用子能力。它不是主 SDK 的替代品,而是用于让已经使用 Mirror 的项目将 Mirror 收发连接接入 IGP 房间数据面。
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | ---------------------------------------------- |
| Unity | Preview | 通过 `cn.indiegp.sdk.unity.mirror-transport` 提供。 |
| GameMaker | 不适用 | GameMaker 不使用 Mirror。 |
| Godot | 不适用 | Godot 不使用 Unity Mirror。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 项目已经使用 Unity Mirror。
* Mirror 版本为 `v89.0.0` 或更高版本;推荐 `v90.0.0` 或更高版本。
* 已安装 `cn.indiegp.sdk.unity` 主包。
* 已安装 `cn.indiegp.sdk.unity.mirror-transport` 可选包。
* 已完成 [房间](/features/rooms/) 的房间主流程。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
先安装主包:
```text
cn.indiegp.sdk.unity
```
如果项目已经使用 Mirror,再安装可选包:
```text
cn.indiegp.sdk.unity.mirror-transport
```
场景中需要保留以下对象:
```text
IGPRuntimeManager
IGPMirrorTransport
Mirror NetworkManager
```
然后将 Mirror 的 `NetworkManager.transport` 指向 `IGPMirrorTransport`。
业务代码仍然按 Mirror 原有方式编写;IGP 只负责将底层传输接入当前房间。
```csharp
using Mirror;
using UnityEngine;
using IGP.UnitySDK.MirrorTransport;
public sealed class MirrorTransportCheck : MonoBehaviour
{
[SerializeField] private NetworkManager networkManager;
[SerializeField] private IGPMirrorTransport igpTransport;
private void Awake()
{
networkManager.transport = igpTransport;
}
}
```
完整示例工程见 `samples/unity/MirrorTransportDemo`。
* GameMaker
GameMaker 不使用 Unity Mirror,因此不适用这个传输层包。
* Godot
Godot 不使用 Unity Mirror,因此不适用这个传输层包。
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 检查点 |
| --------- | -------------------------------------------------------------------------------------- |
| Unity | Mirror `NetworkManager.transport` 已指向 `IGPMirrorTransport`,host / client 可通过 IGP 房间连接。 |
| GameMaker | 不适用。 |
| Godot | 不适用。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* Mirror 仍走原传输层:检查 `NetworkManager.transport` 引用。
* 找不到 `IGPMirrorTransport`:确认已安装 Mirror 可选包。
* 能进入房间但 Mirror 不可用:先确认主包房间流程可用,再排查 Mirror 配置。
# 联机大厅
> IGP SDK 中基于房间的联机能力总览。
联机大厅是一组基于房间的能力,而不是彼此独立的功能集合。推荐接入顺序是:先进入房间,再在房间内使用实时消息、状态同步、RPC 或 Mirror 传输层。
## 能力关系
[Section titled “能力关系”](#能力关系)
| 能力 | 作用 | 接入前提 |
| ----------------------------------------- | --------------------------- | ------------------ |
| [房间](/features/rooms/) | 管理加入、ready、开始、结束、离开 | 由 IGP 桌面客户端启动 |
| [实时消息](/features/realtime-messaging/) | 房间内发送自定义消息 | 已进入房间 |
| [状态与 RPC](/features/state-rpc/) | 房间内同步状态、调用远端逻辑 | 已进入房间 |
| [Mirror 传输层](/features/mirror-transport/) | Unity Mirror 项目复用 IGP 房间数据面 | Unity、Mirror、已进入房间 |
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | ------------------------------------ |
| Unity | Preview | 联机大厅能力最完整,覆盖房间、消息、状态、RPC、Mirror 传输层。 |
| GameMaker | 暂不支持 | 当前 GameMaker 首期只覆盖桌面客户端能力,不包含房间联机。 |
| Godot | 开发中 | 预览 runtime 已有房间、消息、状态和 RPC 接口。 |
## 推荐接入顺序
[Section titled “推荐接入顺序”](#推荐接入顺序)
1. 先完成 [启动与连接](/features/startup-connection/)。
2. 再完成 [房间](/features/rooms/) 的最小流程。
3. 需要同步事件或聊天时,接 [实时消息](/features/realtime-messaging/)。
4. 需要共享房间状态或远端调用时,接 [状态与 RPC](/features/state-rpc/)。
5. Unity 项目已经使用 Mirror 时,再接 [Mirror 传输层](/features/mirror-transport/)。
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 最小验收 |
| --------- | ------------------------------------------ |
| Unity | 两个客户端能进入同一房间,一个客户端 ready 后另一个客户端能收到房间状态变化。 |
| GameMaker | 当前不做联机大厅验收。 |
| Godot | 能收到房间快照,并能调用 ready 或发送一条 JSON 消息。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* **消息、状态、RPC 均不可用**:优先确认房间是否已加入成功。
* **Unity 切场景后断线**:检查是否保留了唯一的 `IGPRuntimeManager`。
* **Mirror 不可用**:先确认普通房间流程可用,再检查 Mirror transport 引用。
* **Godot 收不到事件**:确认 autoload 已注册,并且房间联机连接已建立。
# 按功能使用 SDK
> 按能力查看 IGP SDK 在 Unity、GameMaker、Godot 上的支持情况和示例代码。
本组文档按功能组织。建议先确认 SDK 的能力范围,再查看目标能力在不同引擎中的接入示例。引擎目录仅保留安装、Quick Start、调试和示例工程等细节。
## 能力矩阵
[Section titled “能力矩阵”](#能力矩阵)
### 基础与桌面客户端能力
[Section titled “基础与桌面客户端能力”](#基础与桌面客户端能力)
| 功能 | 主要用途 | Unity | GameMaker | Godot | 接入前提 |
| -------------------------------------- | ------------ | ----------- | --------- | -------- | ----------------------- |
| [启动与连接](/features/startup-connection/) | 让 SDK 在游戏中可用 | Preview | Preview | 开发中 | `appId`、显式初始化、IGP 桌面客户端 |
| [正版校验](/features/game-authorization/) | 确认玩家合法持有游戏 | Preview | Preview | 暂未暴露独立入口 | 已连接 IGP 桌面客户端 |
| [实名认证与防沉迷](/features/compliance/) | 判断当前是否可玩 | Preview,可选包 | Preview | 暂不支持 | 已连接 IGP 桌面客户端、已选择处理方式 |
| [成就](/features/achievements/) | 解锁成就、上报进度 | Preview | Preview | 开发中 | 已连接 IGP 桌面客户端 |
### 联机大厅能力
[Section titled “联机大厅能力”](#联机大厅能力)
| 功能 | 主要用途 | Unity | GameMaker | Godot | 接入前提 |
| ----------------------------------------- | ------------------------ | ----------- | --------- | ----- | ------------------ |
| [联机大厅](/features/multiplayer-lobby/) | 基于房间的联机能力总入口 | Preview | 暂不支持 | 开发中 | 由 IGP 桌面客户端启动 |
| [房间](/features/rooms/) | ready、开始、结束、离开 | Preview | 暂不支持 | 开发中 | 由 IGP 桌面客户端启动 |
| [实时消息](/features/realtime-messaging/) | 房间内发送自定义消息 | Preview | 暂不支持 | 开发中 | 已进入房间 |
| [状态与 RPC](/features/state-rpc/) | 房间内同步状态、调用远端逻辑 | Preview | 暂不支持 | 开发中 | 已进入房间 |
| [Mirror 传输层](/features/mirror-transport/) | Unity Mirror 项目接入 IGP 传输 | Preview,可选包 | 不适用 | 不适用 | Unity、Mirror、已进入房间 |
## 选择入口
[Section titled “选择入口”](#选择入口)
* 需要确认 SDK 能力范围时,从本页能力矩阵开始。
* 需要接入 SDK 基础流程时,查看 [启动与连接](/features/startup-connection/) 中的初始化方式。
* 需要判断玩家是否可以进入游戏时,查看 [正版校验](/features/game-authorization/) 和 [实名认证与防沉迷](/features/compliance/)。
* 需要接入玩家成长或奖励体系时,查看 [成就](/features/achievements/)。
* 需要接入基于房间的联机大厅时,先查看 [联机大厅](/features/multiplayer-lobby/),再按需进入房间、实时消息、状态与 RPC 或 Mirror。
## 推荐阅读顺序
[Section titled “推荐阅读顺序”](#推荐阅读顺序)
1. 查看本页能力矩阵,确认 SDK 当前提供的功能。
2. 进入目标功能页,确认支持引擎和接入前提。
3. 如果需要安装、Quick Start 或调试说明,再进入 [引擎接入细节](/getting-started/choose-engine/)。
4. 回到目标功能页,按该功能的推荐顺序完成接入。
5. 接入完成后,按 [联调与测试](/testing/overview/) 执行检查。
## 状态说明
[Section titled “状态说明”](#状态说明)
* **Preview**:已有可用入口,但预览阶段仍可能调整。
* **开发中**:仓库内已有代码或样例,但尚未作为稳定公开交付。
* **暂不支持**:当前引擎没有这项能力入口。
* **不适用**:这项能力只面向某个特定引擎或技术栈。
# 实时消息
> 在不同引擎中发送和接收 IGP 房间实时消息。
## 功能说明
[Section titled “功能说明”](#功能说明)
实时消息属于 [联机大厅](/features/multiplayer-lobby/) 的子能力,用于房间内玩家之间发送自定义数据。Unity 侧提供可靠通道和大消息分片;Godot 当前提供 JSON 消息入口。实时消息需要先完成房间连接,不能在未进入房间时单独使用。
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | --------------------------- |
| Unity | Preview | 支持房间消息、可靠传输和大消息分片。 |
| GameMaker | 暂不支持 | 当前 GameMaker 首期不包含实时消息。 |
| Godot | 开发中 | 预览 runtime 已有 JSON 消息发送和接收。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已完成 [房间](/features/rooms/) 的最小流程。
* 已进入房间。
* 消息类型不要使用 SDK 保留类型。
* 发送的内容应保持结构稳定,便于两端解析。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
```csharp
using System;
using UnityEngine;
using IGP.UnitySDK;
using IGP.UnitySDK.Models;
public sealed class IGPChatDriver : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
private void OnEnable()
{
runtimeManager.onMessageReceived.AddListener(OnMessageReceived);
}
private void OnDisable()
{
runtimeManager.onMessageReceived.RemoveListener(OnMessageReceived);
}
public async void SendChat()
{
await runtimeManager.SendMessageAsync(new Message
{
type = "chat.message",
roomId = runtimeManager.CurrentRoomId,
playerId = runtimeManager.PlayerId,
reliable = true,
content = new
{
text = "hello",
sentAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
},
});
}
private void OnMessageReceived(string messageType, object content)
{
Debug.Log($"Message {messageType}: {content}");
}
}
```
* GameMaker
GameMaker 当前暂不支持实时消息。
* Godot
```csharp
using Godot;
using IGP.GodotSDK.Autoload;
public partial class ChatPanel : Control
{
private IGPGodotAutoload IGP =>
GetNode("/root/IGP");
public override void _Ready()
{
IGP.MessageReceived += OnMessageReceived;
}
public async void SendChat()
{
await IGP.SendMessageJsonAsync(
"chat.message",
"{\"text\":\"hello\"}",
reliable: true);
}
private void OnMessageReceived(
string messageType,
string roomId,
string playerId)
{
GD.Print($"Message {messageType} from {playerId}");
}
}
```
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 检查点 |
| --------- | ------------------------------------------- |
| Unity | 两个客户端在同一房间内,一端发送后另一端收到 `onMessageReceived`。 |
| GameMaker | 当前不做实时消息验收。 |
| Godot | 发送 JSON 消息后,另一端收到 `MessageReceived` signal。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* 发送成功但未收到消息:确认两个客户端在同一个房间。
* 内容解析失败:先用最简单的 JSON 字符串验证。
* Unity 大消息发送失败:优先使用可靠消息入口。
* Godot 报保留类型错误:换成业务自定义消息类型名。
# 房间
> 在不同引擎中接入 IGP 房间生命周期。
## 功能说明
[Section titled “功能说明”](#功能说明)
房间是 [联机大厅](/features/multiplayer-lobby/) 的基础能力。实时消息、状态与 RPC、Mirror 传输层都依赖房间流程。
房间能力覆盖进入房间、准备、开始、结束、重赛、离开、运行中换地图,以及玩家加入 / 离开等事件。房间流程通常需要由 IGP 桌面客户端按联调或正式流程启动游戏。
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | ----------------------- |
| Unity | Preview | 已提供完整房间主流程。 |
| GameMaker | 暂不支持 | 当前 GameMaker 首期不包含房间能力。 |
| Godot | 开发中 | 预览 runtime 已有房间生命周期调用。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已完成 [启动与连接](/features/startup-connection/)。
* 游戏通过 IGP 桌面客户端启动,并获取联机启动信息。
* Unity 场景中保留唯一的 `IGPRuntimeManager`。
* Godot 项目已注册 `IGPGodotAutoload`。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
```csharp
using UnityEngine;
using IGP.UnitySDK;
using IGP.UnitySDK.Models;
public sealed class IGPRoomDriver : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
private void OnEnable()
{
runtimeManager.onRoomJoined.AddListener(OnRoomJoined);
runtimeManager.onRoomUpdated.AddListener(OnRoomUpdated);
runtimeManager.onRoomLeft.AddListener(OnRoomLeft);
runtimeManager.onMapChanged.AddListener(OnMapChanged);
}
private void OnDisable()
{
runtimeManager.onRoomJoined.RemoveListener(OnRoomJoined);
runtimeManager.onRoomUpdated.RemoveListener(OnRoomUpdated);
runtimeManager.onRoomLeft.RemoveListener(OnRoomLeft);
runtimeManager.onMapChanged.RemoveListener(OnMapChanged);
}
private async void OnRoomJoined(Room room)
{
Debug.Log($"Joined room {room.id}");
await runtimeManager.SetReadyAsync(true);
}
public async void StartGame()
{
await runtimeManager.StartHostedGameAsync();
}
public async void FinishGame()
{
await runtimeManager.FinishHostedGameAsync();
}
public async void LeaveRoom()
{
await runtimeManager.LeaveHostedRoomAsync();
}
private void OnRoomUpdated(Room room) {}
private void OnRoomLeft(Room room) {}
private void OnMapChanged(IGPMapChangeData mapChange)
{
Debug.Log($"Map changed to {mapChange.currentMapPublicId}");
}
}
```
* GameMaker
GameMaker 当前暂不支持房间能力。
* Godot
Godot 当前建议通过 autoload 调用房间能力。
```csharp
using Godot;
using IGP.GodotSDK.Autoload;
public partial class RoomPanel : Control
{
private IGPGodotAutoload IGP =>
GetNode("/root/IGP");
public override void _Ready()
{
IGP.RoomSnapshotReceived += OnRoomSnapshotReceived;
IGP.RoomEventReceived += OnRoomEventReceived;
}
public async void Ready()
{
await IGP.SetReadyAsync(true);
}
public async void StartGame()
{
await IGP.StartHostedGameAsync();
}
public async void FinishGame()
{
await IGP.FinishHostedGameAsync();
}
private void OnRoomSnapshotReceived(string connectionStatus) {}
private void OnRoomEventReceived(int eventType, string roomId) {}
}
```
Godot 仍处于开发中,当前示例主要用于评估和对齐接入方式。
## 运行中换地图
[Section titled “运行中换地图”](#运行中换地图)
如果一局结束后仍然保留同一个房间,IGP 桌面客户端或 lobby 选择新地图后,会通过新的房间快照通知游戏。
Unity 游戏侧监听 `onMapChanged`:
```csharp
runtimeManager.onMapChanged.AddListener(mapChange =>
{
Debug.Log($"Map changed to {mapChange.currentMapPublicId}");
});
```
`IGPMapChangeData` 包含:
| 字段 | 说明 |
| ---------------------------------------------- | ----------- |
| `roomId` | 当前房间 ID |
| `previousMapPublicId` / `previousMapVersionId` | 变更前地图 |
| `currentMapPublicId` / `currentMapVersionId` | 变更后地图 |
| `room` | 已更新后的完整房间快照 |
`onMapChanged` 只在同一个房间内地图字段变化时触发。如果是离开旧房间再进入新房间,仍然按 `onRoomLeft` / `onRoomJoined` 处理。
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 检查点 |
| --------- | ----------------------------------------------------------------------- |
| Unity | 收到 `onRoomJoined`,调用 `SetReadyAsync(true)` 成功;运行中换地图时收到 `onMapChanged`。 |
| GameMaker | 当前不做房间验收。 |
| Godot | 收到 `RoomSnapshotReceived`,调用 `SetReadyAsync(true)` 成功。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* 无法进入房间:先确认游戏是否由 IGP 桌面客户端启动。
* Unity 切场景后房间断开:检查是否创建了第二个 `IGPRuntimeManager`。
* Unity 没收到换地图事件:确认仍在同一个 `roomId`,且新房间快照里的 `mapPublicId` 或 `mapVersionId` 已变化。
* ready 未生效:确认已经进入房间后再调用 ready。
* Godot 收不到房间快照:确认已完成 bootstrap,并建立了房间联机连接。
# 启动与连接
> 接入 IGP SDK 前必须先理解的启动、连接和运行时就绪流程。
启动与连接是所有能力的前置流程。不同引擎的接入方式不同,但目标一致:让游戏获得 `appId`,连接本机 IGP 桌面客户端,并在需要时进入联机大厅流程。
## 功能说明
[Section titled “功能说明”](#功能说明)
这一层主要负责:
* 读取或配置 `appId`
* 执行游戏主动触发的 SDK 初始化
* 连接本机 IGP 桌面客户端
* 判断连接状态
* 查询桌面客户端当前暴露的能力
* 处理从 IGP 桌面客户端启动游戏时注入的参数
* 在房间、实时消息、状态和 RPC 场景中建立房间联机连接
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | ------------------------------------------ |
| Unity | Preview | `IGPRuntimeManager` 负责桌面客户端连接、启动参数和房间联机连接。 |
| GameMaker | Preview | Windows runtime 负责初始化、每帧更新、能力查询和事件队列。 |
| Godot | 开发中 | 通过命令行参数 bootstrap,并用 autoload 暴露房间联机能力。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 本机安装 IGP 桌面客户端。
* 游戏已获得 IGP 分配的 `appId`。
* 游戏会在启动流程中调用 IGP SDK 初始化方法。
* 需要房间、实时消息、状态或 RPC 时,游戏必须由 IGP 桌面客户端按联调流程启动。
* 只验证成就、正版校验、实名认证与防沉迷时,也需要 IGP 桌面客户端连接可用。
## 游戏内初始化
[Section titled “游戏内初始化”](#游戏内初始化)
初始化由游戏项目自己的启动流程控制。只把 SDK 组件放进场景不会自动启动 SDK。
Unity 侧调用 `IGPRuntimeManager.InitializeAsync()` 完成初始化。
GameMaker 侧调用 `igp_init(...)` 完成初始化。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
Unity 侧需要在场景中放置一个 `IGPRuntimeManager`,配置 `appId`,并在启动流程中调用 `InitializeAsync()`。
```csharp
using UnityEngine;
using IGP.UnitySDK;
public sealed class IGPStartupDriver : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
private void OnEnable()
{
if (runtimeManager == null)
{
return;
}
runtimeManager.onConnectionStateChanged.AddListener(OnConnectionChanged);
runtimeManager.onRoomJoined.AddListener(room =>
{
Debug.Log($"IGP room joined: {room.id}");
});
runtimeManager.onError.AddListener(error =>
{
Debug.LogError($"IGP runtime error: {error}");
});
}
private async void Start()
{
await runtimeManager.InitializeAsync();
}
private void OnDisable()
{
if (runtimeManager == null)
{
return;
}
runtimeManager.onConnectionStateChanged.RemoveListener(OnConnectionChanged);
}
private void OnConnectionChanged(bool connected)
{
Debug.Log($"IGP connected={connected}");
}
}
```
如需在 Unity Editor 中调试完整房间流程,请查看 [Unity 调试](/unity/debugging/)。
* GameMaker
GameMaker 侧的基本流程为初始化、每帧更新和轮询事件。
```txt
// Create
global.igp_app_id = YOUR_APP_ID;
global.igp_sdk_enabled = true;
if (global.igp_sdk_enabled)
{
igp_init(global.igp_app_id, {
desktop_auto_attach: true
});
}
```
```txt
// Step
if (!global.igp_sdk_enabled)
{
exit;
}
igp_update();
var snapshot = igp_get_state_snapshot();
if (snapshot.connection_state == "connected")
{
// 可以继续读取授权、实名认证与防沉迷和成就相关状态。
}
var evt = igp_poll_event();
while (!is_undefined(evt))
{
show_debug_message("IGP event: " + string(evt.type));
evt = igp_poll_event();
}
```
如需确认桌面客户端支持的能力:
```txt
var capabilities = igp_get_desktop_capabilities();
if (!is_undefined(capabilities) && capabilities.achievements)
{
// 可以调用成就接口。
}
```
* Godot
Godot 当前通过命令行参数完成 bootstrap,并建议注册为 autoload。
```csharp
using Godot;
using IGP.GodotSDK.Autoload;
public partial class BootstrapFromCommandLine : Node
{
public override async void _Ready()
{
var igp = GetNode("/root/IGP");
var bootstrapped = await igp.BootstrapFromCommandLineAsync();
if (bootstrapped)
{
await igp.ConnectHostedSessionAsync();
}
}
}
```
Godot 仍是开发中状态,当前入口用于评估,不建议直接用于正式发行项目。
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 最小自测 |
| --------- | ---------------------------------------------------------------------------------- |
| Unity | 完成 [Unity Quick Start](/unity/quickstart/),非房间接入时至少看到桌面能力结果,房间接入时至少看到进房和 ready 日志。 |
| GameMaker | 完成 [GameMaker Quick Start](/gamemaker/quickstart/),确认连接状态不再停留在 `disconnected`。 |
| Godot | 用预览工程验证 `BootstrapFromCommandLineAsync()` 返回成功,并收到房间快照。 |
更完整的检查清单见 [联调与测试](/testing/overview/)。
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* **没有 appId**:优先补齐平台分配的 `appId`。
* **SDK 没有任何连接或事件**:确认是否调用了 `IGPRuntimeManager.InitializeAsync()` 或对应引擎的初始化入口。
* **没有从桌面客户端启动**:房间、实时消息、状态、RPC 通常不会完整可用。
* **连接状态持续失败**:先确认本机 IGP 桌面客户端是否已安装并可启动。
* **Unity 切场景后断线**:确保全程只有一个 `IGPRuntimeManager`,并按需要做成跨场景常驻。
# 状态与 RPC
> 在不同引擎中同步状态和调用 RPC。
## 功能说明
[Section titled “功能说明”](#功能说明)
状态与 RPC 属于 [联机大厅](/features/multiplayer-lobby/) 的子能力。状态用于同步房间内的共享数据或玩家数据;RPC 用于在房间内触发一段命名逻辑。两者都需要在玩家进入房间后使用。
## 支持引擎
[Section titled “支持引擎”](#支持引擎)
| 引擎 | 状态 | 说明 |
| --------- | ------- | ---------------------------------------------------------- |
| Unity | Preview | 支持状态 set / get / reset 和 RPC register / call / unregister。 |
| GameMaker | 暂不支持 | 当前 GameMaker 首期不包含状态和 RPC。 |
| Godot | 开发中 | 预览 runtime 已有 JSON 状态和 RPC 调用。 |
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已完成 [房间](/features/rooms/) 的最小流程。
* 已进入房间。
* 状态 key 和 RPC 名称需要保持稳定。
* Unity 如需接收事件,需要在场景中同时放置 `IGPEventManager`。
## 按引擎查看
[Section titled “按引擎查看”](#按引擎查看)
* Unity
```csharp
using System;
using UnityEngine;
using IGP.UnitySDK;
public sealed class IGPStateRpcDriver : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
public async void SetGlobalScore()
{
await runtimeManager.SetGlobalStateAsync("match.score", new
{
red = 1,
blue = 0,
updatedAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
});
}
public async void RegisterEchoRpc()
{
await runtimeManager.RegisterRPCAsync("sample.echo");
}
public async void CallEchoRpc()
{
var requestId = await runtimeManager.CallRPCAsync(
"sample.echo",
new { text = "hello" },
"all");
Debug.Log($"RPC request id={requestId}");
}
}
```
如需接收状态和 RPC 事件,需要在场景中同时放置 `IGPEventManager`,并监听其中的状态变化和 RPC 事件。
* GameMaker
GameMaker 当前暂不支持状态与 RPC。
* Godot
```csharp
using Godot;
using IGP.GodotSDK.Autoload;
public partial class StateRpcPanel : Control
{
private IGPGodotAutoload IGP =>
GetNode("/root/IGP");
public async void SetGlobalScore()
{
await IGP.SetStateJsonAsync(
"global",
"match.score",
"{\"red\":1,\"blue\":0}");
}
public async void RegisterEchoRpc()
{
await IGP.RegisterRpcAsync("sample.echo");
}
public async void CallEchoRpc()
{
await IGP.CallRpcJsonAsync(
"sample.echo",
"{\"text\":\"hello\"}",
"all");
}
}
```
## 自测方式
[Section titled “自测方式”](#自测方式)
| 引擎 | 检查点 |
| --------- | ------------------------------------------------------------- |
| Unity | 设置状态后能收到状态变化;注册 RPC 后能调用并收到响应。 |
| GameMaker | 当前不做状态与 RPC 验收。 |
| Godot | `SetStateJsonAsync`、`GetStateAsync`、`CallRpcJsonAsync` 能顺序完成。 |
## 常见问题 / 排查
[Section titled “常见问题 / 排查”](#常见问题--排查)
* 无法读取状态:确认 scope 和 key 完全一致。
* RPC 未触发:先确认已经注册对应 RPC 名称。
* Unity 未收到事件:确认场景中存在 `IGPEventManager`,并绑定了对应事件。
* Godot JSON 失败:先用简单对象字符串验证,例如 `{"value":1}`。
# GameMaker Native Bridge
> 面向 GameMaker(Windows 10 及以上)的本地桥接库与导出函数说明。
Native Bridge 是面向 **GameMaker(Windows 10 及以上)** 的本地桥接库。
## 角色
[Section titled “角色”](#角色)
* **`IGP.GamemakerDesktopBridge.Native.dll`** —— 负责真正的桌面连接、事件队列、结果状态
* **GameMaker 侧的 runtime 脚本** —— 将 DLL 的 C API 封装为 GameMaker 的函数调用
## 使用方式
[Section titled “使用方式”](#使用方式)
在 GameMaker 工程中:
1. 将 `IGP.GamemakerDesktopBridge.Native.dll` 作为 **Included File** 加入工程
2. 引入适配层提供的 GML runtime 脚本(见示例工程 `windows-auth-achievements`)
3. 在 `obj_controller` 等对象的 Create / Step 事件中按固定节奏调用 initialize / update / poll\_event
## 导出函数清单
[Section titled “导出函数清单”](#导出函数清单)
| 函数 | 作用 |
| --------------------------------------------- | --------------- |
| `igp_gms2_bridge_initialize` | 初始化桥 |
| `igp_gms2_bridge_update` | 每帧驱动(建议放在 Step) |
| `igp_gms2_bridge_poll_event` | 从事件队列读取下一条事件 |
| `igp_gms2_bridge_request_game_authorization` | 发起正版校验请求 |
| `igp_gms2_bridge_get_desktop_capabilities` | 查询桌面客户端能力集 |
| `igp_gms2_bridge_unlock_achievement` | 解锁成就 |
| `igp_gms2_bridge_report_achievement_progress` | 上报成就进度 |
| `igp_gms2_bridge_get_state_snapshot` | 获取当前状态快照 |
| `igp_gms2_bridge_shutdown` | 关闭桥 |
## 扩展约定
[Section titled “扩展约定”](#扩展约定)
后续如需扩展正版校验或能力查询,也应继续**在 Native Bridge 层增加导出**。
警告
不要将桌面连接协议的字节码、握手过程等细节分散到 GML 中。 GML 只消费 bridge 暴露出的函数与事件。
# GameMaker 调试
> 在示例工程或自有 GameMaker 工程中排查授权与成就问题。
本页仅说明 **GameMaker 当前首期能力** 的调试方式:
* 正版校验
* 成就解锁
* 成就进度上报
## 场景 A:调试官方示例
[Section titled “场景 A:调试官方示例”](#场景-a调试官方示例)
如需确认 SDK 主流程是否可用,建议优先运行发布包中的示例工程:
1. 打开 `samples/gamemaker/windows-auth-achievements/project/IGP.WindowsAuthAchievements.yyp`
2. 按 **F5** 运行
3. 重点查看界面上的以下字段:
* `Initialized`
* `Connection`
* `Authorization`
* `Pending events`
* `Latest result`
* `Latest error`
* `Latest event`
4. 按 **F1** 触发成就解锁
5. 按 **F2** 触发进度上报
如果示例工程可运行,但自有游戏无法得到预期成功结果,请先确认是否仍在使用演示用 `appId = 10` 和演示用成就 key。
## 场景 B:调试自有工程
[Section titled “场景 B:调试自有工程”](#场景-b调试自有工程)
在自有工程中,优先确认以下调用顺序是否成立:
1. `igp_init(app_id, options)` 在启动时只做一次
2. `igp_update()` 在 Step 或等价时机持续调用
3. `igp_poll_event()` 被持续排空
4. 需要结束时调用 `igp_shutdown()`
如果其中任一步骤缺失,状态可能出现局部更新,但连接不会真正就绪。
## 建议关注的状态
[Section titled “建议关注的状态”](#建议关注的状态)
排查自有工程时,建议直接查看 `igp_get_state_snapshot()` 返回的字段:
* `connection_state`
* `desktop_channel_state`
* `desktop_attach_state`
* `desktop_attach_source`
* `authorization_state`
* `authorization_required`
* `bridge_loaded`
* `bridge_error`
* `last_error`
* `last_result`
* `pending_events`
其中最关键的两个额外字段是:
* `bridge_loaded`:原生桥 DLL 是否已成功加载
* `bridge_error`:如果 DLL 加载失败,这里会保留最直接的原因
## 主动检查方式
[Section titled “主动检查方式”](#主动检查方式)
除等待状态变化外,也可以主动执行以下检查:
### 1. 主动请求一次正版校验
[Section titled “1. 主动请求一次正版校验”](#1-主动请求一次正版校验)
```txt
var result = igp_request_game_authorization(global.igp_app_id);
show_debug_message(json_stringify(result));
```
该调用返回的是“授权请求结果”,最终状态仍以 `authorization_state` 为准。
### 2. 查看当前桌面端暴露的能力
[Section titled “2. 查看当前桌面端暴露的能力”](#2-查看当前桌面端暴露的能力)
```txt
var capabilities = igp_get_desktop_capabilities();
show_debug_message(json_stringify(capabilities));
```
如果这一步无法获得结果,请优先排查桌面连接本身,而不是成就逻辑。
## 常见问题
[Section titled “常见问题”](#常见问题)
* **`APP_ID_REQUIRED`**:传进去的 `app_id` 为空、不是正数,或者根本没初始化成功。
* **`bridge_loaded = false`**:DLL 未加入 Included Files,或虽已加入但运行时未加载成功。
* **`bridge_error` 有值**:优先查看该字段,它通常比主观判断更接近真实原因。
* **`Connection` 长时间停留在 `connecting`**:桌面客户端未启动、未附着成功,或仍在等待自动启动完成。
* **`Authorization` 持续停留在 `pending`**:通常不是授权逻辑本身的问题,而是前置桌面连接尚未完成,或没有持续调用 `igp_update()`。
* **F1 / F2 触发后没有成功结果**:常见原因是成就 key 仍在使用示例值,或后台尚未配置该成就。
## 何时返回安装检查
[Section titled “何时返回安装检查”](#何时返回安装检查)
如果遇到以下问题,请优先返回 [GameMaker 安装](/gamemaker/installation/) 检查基础安装,而不是继续排查业务逻辑:
* 工程中没有 `igp_gms2_windows_runtime`
* Included Files 中没有 `IGP.GamemakerDesktopBridge.Native.dll`
* 一启动就报找不到脚本或 DLL
# GameMaker 安装
> 将 IGP GameMaker SDK 加入自有 GameMaker 工程。
本页仅说明**如何将 SDK 安装到自有 GameMaker 工程**。如需先完成最小验证流程,请查看 [GameMaker Quick Start](/gamemaker/quickstart/)。
## 前置条件
[Section titled “前置条件”](#前置条件)
* **GameMaker** `2024.2 LTS` 或更高
* **Windows 10 及以上**
* 本机安装 **IGP 桌面客户端**
* IGP 运营分配的 **`appId`**
## 下载并解压发布包
[Section titled “下载并解压发布包”](#下载并解压发布包)
从 [Release Notes](/release-notes/) 下载需要使用的版本。当前 GameMaker SDK 版本是 `0.0.6`,对应的发布包文件名是 `igp-gamemaker-sdk-0.0.6.zip`。解压后主要使用以下位置:
* `adapters/gamemaker/runtime/igp_gms2_windows_runtime.gml` —— 加入自有工程的 runtime 脚本
* `adapters/gamemaker/bridge/IGP.GamemakerDesktopBridge.Native.dll` —— 加入 Included Files 的原生桥 DLL
* `samples/gamemaker/windows-auth-achievements/` —— 官方示例工程和接入说明
## 安装到自有工程
[Section titled “安装到自有工程”](#安装到自有工程)
### 1. 加入 runtime 脚本
[Section titled “1. 加入 runtime 脚本”](#1-加入-runtime-脚本)
将 `adapters/gamemaker/runtime/igp_gms2_windows_runtime.gml` 作为 **script 资源** 加入工程。
建议保留脚本名 `igp_gms2_windows_runtime`,以便直接复用后续示例代码。
### 2. 加入原生桥 DLL
[Section titled “2. 加入原生桥 DLL”](#2-加入原生桥-dll)
将 `adapters/gamemaker/bridge/IGP.GamemakerDesktopBridge.Native.dll` 作为 **Included File** 加入工程。
建议放在 `datafiles/`,以便 GameMaker 运行时将 DLL 一并带到工作目录。
### 3. 保持默认可选项
[Section titled “3. 保持默认可选项”](#3-保持默认可选项)
常规接入先只准备好 `appId` 即可。
以下字段属于**调试或特殊发行覆盖**,首次接入通常不需要修改:
* `desktop_auto_attach`
* `desktop_pipe_endpoint`
* `desktop_launch_command`
默认行为已经是:
* 会自动尝试附着本机桌面客户端
* 留空时会按当前策略自动尝试发现并启动桌面客户端
## 验证安装
[Section titled “验证安装”](#验证安装)
安装完成后,至少确认以下事项:
1. 工程中已包含 `igp_gms2_windows_runtime` 这个 script 资源
2. Included Files 中已包含 `IGP.GamemakerDesktopBridge.Native.dll`
3. 按 **F5** 启动工程时,没有因为脚本缺失或 DLL 缺失直接报错
如需验证完整最小流程,请继续执行 [GameMaker Quick Start](/gamemaker/quickstart/)。
# GameMaker 概览
> IGP GameMaker SDK 的能力范围、接入前提和开始接入方式。
IGP GameMaker SDK 用于将 **GameMaker** 游戏接入 IGP 平台的正版校验、实名认证与防沉迷和成就能力。首期聚焦 Windows 上的桌面客户端能力,暂不支持联机房间。
本页仅说明 GameMaker 引擎相关细节。具体功能接入方式,请优先查看“按功能使用”中的对应页面。
## 功能列表
[Section titled “功能列表”](#功能列表)
* **运行时生命周期**:初始化、每帧更新、读取状态快照、轮询事件队列、关闭运行时。
* **正版校验**:在游戏启动时确认当前玩家是否在 IGP 平台上合法持有这款游戏,返回 `authorized_online` / `authorized_offline` 等状态(协议层对应 `RequestGameAuthorization`)。
* **连接状态**:观察与本机 IGP 桌面客户端的连接是否就绪。
* **桌面客户端能力查询**:调用能力前可先确认当前桌面客户端暴露了哪些能力。
* **实名认证与防沉迷**:读取当前状态、主动刷新状态,并通过 `anti_addiction_state_changed` 事件接收变化。
* **成就解锁**:按 key 解锁成就。
* **成就进度上报**:按 key 和增量上报进度。
* **事件队列**:通过一个轮询入口接收连接、授权、实名认证与防沉迷、成就、错误和断开事件。
## 暂不支持
[Section titled “暂不支持”](#暂不支持)
* 联机房间(创建 / 加入 / ready / 实时通信 / state / RPC)
* macOS / Linux / 主机 / 移动端
* 当前 Windows runtime 以外的其他 GameMaker 目标(HTML5 / YYC 等)
## 接入前提
[Section titled “接入前提”](#接入前提)
* **GameMaker** `2024.2 LTS` 或更高
* **Windows 10 及以上**
* 本机安装 **IGP 桌面客户端**
* IGP 运营分配的 **`appId`**
## 交付形态
[Section titled “交付形态”](#交付形态)
一个 zip 包,解压后包含:
* `IGP.GamemakerDesktopBridge.Native.dll` —— 原生桥接库(Windows)
* GML runtime 脚本 —— 将桥接库的 C API 封装为 GameMaker 函数
* `windows-auth-achievements` 示例工程 —— 可直接使用 GameMaker 打开
* `INTEGRATION.md` 与 `SMOKE-CHECKLIST.md` —— 接入和冒烟验收步骤
当前可用版本与下载链接见 [Release Notes](/release-notes/)。
## 开始接入
[Section titled “开始接入”](#开始接入)
1. 先查看 [GameMaker 安装](/gamemaker/installation/)
2. 完成最小验证流程:[GameMaker Quick Start](/gamemaker/quickstart/)
3. 确认基础启动流程:[启动与连接](/features/startup-connection/)
4. 按目标功能继续看:
* [正版校验](/features/game-authorization/)
* [实名认证与防沉迷](/features/compliance/)
* [成就](/features/achievements/)
5. 做完整检查:[联调与测试](/testing/overview/)
6. 如需排查状态和错误:[GameMaker 调试](/gamemaker/debugging/)
7. 需要查导出函数和底层边界:[GameMaker Native Bridge](/gamemaker/bridge/)
8. 查看示例目录和演示工程:[Windows 正版校验与成就示例](/gamemaker/sample-windows-auth-achievements/)
## 商标与版权声明
[Section titled “商标与版权声明”](#商标与版权声明)
本页面和 IGP GameMaker SDK 未由 YoYo Games、GameMaker 或 Opera 赞助,也不代表与上述主体存在官方关联或背书。
GameMaker、GameMaker 标志及相关品牌资产归 YoYo Games / Opera 及其关联方所有。GameMaker 名称、标志和品牌资产的使用应遵循 [GameMaker 官方品牌指南](https://gamemaker.io/en/legal/brand)。
# GameMaker Quick Start
> 使用官方示例或最小代码,在 GameMaker 中验证授权与成就流程。
本页提供两种最小验证方式:
* **运行官方示例**:使用发布包自带的示例工程完成验证
* **接入自有工程**:按最小调用顺序接入 runtime
当前首期覆盖:
* 正版校验
* 实名认证与防沉迷状态
* 成就解锁
* 成就进度上报
暂不覆盖房间、实时通信和 RPC。
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已经下载并解压 `igp-gamemaker-sdk-0.0.6.zip`
* 本机已安装并可启动 **IGP 桌面客户端**
* 如需验证**自有游戏**的成功流程,需已获得 IGP 分配的 `appId`
* GameMaker runtime 通过 `igp_init(...)` 初始化
* 如需验证实名认证与防沉迷,后台已选择“启动拦截”或“游戏内实名”;GameMaker 当前主要用于读取和刷新状态
## 1. 运行官方示例
[Section titled “1. 运行官方示例”](#1-运行官方示例)
1. 使用 GameMaker 打开 `samples/gamemaker/windows-auth-achievements/project/IGP.WindowsAuthAchievements.yyp`
2. 按 **F5** 运行
3. 确认界面上的以下状态是否开始刷新:
* `Initialized`
* `Connection`
* `Authorization`
* `Latest result`
* `Latest error`
* `Latest event`
4. 按 **F1** 触发一次成就解锁
5. 按 **F2** 上报一次 50% 进度
提示
该示例工程已预置 runtime 脚本和 DLL,不需要额外手动复制文件。
警告
示例工程默认带的是演示用配置:`appId = 10`,成就 key 是 `sample.windows.auth.unlock` 和 `sample.windows.auth.progress`。
如果只是确认示例能运行,可直接使用默认配置;如需验证**自有游戏**的授权和成就结果,请先将这些值替换为自有 `appId` 和后台已配置的成就项。
## 2. 接入自有工程的最小调用顺序
[Section titled “2. 接入自有工程的最小调用顺序”](#2-接入自有工程的最小调用顺序)
### Create 事件
[Section titled “Create 事件”](#create-事件)
```txt
global.igp_app_id = YOUR_APP_ID;
global.igp_sdk_enabled = true;
if (global.igp_sdk_enabled && !igp_init(global.igp_app_id, {
desktop_auto_attach: true
}))
{
show_debug_message("IGP init failed");
}
```
### Step 事件
[Section titled “Step 事件”](#step-事件)
```txt
if (!global.igp_sdk_enabled)
{
exit;
}
igp_update();
var evt = igp_poll_event();
while (!is_undefined(evt))
{
show_debug_message("IGP event: " + string(evt.type));
evt = igp_poll_event();
}
if (keyboard_check_pressed(vk_f1))
{
igp_unlock_achievement("YOUR_ACHIEVEMENT_KEY", "", 0, global.igp_app_id);
}
if (keyboard_check_pressed(vk_f2))
{
igp_report_achievement_progress(
"YOUR_PROGRESS_ACHIEVEMENT_KEY",
50,
"",
"",
0,
global.igp_app_id);
}
```
### Clean Up 事件
[Section titled “Clean Up 事件”](#clean-up-事件)
```txt
igp_shutdown();
```
## 3. 最小验收标准
[Section titled “3. 最小验收标准”](#3-最小验收标准)
在桌面客户端可用、`appId` 正确、成就项已配置的前提下,至少确认以下结果:
1. `igp_init(...)` 返回 `true`
2. `Connection` 不再持续停留在 `disconnected`
3. `Authorization` 会从 `pending` 进入一个明确结果
* `authorized_online`
* `authorized_offline`
* `failed`
4. 触发 F1 或 F2 后,`Latest result` 或 `Latest event` 有更新
## 4. 下一步
[Section titled “4. 下一步”](#4-下一步)
Quick Start 完成后,按目标能力继续:
* 按功能查看引擎示例:[按功能使用 SDK](/features/overview/)
* 确认基础启动流程:[启动与连接](/features/startup-connection/)
* 接入正版校验:[正版校验](/features/game-authorization/)
* 接入实名认证与防沉迷:[实名认证与防沉迷](/features/compliance/)
* 接入成就:[成就](/features/achievements/)
* 完成完整检查:[联调与测试](/testing/overview/)
* 将文件加入自有工程:[GameMaker 安装](/gamemaker/installation/)
* 排查状态和错误:[GameMaker 调试](/gamemaker/debugging/)
* 查询底层导出函数:[GameMaker Native Bridge](/gamemaker/bridge/)
* 查看示例目录内容:[Windows 正版校验与成就示例](/gamemaker/sample-windows-auth-achievements/)
# Windows 正版校验与成就示例
> GameMaker(Windows 10 及以上)首期示例:演示正版校验、连接状态、成就解锁与进度上报。
GameMaker(Windows 10 及以上)首期示例:演示**正版校验、连接状态、成就解锁与进度上报**。
## 快速开始
[Section titled “快速开始”](#快速开始)
1. 从 [Release Notes](/release-notes/) 下载需要使用的发布包。当前文件名是 `igp-gamemaker-sdk-0.0.6.zip`,解压到任意目录
2. 进入解压后的 `samples/gamemaker/windows-auth-achievements/project/`
3. 用 GameMaker(`2024.2 LTS` 及以上)打开 `IGP.WindowsAuthAchievements.yyp`
4. 按 **F5** 运行
5. 状态面板应显示当前连接状态与正版校验状态;如本机 IGP 桌面客户端已启动,连接应切换到 `connected`
提示
不需要手动复制 DLL 或 GML。`IGP.GamemakerDesktopBridge.Native.dll` 已在 `project/datafiles/` 中,运行时 GML 也已作为 script 资源预置在示例工程中。
警告
示例工程中预置的是演示用配置:`appId = 10`,成就 key 使用 `sample.windows.auth.unlock` 和 `sample.windows.auth.progress`。
如果只是确认示例能运行,可直接按上述步骤启动;如需验证**自有游戏**的授权和成就结果,请先将这些值替换为 IGP 分配的 `appId` 和后台已配置的成就项。
## 包含文件
[Section titled “包含文件”](#包含文件)
| 文件 | 用途 |
| --------------------------------------------------------- | ------------------------------- |
| `project/IGP.WindowsAuthAchievements.yyp` | 可直接打开的 GameMaker 工程壳 |
| `project/datafiles/IGP.GamemakerDesktopBridge.Native.dll` | 原生桥 DLL |
| `project/scripts/igp_gms2_windows_runtime/` | 运行时 GML(官方同步) |
| `project/objects/obj_igp_windows_auth_achievements/` | 示例对象,演示 Create / Step / Draw 接线 |
| `igp_windows_auth_achievements_sample.gml` | 示例控制器函数 |
| `igp_windows_auth_achievements_view.gml` | UI 渲染辅助函数 |
| `INTEGRATION.md` | 接入自有工程的步骤 |
| `SMOKE-CHECKLIST.md` | 冒烟验收清单 |
## 示例演示什么
[Section titled “示例演示什么”](#示例演示什么)
* 显示当前正版校验状态:`pending` / `authorized_online` / `authorized_offline` / `failed` / `skipped`
* 显示当前连接状态:`disconnected` / `connecting` / `connected` / `detached`
* 按 **F1** 触发一次成就解锁
* 按 **F2** 上报一次 50% 进度
* 显示最近一次结果(`success / operation`)与最近一次错误(`code: message`)
## 进一步
[Section titled “进一步”](#进一步)
本页主要说明示例包内容。首次接入时,建议按以下顺序阅读:
* [GameMaker 安装](/gamemaker/installation/)
* [GameMaker Quick Start](/gamemaker/quickstart/)
* [GameMaker 调试](/gamemaker/debugging/)
解压后的目录还包含两份面向接入的文档:
* `INTEGRATION.md` —— 将 bridge 接入自有 GameMaker 工程
* `SMOKE-CHECKLIST.md` —— 接入完成后的冒烟验收步骤
# 引擎接入细节
> 按引擎查看安装、Quick Start、调试和示例工程等细节。
本页仅汇总引擎相关细节:安装、Quick Start、调试和示例工程。
SDK 文档的主阅读顺序仍以功能为准。若尚未确认目标能力,建议先查看 [功能总览](/features/overview/)。
## Unity
[Section titled “Unity”](#unity)
Unity 是当前**首选交付引擎**,能力覆盖最完整。建议路径:
1. 先确认目标能力在 Unity 的支持状态:[功能总览](/features/overview/)
2. 进入对应功能页,先查看 Unity 小节
3. 需要安装或调试细节时,再阅读 [Unity 概览](/unity/overview/)
4. 按 [Unity 安装](/unity/installation/) 将 SDK 加入工程
5. 完成 [Unity Quick Start](/unity/quickstart/)
6. 确认 [启动与连接](/features/startup-connection/)
7. 回到目标功能页继续接入
8. 按 [联调与测试](/testing/overview/) 完成验收
9. 需要在 Editor 中调试时,查看 [Unity 调试](/unity/debugging/)
10. 已使用 Mirror 的项目,另行查看 [Mirror 传输层](/features/mirror-transport/)
## Godot
[Section titled “Godot”](#godot)
Godot 适配层目前仍在开发中,**不作为正式对外交付**。
* [Godot 概览](/godot/overview/)
* 可评估的功能入口见 [按功能使用 SDK](/features/overview/)
* 基础启动流程见 [启动与连接](/features/startup-connection/)
## GameMaker
[Section titled “GameMaker”](#gamemaker)
GameMaker 首期面向 Windows 10 及以上,正版校验、实名认证与防沉迷和成就主流程已可用:
1. 先确认目标能力在 GameMaker 的支持状态:[功能总览](/features/overview/)
2. 进入对应功能页,先查看 GameMaker 小节
3. 需要安装或调试细节时,再阅读 [GameMaker 概览](/gamemaker/overview/)
4. 将 SDK 加入工程:[GameMaker 安装](/gamemaker/installation/)
5. 完成最小验证流程:[GameMaker Quick Start](/gamemaker/quickstart/)
6. 确认 [启动与连接](/features/startup-connection/)
7. 回到目标功能页继续接入
8. 按 [联调与测试](/testing/overview/) 完成验收
9. 需要排查问题时,查看 [GameMaker 调试](/gamemaker/debugging/)
10. 需要查询底层导出函数时,再查看 [Native Bridge](/gamemaker/bridge/)
## Unreal
[Section titled “Unreal”](#unreal)
Unreal 适配层尚未开始。
# 介绍 IGP Developer Docs
> IGP Developer Docs 是什么、当前收录哪些功能、如何开始接入。
IGP Developer Docs 是 **面向游戏开发者** 的官方文档入口。
当前首批公开内容主要围绕游戏接入 IGP 平台能力。文档分为两层:
* **按功能使用**:说明 SDK 的能力范围、各能力支持的引擎,以及同一能力在不同引擎中的接入方式。
* **引擎接入细节**:补充 Unity、GameMaker、Godot 的安装、Quick Start、调试和示例工程说明。
## 当前收录什么内容
[Section titled “当前收录什么内容”](#当前收录什么内容)
* **功能使用文档**:将同一能力集中在一页,并按引擎提供示例代码。
* **引擎细节文档**:说明各引擎当前能力范围、安装方式和最小验证流程。
* **版本与下载**:集中列出当前公开包、下载链接和校验值。
* **调试与联调说明**:覆盖本地验证、常见卡点和示例工程。
这些文档背后对应的 IGP 平台能力,当前主要包括:
* **正版校验**:在游戏启动时校验当前玩家是否在 IGP 平台上合法持有这款游戏。
* **联机房间**:创建 / 加入 / 离开房间,配套 ready、start、finish 生命周期事件。
* **实时通信**:房间内玩家之间的可靠消息通道,大消息自动分片。
* **状态与 RPC**:跨端同步玩家状态、点对点调用房间内其他玩家的逻辑。
* **成就**:解锁与进度上报。
* **实名认证与防沉迷**:读取当前是否可玩,以及状态变化原因;支持“启动拦截”和“游戏内实名”两种处理方式。
## 支持的引擎
[Section titled “支持的引擎”](#支持的引擎)
| 引擎 | 能用吗 | 说明 |
| --------- | ---------- | ------------------------------- |
| Unity | ✅ Preview | 首选交付引擎,能力覆盖最全,当前文档最完整。 |
| GameMaker | ⚠️ Preview | 覆盖正版校验、实名认证与防沉迷和成就主流程,暂不支持联机房间。 |
| Godot | 🚧 开发中 | 暂无对外发布包。 |
| Unreal | ⏳ 规划中 | 尚未开始。 |
## 开始接入
[Section titled “开始接入”](#开始接入)
* 初次阅读文档时,建议从 [按功能使用 SDK](/features/overview/) 开始,先了解当前能力范围。
* 已确定目标能力时,进入对应功能页,确认支持引擎、接入前提和自测方式。
* 需要安装、Quick Start 或调试说明时,再查看 [引擎接入细节](/getting-started/choose-engine/)。
* 接入任何能力前,需先确认 [启动与连接](/features/startup-connection/) 中的初始化方式。
* 接入完成后,按 [联调与测试](/testing/overview/) 完成检查。
* 如需验证 Unity 最小流程,请查看 [Unity Quick Start](/unity/quickstart/)。
* 如需验证 GameMaker 最小流程,请查看 [GameMaker Quick Start](/gamemaker/quickstart/)。
* 如需查看当前可用版本与下载包,请查看 [Release Notes](/release-notes/)。
# Godot 概览
> IGP Godot SDK 当前能力、状态,以及预览接入方式。
开发中
IGP Godot SDK 当前**处于开发中**,尚无正式对外发布的包。 接口、包名、项目结构随时可能变动,**不建议**在正式项目中接入。
当前 Godot 适配层是面向 Godot C# 项目的 runtime。它已经可以验证房间联机和桌面客户端流程,但仍应按评估版本看待,并非稳定公开包。
本页仅说明 Godot 引擎相关细节。具体功能接入方式,请优先查看“按功能使用”中的对应页面。
## 功能列表
[Section titled “功能列表”](#功能列表)
* **命令行启动接入**:读取 IGP 启动参数并兑换启动票据。
* **Autoload 接入**:通过 `IGPGodotAutoload` 暴露 runtime,并提供 Godot signal、当前房间和当前玩家快照。
* **房间联机连接**:bootstrap 后连接房间并接收房间快照。
* **房间生命周期**:ready、离开、开始、结束、重赛、换队、刷新房间、ping。
* **实时通信**:发送 JSON 消息,并通过 autoload signal 接收房间消息。
* **状态与 RPC**:设置、读取、重置状态;注册、取消注册、调用 RPC。
* **成就**:通过本机 IGP 桌面客户端解锁成就和上报进度。
* **错误与断开信号**:通过 Godot signal 接收错误和断开原因。
## 当前状态
[Section titled “当前状态”](#当前状态)
* 已完成与 IGP 后台、IGP 桌面客户端的最小流程验证
* 已完成 runtime、autoload、signal 参考和示例场景的初版实现
* 样例覆盖联机 quickstart、房间生命周期、实时通信和 autoload 接入
* **尚未定型**:API 命名、场景接入方式、分发形态都可能变动
## 正式发布后的计划形态
[Section titled “正式发布后的计划形态”](#正式发布后的计划形态)
稳定后,Godot 适配层计划以下列两种方式之一对外发布:
* Godot Asset Library 条目(首选)
* 一个 zip 包,与 GameMaker 适配层的分发方式一致
正式发布后,本页面会补充:
* 支持的 Godot 版本(平台口径与全站一致:仅 Windows 10 及以上)
* 安装步骤
* Quick Start
* 示例工程链接
## 预览接入
[Section titled “预览接入”](#预览接入)
如需评估 Godot 接入或提前对齐接入方式,请联系 IGP 运营获取预览版本。当前预览版本**仅用于评估**,不建议直接用于发行项目。
如需了解当前已有的评估入口,可先阅读:
* [按功能使用 SDK](/features/overview/)
* [启动与连接](/features/startup-connection/)
* [成就](/features/achievements/)
* [联机大厅](/features/multiplayer-lobby/)
* [联调与测试](/testing/overview/)
## 商标与版权声明
[Section titled “商标与版权声明”](#商标与版权声明)
本页面和 IGP Godot SDK 未由 Godot Foundation 赞助,也不代表与 Godot Foundation 存在官方关联或背书。
Godot、Godot Engine、Godot 标志及相关商标归 Godot Foundation 所有。Godot 名称、标志和相关商标的使用应遵循 [Godot Trademark Policy and License](https://godot.foundation/policies-and-procedures/trademark-policy)。
# Release Notes
> IGP Developer Docs 当前收录的各引擎 SDK 包版本、下载链接与校验值。
本页列出 IGP Developer Docs **当前公开的各引擎 SDK 包版本**、下载链接与校验值。
每个版本都有固定下载链接,并附带 `SHA256SUMS`;正式项目请固定具体版本,不要直接使用 `latest`。
如需查看每个版本的具体变更,请查看 [Changelog](/changelog/)。
当前最新版本:Unity `0.1.6`,Unity Cloud Archive `0.1.4`,GameMaker `0.0.6`。
0.1.6 更新重点:
* Unity hosted data-plane attach 改为同一 `roomId + playerId` single-flight,避免重复请求 descriptor 和重复替换 KCP session。
* Unity Direct KCP 只有收到 `kcp_handshake_ack` 后才进入 connected;重连会先关闭旧 KCP,再按 `500ms -> 1s -> 2s` 退避重试并丢弃过期 attempt 回调。
* Cloud Archive 仍是独立版本 `0.1.4`;当前公开版本:Unity 为 0.1.6,Unity Cloud Archive 为 0.1.4,GameMaker 仍为 0.0.6。
下载后可以用 `SHA256SUMS` 做校验,命令:
```bash
sha256sum -c SHA256SUMS
```
Windows 下可以用 PowerShell 对比:
```powershell
Get-FileHash -Algorithm SHA256 .\cn.indiegp.sdk.unity-0.1.6.unitypackage
```
## 当前可用版本
[Section titled “当前可用版本”](#当前可用版本)
### Unity
[Section titled “Unity”](#unity)
| 版本 | 文件 | 下载 |
| ------- | -------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------ |
| `0.1.6` | `cn.indiegp.sdk.unity-0.1.6.unitypackage` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.6/cn.indiegp.sdk.unity-0.1.6.unitypackage) |
| `0.1.6` | `cn.indiegp.sdk.unity.mirror-transport-0.1.6.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.6/cn.indiegp.sdk.unity.mirror-transport-0.1.6.unitypackage) |
| `0.1.6` | `cn.indiegp.sdk.unity.compliance-0.1.6.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.6/cn.indiegp.sdk.unity.compliance-0.1.6.unitypackage) |
| `0.1.6` | `cn.indiegp.sdk.unity.lying-bottle-0.1.6.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.6/cn.indiegp.sdk.unity.lying-bottle-0.1.6.unitypackage) |
| `0.1.6` | `cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.6/cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage) |
| `0.1.6` | `SHA256SUMS` | [查看](https://docs.indiegp.cn/downloads/unity/0.1.6/SHA256SUMS) |
| `0.1.5` | `cn.indiegp.sdk.unity-0.1.5.unitypackage` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.5/cn.indiegp.sdk.unity-0.1.5.unitypackage) |
| `0.1.5` | `cn.indiegp.sdk.unity.mirror-transport-0.1.5.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.5/cn.indiegp.sdk.unity.mirror-transport-0.1.5.unitypackage) |
| `0.1.5` | `cn.indiegp.sdk.unity.compliance-0.1.5.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.5/cn.indiegp.sdk.unity.compliance-0.1.5.unitypackage) |
| `0.1.5` | `cn.indiegp.sdk.unity.lying-bottle-0.1.5.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.5/cn.indiegp.sdk.unity.lying-bottle-0.1.5.unitypackage) |
| `0.1.5` | `cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.5/cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage) |
| `0.1.5` | `SHA256SUMS` | [查看](https://docs.indiegp.cn/downloads/unity/0.1.5/SHA256SUMS) |
| `0.1.4` | `cn.indiegp.sdk.unity-0.1.4.unitypackage` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.4/cn.indiegp.sdk.unity-0.1.4.unitypackage) |
| `0.1.4` | `cn.indiegp.sdk.unity.mirror-transport-0.1.4.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.4/cn.indiegp.sdk.unity.mirror-transport-0.1.4.unitypackage) |
| `0.1.4` | `cn.indiegp.sdk.unity.compliance-0.1.4.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.4/cn.indiegp.sdk.unity.compliance-0.1.4.unitypackage) |
| `0.1.4` | `cn.indiegp.sdk.unity.lying-bottle-0.1.4.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.4/cn.indiegp.sdk.unity.lying-bottle-0.1.4.unitypackage) |
| `0.1.4` | `cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.4/cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage) |
| `0.1.4` | `SHA256SUMS` | [查看](https://docs.indiegp.cn/downloads/unity/0.1.4/SHA256SUMS) |
| `0.1.3` | `cn.indiegp.sdk.unity-0.1.3.unitypackage` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.3/cn.indiegp.sdk.unity-0.1.3.unitypackage) |
| `0.1.3` | `cn.indiegp.sdk.unity.mirror-transport-0.1.3.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.3/cn.indiegp.sdk.unity.mirror-transport-0.1.3.unitypackage) |
| `0.1.3` | `cn.indiegp.sdk.unity.compliance-0.1.3.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.3/cn.indiegp.sdk.unity.compliance-0.1.3.unitypackage) |
| `0.1.3` | `cn.indiegp.sdk.unity.lying-bottle-0.1.3.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.3/cn.indiegp.sdk.unity.lying-bottle-0.1.3.unitypackage) |
| `0.1.3` | `cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.3/cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage) |
| `0.1.3` | `SHA256SUMS` | [查看](https://docs.indiegp.cn/downloads/unity/0.1.3/SHA256SUMS) |
| `0.1.0` | `cn.indiegp.sdk.unity-0.1.0.unitypackage` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.0/cn.indiegp.sdk.unity-0.1.0.unitypackage) |
| `0.1.0` | `cn.indiegp.sdk.unity.mirror-transport-0.1.0.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.0/cn.indiegp.sdk.unity.mirror-transport-0.1.0.unitypackage) |
| `0.1.0` | `cn.indiegp.sdk.unity.compliance-0.1.0.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.0/cn.indiegp.sdk.unity.compliance-0.1.0.unitypackage) |
| `0.1.0` | `cn.indiegp.sdk.unity.lying-bottle-0.1.0.unitypackage(可选)` | [下载](https://docs.indiegp.cn/downloads/unity/0.1.0/cn.indiegp.sdk.unity.lying-bottle-0.1.0.unitypackage) |
| `0.1.0` | `SHA256SUMS` | [查看](https://docs.indiegp.cn/downloads/unity/0.1.0/SHA256SUMS) |
* 安装方式:参考 [Unity 安装](/unity/installation/)
### GameMaker
[Section titled “GameMaker”](#gamemaker)
| 版本 | 文件 | 下载 |
| ------- | --------------------------------- | ----------------------------------------------------------------------------------- |
| `0.0.6` | `igp-gamemaker-sdk-0.0.6.zip(预览)` | [下载](https://docs.indiegp.cn/downloads/gamemaker/0.0.6/igp-gamemaker-sdk-0.0.6.zip) |
| `0.0.6` | `SHA256SUMS` | [查看](https://docs.indiegp.cn/downloads/gamemaker/0.0.6/SHA256SUMS) |
* 使用方式:解压后使用 GameMaker 打开 `samples/gamemaker/windows-auth-achievements/project/IGP.WindowsAuthAchievements.yyp`,并参考 [GameMaker Quick Start](/gamemaker/quickstart/)。
### Godot
[Section titled “Godot”](#godot)
Godot 适配层尚未正式对外发布,见 [Godot 概览](/godot/overview/)。
### Unreal
[Section titled “Unreal”](#unreal)
Unreal 适配层尚未开始。
## 升级策略
[Section titled “升级策略”](#升级策略)
Preview 阶段的升级建议:
* **固定版本**:记录当前使用的 Unity / GameMaker SDK 版本,**不要**直接指向 `latest/`。
* **版本记录**:每次升级之前备份旧的 `.unitypackage` / `.zip`,方便回滚。
* **校验**:下载后执行一次 `sha256sum -c SHA256SUMS`,确认文件完整。
* **接口变更**:预览阶段的 patch 版本仍可能有破坏性变更,发版时会在 release notes 里注明。
# 联调与测试
> 按功能检查 IGP SDK 的本地联调和上线前状态。
本页汇总本地联调和上线前检查路径。整体顺序仍以功能为主:先确认目标能力,再按对应引擎补充 Quick Start、调试和专项验证。
## 测试前准备
[Section titled “测试前准备”](#测试前准备)
* 本机安装并能启动 IGP 桌面客户端。
* 已获得正确的 `appId`。
* 游戏启动流程已按文档完成 SDK 初始化。
* 成就、正版校验、实名认证与防沉迷等能力已在后台完成必要配置;实名认证与防沉迷已选择“启动拦截”或“游戏内实名”。
* 需要房间、实时消息、状态和 RPC 时,应使用 IGP 桌面客户端启动游戏,不要仅直接双击可执行文件。
## Unity
[Section titled “Unity”](#unity)
推荐顺序:
1. 按 [Unity 安装](/unity/installation/) 安装主包。
2. 完成 [Unity Quick Start](/unity/quickstart/)。
3. 在 Editor 中按 [Unity 调试](/unity/debugging/) 处理启动参数和桌面客户端联调。
4. 按目标功能进入功能页执行专项自测。
最小验收:
* 单机或非房间接入时,能看到授权或成就调用结果。
* 需要房间时,能看到已进入房间、能设置 ready,并能发一条实时消息。
* 需要实名认证与防沉迷时,能按后台选择的处理方式完成验证。
## GameMaker
[Section titled “GameMaker”](#gamemaker)
推荐顺序:
1. 下载并解压 GameMaker 发布包。
2. 打开示例工程:`windows-auth-achievements`。
3. 按 [GameMaker Quick Start](/gamemaker/quickstart/) 完成初始化、授权和成就验证。
4. 需要排查时查看 [GameMaker 调试](/gamemaker/debugging/)。
最小验收:
* `igp_init(...)` 返回成功。
* 连接状态从 `disconnected` 进入明确状态。
* 授权状态从 `pending` 进入明确结果。
* 触发成就后能从事件队列看到结果。
* 刷新实名认证与防沉迷状态后能读到当前状态。
* 如使用启动拦截方式,能确认不符合条件的用户不会进入游戏主流程。
## Godot
[Section titled “Godot”](#godot)
Godot 当前是开发中预览,建议只做评估测试。
推荐顺序:
1. 注册 `IGPGodotAutoload`。
2. 验证启动场景能够获得 `/root/IGP`。
3. 调用 `BootstrapFromCommandLineAsync()`。
4. 验证 `RoomSnapshotReceived` 或错误 signal。
5. 再测试 ready、消息、状态、RPC、成就。
最小验收:
* 启动场景能够获得 autoload。
* bootstrap 成功后能建立房间联机连接。
* 至少收到一次房间快照。
## 按功能检查
[Section titled “按功能检查”](#按功能检查)
| 功能 | 检查入口 |
| ---------- | ----------------------------------------- |
| 启动与连接 | [启动与连接](/features/startup-connection/) |
| 正版校验 | [正版校验](/features/game-authorization/) |
| 实名认证与防沉迷 | [实名认证与防沉迷](/features/compliance/) |
| 成就 | [成就](/features/achievements/) |
| 联机大厅 | [联机大厅](/features/multiplayer-lobby/) |
| 房间 | [房间](/features/rooms/) |
| 实时消息 | [实时消息](/features/realtime-messaging/) |
| 状态与 RPC | [状态与 RPC](/features/state-rpc/) |
| Mirror 传输层 | [Mirror 传输层](/features/mirror-transport/) |
## 上线前检查
[Section titled “上线前检查”](#上线前检查)
* 文档中使用的 `appId` 已换成正式游戏的 `appId`。
* 示例 key 已换成后台真实配置的成就 key。
* 调试用启动参数、测试文件或临时配置没有进入正式包。
* 没有在正式场景中放置多个运行时实例。
* 失败、断线、授权失败、实名认证与防沉迷限制都有游戏内处理。
* SDK 初始化调用位置清晰,实名认证与防沉迷处理方式与游戏内流程一致。
# Unity 调试
> 在 Unity Editor 中调试 IGP SDK 的两种典型场景:验证桌面客户端能力,或验证完整托管房间流程。
本页说明 **如何在 Unity Editor 中调试 IGP SDK**。安装和最小接入请先查看 [安装](/unity/installation/) 和 [Quick Start](/unity/quickstart/)。
在 Editor 中调试 IGP SDK 有两种典型场景:
* **场景 A**:验证 IGP 桌面客户端提供的能力(正版校验、成就解锁、进度上报)。
* **场景 B**:验证完整托管房间流程(launch ticket、自动进房、ready、start、finish、房间消息、state、RPC、数据面)。
单机游戏或暂不接入联机房间的游戏,通常只需要完成场景 A。只有接入房间、realtime、state、RPC、Mirror Transport、KCP 或运行中换地图时,才需要完成场景 B。
## 场景 A:验证桌面客户端能力
[Section titled “场景 A:验证桌面客户端能力”](#场景-a验证桌面客户端能力)
这条路径使用 `desktop session`,不依赖房间上下文。它适用于正版校验、成就解锁、成就进度上报等 room 无关能力。
Unity Editor 里直接调 desktop 能力时,通常不需要填写 `Desktop Executable Path Debug Override`。
不填这个路径时,SDK 会按环境启动桌面端,并把 Unity Editor 当前进程路径和 `appId` 一起交给桌面端;是否允许联调由桌面端的 SDK 联调规则判断。只有需要模拟正式安装路径或排查本地 exe 绑定时,才需要填这个路径;此时应填写该游戏真实的 Windows 可执行文件路径(例如 `D:\builds\MyGame\MyGame.exe`),不要填写桌面端路径。
这个配置不是桌面端路径。桌面端启动命令由 SDK 根据 `SDK Environment` 自动选择:`PROD` 对应 IndieGamesPass,`PREVIEW` 对应 IndieGamesPass Preview,`DEV` 对应 IndieSpark。`PROD` 和 `PREVIEW` 只会启动对应环境的官方可信桌面端;`DEV` 才允许用 `Desktop Launch Command` 或 `INDIEGP_DESKTOP_PATH` 明确指定本机调试用桌面端。
注意
这个路径只会在 Editor 中生效。Build 生成的 Player 会使用自身 exe 路径,不需要额外清理。
## 场景 B:验证完整托管房间流程
[Section titled “场景 B:验证完整托管房间流程”](#场景-b验证完整托管房间流程)
这条路径使用 `hosted session`,只适用于需要房间上下文的能力。单机接入不需要创建测试房间或选择地图。
需要验证从 launch ticket 开始的端到端流程时:
### 1. 进入当前游戏的测试房间
[Section titled “1. 进入当前游戏的测试房间”](#1-进入当前游戏的测试房间)
1. 在 IGP 桌面客户端打开当前游戏的 `SDK 联调` 页
2. 创建测试房间,或者加入一个已经存在的测试房间
注意
`Connect Current Test Room` 只会连接当前已经在桌面客户端中进入的测试房间。 如果尚未进入房间,后续即使启动包正确,也会表现为连接失败。
### 2. 在 IGP 桌面客户端生成 Unity 启动包
[Section titled “2. 在 IGP 桌面客户端生成 Unity 启动包”](#2-在-igp-桌面客户端生成-unity-启动包)
在 IGP 桌面客户端中打开 `SDK 联调` 页,点击生成 `Unity 启动包`,复制生成的 JSON。
### 3. 将启动包粘贴到 Runtime Manager
[Section titled “3. 将启动包粘贴到 Runtime Manager”](#3-将启动包粘贴到-runtime-manager)
1. 打开包含 `IGPRuntimeManager` 的场景
2. 选中挂了 `IGPRuntimeManager` 的对象
3. 在 Inspector 中找到 `Unity Editor 联调 → Launch Package JSON`
4. 粘贴整包 JSON
5. 点击 `Apply Launch Package`
### 4. 进入 Play mode 并连接房间
[Section titled “4. 进入 Play mode 并连接房间”](#4-进入-play-mode-并连接房间)
1. 点击 Editor 的 `Play` 按钮
2. 在 Inspector 中点击 `Connect Current Test Room`
整个过程对 host 和 guest 是对称的:调试 host 端时使用 host 启动包,调试 guest 端时使用 guest 启动包。
## 常见问题
[Section titled “常见问题”](#常见问题)
* **只看到 `detached` 状态**:确认桌面端已登录、已打开 `SDK 联调`,后台已允许该账号联调当前 `appId`。
* **`Connect Current Test Room` 持续连接失败**:尚未先在 IGP 桌面客户端进入当前游戏的测试房间。
* **`Apply Launch Package` 后没有进房**:启动包已经过期(ticket 有时效),回到桌面客户端重新生成。
* **两端都已启动但看不到对方**:两端使用了**同一份**启动包。每个玩家都需要使用各自对应的启动包。
# Unity 安装
> 通过 Unity 标准导入包将 IGP.UnitySDK 加入 Unity 工程,并按需导入 Mirror 传输层和合规模块。
本页仅说明**如何将 SDK 安装到 Unity 工程**。安装完成后的接入主流程请查看 [Unity Quick Start](/unity/quickstart/)。
## 前置条件
[Section titled “前置条件”](#前置条件)
* Windows 10 及以上
* Unity `2022.3 LTS` 或更高
* 已注册的 `appId`(找 IGP 运营获取)
## 方式:导入 Unity Package(推荐)
[Section titled “方式:导入 Unity Package(推荐)”](#方式导入-unity-package推荐)
这是当前 **Preview 阶段的默认分发方式**。导入后 SDK 会放在 `Assets/IGP.UnitySDK` 下,便于 Unity 工程直接识别和编译。
### 1. 下载安装包
[Section titled “1. 下载安装包”](#1-下载安装包)
从 [Release Notes](/release-notes/) 选择需要锁定的版本。以当前 Unity SDK 版本 `0.1.6` 为例,需要下载:
* `cn.indiegp.sdk.unity-0.1.6.unitypackage` —— 主包(必需)
* `cn.indiegp.sdk.unity.mirror-transport-0.1.6.unitypackage` —— Mirror 传输层(可选)
* `cn.indiegp.sdk.unity.compliance-0.1.6.unitypackage` —— 实名认证与防沉迷模块(可选)
* `cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage` —— Cloud Archive 模块(可选)
下载后请与同目录的 `SHA256SUMS` 校验一致。
### 2. 先安装 Unity 依赖
[Section titled “2. 先安装 Unity 依赖”](#2-先安装-unity-依赖)
主包依赖 Unity 官方包 `Newtonsoft JSON` 和 `UGUI`。如果工程里还没有这两个包,请先在 Unity Editor 中打开 `Window → Package Manager`,通过 `Add package by name...` 添加:
* `com.unity.nuget.newtonsoft-json`
* `com.unity.ugui`
也可以直接在 `Packages/manifest.json` 的 `dependencies` 中加入:
```json
"com.unity.nuget.newtonsoft-json": "3.2.1",
"com.unity.ugui": "1.0.0"
```
### 3. 导入 SDK 包
[Section titled “3. 导入 SDK 包”](#3-导入-sdk-包)
在 Unity Editor 中执行:
1. `Assets → Import Package → Custom Package...`
2. 选择 `cn.indiegp.sdk.unity-0.1.6.unitypackage`
3. 确认导入全部文件
如果项目需要实名认证与防沉迷,再用同样方式导入 `cn.indiegp.sdk.unity.compliance-0.1.6.unitypackage`。
如果项目需要 Cloud Archive,再用同样方式导入 `cn.indiegp.sdk.unity.cloud-archive-0.1.4.unitypackage`。
如果项目已经在用 Mirror,再用同样方式导入 `cn.indiegp.sdk.unity.mirror-transport-0.1.6.unitypackage`。导入前请确认项目本身已经安装 Mirror。
提示
建议先导入主包并确认 Console 没有编译错误,再导入可选包。可选包依赖主包。
## 验证安装
[Section titled “验证安装”](#验证安装)
Unity Editor 打开后:
1. 工程里能看到 `Assets/IGP.UnitySDK`
2. 如导入可选包,能看到对应的 `Assets/IGP.UnitySDK.*` 目录
3. Console 没有关于 `IGP.UnitySDK` 的编译错误
4. `Assets/IGP.UnitySDK/package.json` 中的版本号与下载版本一致
安装完成后,请继续执行 [Unity Quick Start](/unity/quickstart/)。
# Unity 概览
> IGP Unity SDK 的能力范围、接入前提和开始接入方式。
IGP Unity SDK 用于将 Unity 游戏接入 IGP 平台的**正版校验、联机房间、实时通信、成就、实名认证与防沉迷**能力。接入方只需配置 `appId`,SDK 会处理与 IGP 桌面客户端和后台服务之间的通信。
本页仅说明 Unity 引擎相关细节。具体功能接入方式,请优先查看“按功能使用”中的对应页面。
## 功能列表
[Section titled “功能列表”](#功能列表)
* **正版校验**:在游戏启动时确认当前玩家是否在 IGP 平台上合法持有这款游戏,支持 `authorized_online` / `authorized_offline` 两种结果(协议层对应 `RequestGameAuthorization`)。
* **桌面客户端连接**:连接本机 IGP 桌面客户端,支持重试、按需启动和能力查询。
* **联机房间**:创建 / 加入 / 离开房间,ready、start、finish 生命周期事件,host / guest 对称。
* **实时通信**:房间内可靠消息、KCP 数据通道、大消息自动分片。
* **状态与 RPC**:跨端同步玩家状态,点对点调用房间内其他玩家的逻辑。
* **成就**:解锁与进度上报。
* **实名认证与防沉迷模块**:可选接入实名认证与防沉迷状态事件、年龄段读取、剩余可玩时长读取。
* **Mirror 传输层**:为已经使用 Mirror 的 Unity 项目提供可选传输层包。
## 接入前提
[Section titled “接入前提”](#接入前提)
* **Unity** `2022.3 LTS` 或更高
* **Windows 10 及以上**
* 本机安装 **IGP 桌面客户端**
* IGP 运营分配的 **`appId`**
## 包组成
[Section titled “包组成”](#包组成)
通过 Unity 标准导入包安装,三个包按需组合:
| 包名 | 用途 | 适用项目 |
| --------------------------------------- | ------------------------- | -------------------- |
| `cn.indiegp.sdk.unity` | 主包,包含 runtime 与 Editor 工具 | 所有接入项目都必装 |
| `cn.indiegp.sdk.unity.mirror-transport` | Mirror 传输层适配 | 仅**已经在用 Mirror** 的项目 |
| `cn.indiegp.sdk.unity.compliance` | 实名认证与防沉迷辅助入口 | 需要读取实名认证与防沉迷状态和事件的项目 |
主包附带以下示例,导入后可在 `Assets/IGP.UnitySDK/Samples` 下查看:
* `StarterDemo` —— 最小接入样例
* `RoomLifecycle` —— 房间生命周期演示
* `RealtimeMessaging` —— 实时 / state / RPC
* `Achievements` —— 成就解锁与进度上报
* `HostedPlayground` —— 综合手动联调台
## 开始接入
[Section titled “开始接入”](#开始接入)
1. 装包:[Unity 安装](/unity/installation/)
2. 按接入目标完成最小验证流程:[Unity Quick Start](/unity/quickstart/)
3. 确认基础启动流程:[启动与连接](/features/startup-connection/)
4. 按目标功能继续看:
* [正版校验](/features/game-authorization/)
* [实名认证与防沉迷](/features/compliance/)
* [成就](/features/achievements/)
* [联机大厅](/features/multiplayer-lobby/)
5. 做对应能力的完整检查:[联调与测试](/testing/overview/)
6. 如需在 Editor 中调试 desktop 能力或完整房间流程:[Unity 调试](/unity/debugging/)
7. 查看最新版本号与下载链接:[Release Notes](/release-notes/)
## 当前限制
[Section titled “当前限制”](#当前限制)
* Preview 阶段:接口仍可能有不兼容改动,请锁定具体版本号使用。
* **仅支持 Windows 10 及以上**。其他操作系统不在支持范围内。
* 联机房间需要通过本机 IGP 桌面客户端启动;纯无头环境(例如 CI / 云构建)目前不属于房间链路支持场景。
## 商标与版权声明
[Section titled “商标与版权声明”](#商标与版权声明)
本页面和 IGP Unity SDK 未由 Unity Technologies 或其关联公司赞助,也不代表与 Unity Technologies 或其关联公司存在官方关联或背书。
Unity、Unity 标志及其他 Unity 商标是 Unity Technologies 或其关联公司在美国及其他地区的商标或注册商标。Unity 相关商标、标志和素材的使用应遵循 [Unity 官方商标指南](https://unity.com/legal/branding-trademarks)。
# Unity Quick Start
> 使用 IGP.UnitySDK 在 Unity 工程中按目标能力验证桌面能力或托管房间主流程。
本 Quick Start 文档覆盖以下内容:
* 工程中已安装 `IGP.UnitySDK`
* 在场景中挂载 `IGPRuntimeManager`
* 只配置 `appId`
* 游戏启动流程中主动调用 `IGPRuntimeManager.InitializeAsync()`
* 单机或非房间接入先验证 **桌面能力**(正版校验 / 成就)
* 联机接入再通过 IGP 桌面客户端注入启动信息,验证 **进房 → ready → realtime**
也就是说,**桌面能力** 和 **房间流程** 都可以从本页开始验证,但二者的前提条件不同。 如果游戏不接入联机房间,不需要创建房间、选择地图、ready、realtime 或 KCP。 如需优先验证联机主流程,也不需要先完成成就配置。
数据面说明
当前 `Network.SendData(...)` 和 `Network.SendReliableData(...)` 均使用同一条可靠通道。 两者的主要区别在于**大消息自动分片**:`SendReliableData(...)` 会在需要时自动分片,`SendData(...)` 只适合小消息。
## 前置条件
[Section titled “前置条件”](#前置条件)
* 已经按 [Unity 安装](/unity/installation/) 将 `cn.indiegp.sdk.unity` 安装到工程中
* 有 IGP 运营提供的 `appId`
* 本机已安装并可启动 IGP 桌面客户端(Windows 10 及以上)
## 1. 添加一个最小 bootstrap 脚本
[Section titled “1. 添加一个最小 bootstrap 脚本”](#1-添加一个最小-bootstrap-脚本)
在工程中新增 `Assets/Scripts/IGPQuickstartDriver.cs`:
```csharp
using System;
using UnityEngine;
using IGP.UnitySDK;
using IGP.UnitySDK.Models;
public sealed class IGPQuickstartDriver : MonoBehaviour
{
[SerializeField] private IGPRuntimeManager runtimeManager;
[SerializeField] private string debugMessageType = "quickstart_ping";
[SerializeField] private string unlockAchievementKey = "first_session";
[SerializeField] private string progressAchievementKey = "matches_played";
private void Awake()
{
runtimeManager ??= FindObjectOfType();
}
private void OnEnable()
{
if (runtimeManager == null)
{
Debug.LogError("[IGP Quickstart] IGPRuntimeManager is missing.");
enabled = false;
return;
}
runtimeManager.onRoomJoined.AddListener(HandleRoomJoined);
runtimeManager.onMessageReceived.AddListener(HandleMessageReceived);
runtimeManager.onError.AddListener(HandleError);
}
private async void Start()
{
var ok = await runtimeManager.InitializeAsync();
if (!ok)
{
Debug.LogError("[IGP Quickstart] SDK initialization failed.");
}
}
private void OnDisable()
{
if (runtimeManager == null) return;
runtimeManager.onRoomJoined.RemoveListener(HandleRoomJoined);
runtimeManager.onMessageReceived.RemoveListener(HandleMessageReceived);
runtimeManager.onError.RemoveListener(HandleError);
}
[ContextMenu("IGP/Send Quickstart Message")]
public async void SendQuickstartMessage()
{
if (runtimeManager == null) return;
await runtimeManager.SendMessageAsync(new Message
{
type = debugMessageType,
roomId = runtimeManager.CurrentRoomId,
playerId = runtimeManager.PlayerId,
reliable = true,
content = new
{
text = "hello from quickstart",
sentAt = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(),
}
});
Debug.Log("[IGP Quickstart] Sent realtime message.");
}
[ContextMenu("IGP/Unlock Achievement")]
public async void UnlockAchievement()
{
if (runtimeManager == null) return;
var result = await IGPSDK.UnlockAchievementAsync(runtimeManager, unlockAchievementKey);
Debug.Log($"[IGP Quickstart] Unlock success={result.success}, duplicated={result.duplicated}");
}
[ContextMenu("IGP/Report Achievement Progress")]
public async void ReportAchievementProgress()
{
if (runtimeManager == null) return;
var result = await IGPSDK.ReportAchievementProgressAsync(
runtimeManager, progressAchievementKey, 1, "quickstart_manual");
Debug.Log($"[IGP Quickstart] Progress success={result.success}, duplicated={result.duplicated}");
}
private async void HandleRoomJoined(Room room)
{
Debug.Log($"[IGP Quickstart] Joined room id={room.id}, code={room.code}");
await runtimeManager.SetReadyAsync(true);
Debug.Log("[IGP Quickstart] Local player marked ready.");
}
private void HandleMessageReceived(string messageType, object content)
{
Debug.Log($"[IGP Quickstart] Message type={messageType}, payload={content}");
}
private void HandleError(string error)
{
Debug.LogError($"[IGP Quickstart] Runtime error: {error}");
}
}
```
## 2. 在场景中挂载运行时组件
[Section titled “2. 在场景中挂载运行时组件”](#2-在场景中挂载运行时组件)
1. 创建一个空对象,例如 `IGPBootstrap`
2. 为其挂载:
* `IGPRuntimeManager`
* `IGPQuickstartDriver`
3. 将 `IGPQuickstartDriver.runtimeManager` 指向同一个对象上的 `IGPRuntimeManager`
4. 如果游戏后续会切换场景且需要保持联机不中断,请将该对象设置为跨场景常驻,并确保全程只有一个 `IGPRuntimeManager`
常见误用
常见问题是第一个场景已将对象设为常驻,但后续场景又创建了新的同名对象,导致事件绑定到已废弃的实例上。
## 3. 配置 appId
[Section titled “3. 配置 appId”](#3-配置-appid)
给对象添加 `IGPRuntimeManager` 后,SDK 会自动挂载项目里的 `IGPConfig`。如果项目里还没有配置资源,会自动创建 `Assets/IGP/IGPConfig.asset`。
在 `IGPConfig` 上填写 IGP 运营提供的 `appId`。
SDK 不会因为场景里存在 `IGPRuntimeManager` 就自动启动。游戏需要在自己的启动流程中调用 `InitializeAsync()`。
## 4. 在 Editor 中验证
[Section titled “4. 在 Editor 中验证”](#4-在-editor-中验证)
按这次接入目标选择验证路径:
### 4.1 单机 / 非房间接入
[Section titled “4.1 单机 / 非房间接入”](#41-单机--非房间接入)
如果只接入正版校验、成就或其他 room 无关桌面能力,请先按 [Unity 调试](/unity/debugging/) 中的“验证桌面客户端能力”完成验证。
最低目标是看到:
1. `InitializeAsync()` 返回成功
2. 手动触发 `Unlock Achievement` 或 `Report Achievement Progress` 后看到成功日志
这条路径不要求创建房间、选择地图、进入 ready、发送 realtime 消息或连接 KCP。
### 4.2 联机 / 房间接入
[Section titled “4.2 联机 / 房间接入”](#42-联机--房间接入)
如果游戏接入房间、realtime、state、RPC、Mirror Transport、KCP 或运行中换地图,请按 [Unity 调试](/unity/debugging/) 中的“验证完整托管房间流程”完成进房验证。
最低目标是看到:
1. `Joined room` 日志
2. `Local player marked ready` 日志
3. 手动触发 `Send Quickstart Message` 后看到发送日志
如果这一步尚未通过,请先排查房间流程,不要同时排查成就问题。
## 5. 桌面能力调试路径说明
[Section titled “5. 桌面能力调试路径说明”](#5-桌面能力调试路径说明)
如需在 **Unity Editor** 中验证正版校验或成就,请使用 [Unity 调试](/unity/debugging/) 中“验证桌面客户端能力”的准备项。
通常不需要填写 `Desktop Executable Path Debug Override`。不填这个路径时,SDK 会按环境启动桌面端,并把 Unity Editor 当前进程路径和 `appId` 一起交给桌面端;是否允许联调由桌面端的 SDK 联调规则判断。只有需要模拟正式安装路径或排查本地 exe 绑定时,才需要填这个路径;此时应填写该游戏真实的 Windows 可执行文件路径,不要填写桌面端路径。
它不是桌面端路径。SDK 会按 `SDK Environment` 自动找对应桌面端:`PROD` 找 IndieGamesPass,`PREVIEW` 找 IndieGamesPass Preview,`DEV` 找 IndieSpark。`PROD` 和 `PREVIEW` 只会启动对应环境的官方可信桌面端;`DEV` 才允许用 `Desktop Launch Command` 或 `INDIEGP_DESKTOP_PATH` 明确指定本机调试用桌面端。
完成准备后,随后手动触发:
* `Unlock Achievement`
* `Report Achievement Progress`
## 6. 最小验收标准
[Section titled “6. 最小验收标准”](#6-最小验收标准)
验收标准按接入目标分开看:
### 单机 / 非房间接入
[Section titled “单机 / 非房间接入”](#单机--非房间接入)
1. `appId` 已配置
2. `InitializeAsync()` 成功
3. 正版校验或成就调用能返回预期结果
### 联机 / 房间接入
[Section titled “联机 / 房间接入”](#联机--房间接入)
1. 出现 `Joined room` 日志
2. 出现 `Local player marked ready` 日志
3. 手动触发 `Send Quickstart Message` 后看到发送日志
### 可选:桌面能力补充
[Section titled “可选:桌面能力补充”](#可选桌面能力补充)
1. 手动触发 `Unlock Achievement` 后看到成功日志
2. 或手动触发 `Report Achievement Progress` 后看到成功日志
## 7. 下一步
[Section titled “7. 下一步”](#7-下一步)
Quick Start 完成后,按目标能力继续:
* **按功能查看引擎示例**:[按功能使用 SDK](/features/overview/)
* **基础启动流程**:[启动与连接](/features/startup-connection/)
* **正版校验**:[正版校验](/features/game-authorization/)
* **成就**:[成就](/features/achievements/)
* **联机大厅**:[联机大厅](/features/multiplayer-lobby/)
* **最小代码样例**:主包 `Samples` 下的 `StarterDemo`(UPM → Samples 面板导入)
* **综合手动联调**:主包 `Samples` 下的 `HostedPlayground`
* **项目已使用 Mirror**:[Mirror 传输层](/features/mirror-transport/)
* **上线前检查**:[联调与测试](/testing/overview/)