更新日期:2026-06-23QuickGame(Unity)客户端接入文档
|
项 |
说明 |
|
Unity |
建议2018.4 LTS及以上(参考工程 2022.3 LTS) |
|
脚本运行时 |
.NET 4.x / 兼容 Unity 默认 API Level |
|
JSON |
依赖Newtonsoft.Json(发版包 Assets/Plugins/JsonNet/Newtonsoft.Json.dll) |
|
参考工程 |
unitybridgecn(本仓库) |
|
Demo 场景 |
Assets/Scenes/QuickGameDemo.unity |
|
统一配置 |
Assets/Resources/QKSettings.asset`(菜单 QuickSDK → Settings) |
3.1 拷贝到自有 Unity 工程
必选(所有平台)
按平台追加
平台
额外目录 / 资源
Android
Assets/Plugins/Android/(QKConnector.java、libs/*.aar、AndroidManifest.xml、Gradle 模板)+ `Editor/AndroidPreprocessBuild.cs、AndroidPostGenerateGradle.cs
iOS
Assets/QuickGameSDK/Editor/IOSPostProcessBuild.cs、QuickGameIOSIntegrationSettings.cs;原生 SDK 放iOS/releaseSDK(或设 UNITY_QUICKGAME_SDK_ROOT)
小游戏
Assets/QuickGameSDK/Channels/<渠道>/QGSDK.js + Editor/QuickGameWebGLChannelBuilder.cs + Assets/Plugins/WebGL/
PC
Assets/Plugins/Windows/(含 WindowsQGAdapter.cs)+ StreamingAssets/Quicksdk/PCSDK_release/PCSDKUI.exe
3.2 参考工程目录结构
注意:iOS 的 QKConnector.mm在 Build 时由 IOSPostProcessBuild 从releaseSDK/Unity3d/1. Xcode/拷贝到导出工程,无需事先放在 Assets/Plugins/iOS/
using quickgame; // QKGame、QuickListener // Windows / Android 配置类在 quicksdk 命名空间:PackageSettings(QKSettings.asset)
1. 该物体在场景中名称固定(不要用运行时随机名)
2. 物体上挂载继承自 QuickListener的脚本
启动 → setListener(QuickListener) // Awake → startSdk() // 读 QKSettings;iOS 自动三方登录;WebGL 自动 onSetHost + onInit → onInitSuccess / onInitFailed → onLogin() / onGuestLogin() → onUpdateRole(...) // Windows 支付前必调 → onPayOrder(QKPayOrderInfo) // 四端统一支付结构 → onLogout()
4.2 最小代码示例
using UnityEngine;
using quickgame;
public class GameSdkListener : QuickListener
{
public override void onInitSuccess() { /* 进入登录流程 */ }
public override void onInitFailed(ErrorMsg message) { }
public override void onLoginSuccess(UserInfo userInfo) { /* uid / token */ }
public override void onLoginFailed(ErrorMsg errMsg) { }
public override void onLogoutSuccess() { }
public override void onPaySuccess(PayResult payResult) { }
public override void onPayFailed(PayResult payResult) { }
public override void onPayCancel(PayResult payResult) { }
}
public class GameEntry : MonoBehaviour
{
[SerializeField] GameSdkListener listener;
void Awake() => QKGame.setListener(listener);
public void StartSdk() => QKGame.startSdk();
}
入口类:Assets/QuickGameSDK/Scripts/QKGame.cs
|
分类 |
说明 |
|
全平台公共接口 |
Android/ iOS / 小游戏 / PC 四端签名与用法一致,业务代码可直接写、用 #if 区分初始化/支付即可 |
|
平台专有接口 |
仅特定平台可用,或各平台初始化/支付/查询方式不同 |
5.1 调用约定
|
约定 |
说明 |
|
回调注册 |
setListener须在 Awake最早调用,且 Listener 所在 GameObject 名称固定 |
|
初始化 |
公共业务前先 startSdk()(或手动 onInit/ WebGL onSetHost) |
|
登录时机 |
收到 onInitSuccess 后再 onLogin |
|
角色上报 |
创角、进入游戏、升级、换服等节点均须 onUpdateRole;Windows 支付前必须先上报 |
|
支付 |
推荐全平台onPayOrder;onPay仍作原生兼容别名 |
|
支付发货 |
客户端 onPaySuccess仅供参考,游戏发货必须以服务端异步通知为准 |
|
登出后流程 |
onLogoutSuccess 后清除本地角色信息、回到登录界面,可按业务再调 onLogin() |
5.2 全平台公共接口
以下接口在Android、iOS、小游戏、PC 四端均可调用,方法名与参数一致
方法
返回值
回调
说明
setListener(QuickListener)
void
—
注册回调;必须最先调用
startSdk(productCode?, host?)
void
init 成功/失败
推荐:读 QKSettings 并一站式初始化
onPayOrder(QKPayOrderInfo)
void
pay 成功/失败/取消
推荐:全平台统一支付
onLogin()
void
onLoginSuccess / onLoginFailed
调起 SDK 登录
onUserCenter()
void
onUserCenterClose(可选)
打开用户中心
onLogout()
void
onLogoutSuccess
登出
onUpdateRole(...)
void
—
上报角色信息
|
参数 |
类型 |
必填 |
说明 |
|
listener |
QuickListener |
是 |
继承 QuickListener 的组件;将 listener.gameObject.name 传给原生/宿主供 SendMessage 回调 |
无参数。必须在 onInitSuccess 之后调用登录相关接口
onUpdateRole(roleId, role_name, server_Id, sv_name, role_level, vipLevel, role_power)
参数
类型
必填
说明
roleId
string
是
角色 ID
role_name
string
是
角色名
server_Id
string
是
区服 ID
sv_name
string
是
区服名
role_level
string
是
角色等级
vipLevel
string
否
VIP 等级;无则传""或 "0"
role_power
string
否
战力等;WebGL 可解析为 userRoleBalance
注意:创角、进游戏、升级、换服 等节点均应调用。字符串勿传 null 。Windows 支付前必须先调用本接口
void Awake() => QKGame.setListener(this);
void StartSdk() => QKGame.startSdk();
void OnEnterGame() {
QKGame.onUpdateRole(id, name, sid, sname, lv, vip, power);
QKGame.onLogin();
}
void OnPay() => QKGame.onPayOrder(new QKGame.QKPayOrderInfo { /* 见 5.2.3 字段 */ });
5.3.1 Android / iOS / Windows 公共(原生三端)
适用于 Android、iOS、Windows;WebGL **不使用本节初始化与支付接口
方法
返回值
回调
说明
onInit()
void
onInitSuccess / onInitFailed
初始化;无参时读 QKSettings 或桥接默认 productCode
onInit(productCode)
void
同上
iOS 传产品码;Android 仍走无参 Init(见 5.2.2)
onPay(...)
void
pay 成功/失败/取消
定额支付,见下表
onUserID()
string
—
同步用户 ID;未登录返回 ""
onUserToken()
string
—
同步 token
onUserName()
string
— |
同步用户名
onPay 参数
参数
类型
必填
说明
productId
string
是
商品 ID(iOS 为 App Store 商品 ID)
productName
string
是
商品名;建议传「元宝」「月卡」等,不带数量
amount
float
是
金额(元)
orderNo
string
是
CP 订单号
callBackUrl
string
否
服务端回调 URL,可 ""
extrasParams
string
否
透传,回调在 PayResult.extras
|
方法 |
返回值 |
说明 |
|
onInit(productCode) |
void |
与 5.2.1 相同签名;iOS 真机将 productCode 传入QKConnector;空则读 QKSettings/ 桥接默认 |
|
configureThirdPartyLogin(wxAppId, wxAppSecret, wxUniversalLink, qqAppId, qqUniversalLink) |
void |
微信/QQ 登录;必须 onInit() 之前;不用的渠道传 "" |
|
onDeviceIdfa() |
string |
同步 IDFA;非 iOS 返回 "" |
configureThirdPartyLogin 参数须与 Info.plist、开放平台后台一致;导出时 QuickGameIOSIntegrationSettings 会写入 URL Scheme
5.3.3 WebGL 专有(小游戏)
方法
返回值
回调
说明
onSetHost(host)
void
—
设置 SDK 网关;须在 onInit(productCode) 之前
onInit(productCode)
void
init 成功/失败
带产品码初始化;勿用无参 onInit()
onPayOrder(QKPayOrderInfo)
void
pay 成功/失败/取消
小游戏支付;order 不可 null
onSetHost参数
类型
说明
host
string
SDK 地址,如 https://qkgamesdk.quickapi.net;可与 QKSettings.baseUrl 一致
onInit参数
类型
说明
productCode
string
后台产品码;可与 QKSettings.productCode 一致
QKPayOrderInfo 字段见 5.4
WebGL 调用顺序:setListener → onSetHost → onInit(productCode) → onLogin → …
5.3.4 Android + iOS 共有(Windows / WebGL 无)
|
方法 |
返回值 |
说明 |
|
onGuestLogin() |
void |
游客/静默登录 |
|
onIsBindPhone() |
bool |
是否已绑定手机 |
|
onBindPhone() |
void |
调起绑定手机 |
|
onDeviceId() |
string |
同步设备 ID |
|
方法 |
返回值 |
说明 |
|
onRestoreNonConsumptionProducts() |
void |
恢复非消耗型内购 / 补单;回调 onRestoreSuccess(可选) |
5.3.6 Windows 说明
1. 初始化、支付、用户查询与 5.2.1 相同(onInit、onPay、onUserID 等)
2. 不支持onGuestLogin(见 5.2.4)
用于 onInitFailed、onLoginFailed 等失败回调
字段
类型
说明
errMsg
string
错误描述
用于 onLoginSuccess;继承自 ErrorMsg
字段
类型
说明
uid
string
用户 ID
token
string
登录 token
userName
string
账号名
timeLeft
long
防沉迷剩余时间(秒);-1 表示无限制
isNewUser
bool
是否新用户
errMsg
string
附加信息(继承字段)
原生 JSON 字段映射:userId→uid,userToken→token,timeleft /timeLeft→timeLeft,isNewUser("1"/"true")→isNewUser
用于 onPaySuccess / onPayFailed / onPayCancel
字段
类型
说明
code
string
状态码
message
string
状态描述
orderNo
string
SDK 订单号
cpOrderNo
string
CP 订单号
extras
string
下单时 extrasParams 透传回游戏
QKGame.QKPayOrderInfo,用于 onPayOrder
字段
类型
必填
说明
cpOrderNo
string
是
CP 订单号
subject
string
是
商品标题
desc
string
是
商品描述
goodsId
string
是
商品 ID
amount
string
是
金额(字符串,如 "6.00")
userRoleId
string
是
角色 ID
userRoleName
string
是
角色名
serverId
string
是
区服 ID
serverName
string
是
区服名
userLevel
string
是
角色等级
extrasParams
string
是
透传参数(可传 "")
callbackUrl
string
否
支付回调 URL,可空
goods_category
string
视渠道
商品类目(部分渠道必填)
buy_quantity
string
视渠道
购买数量(部分渠道必填)
5.5 接口速查
全平台公共
方法 setListener onLogin onUserCenter onLogout onUpdateRole
平台专有
归属
方法
iOS / Android / Windows
onInit()、onPay、onUserID、onUserToken、onUserName
iOS 专有
configureThirdPartyLogin、onDeviceIdfa
WebGL 专有
onSetHost、onInit(productCode)、onPayOrder
iOS + Android
onGuestLogin、onIsBindPhone、onBindPhone、onDeviceId
iOS + Android + WebGL
onRestoreNonConsumptionProducts
继承 QuickListener(Assets/QuickGameSDK/Scripts/QuickListener.cs),实现抽象方法。原生/宿主以 JSON 字符串调用 public void onXxx(string msg) 重载,基类内部解析后转调你实现的强类型方法
数据类型(ErrorMsg、UserInfo、PayResult)见 5.3*
6.1 全平台公共回调(必须实现)
|
回调 |
参数 |
触发时机 |
|
onInitSuccess |
— |
onInit / onInit(productCode) 成功 |
|
onInitFailed(ErrorMsg) |
errMsg |
初始化失败 |
|
onLoginSuccess(UserInfo) |
uid、token 等 |
onLogin / onGuestLogin 成功 |
|
onLoginFailed(ErrorMsg) |
errMsg |
登录失败或取消 |
|
onLogoutSuccess() |
— |
onLogout 完成 |
|
onPaySuccess(PayResult) |
orderNo、cpOrderNo、extras |
支付成功 |
|
onPayFailed(PayResult) |
code、message |
支付失败 |
|
onPayCancel(PayResult)` |
— | |
用户取消支付 |
6.2 平台相关回调(可选实现)
回调
适用平台
说明
onRestoreSuccess()
iOS / Android / WebGL
onRestoreNonConsumptionProducts 恢复成功
onUserCenterClose()
部分平台
用户中心关闭
onDeviceIdfa()
iOS
设备 IDFA
onDeviceId()
iOS / Android
设备 ID
6.3 回调与 API 对照
调用的 API
可能收到的回调
onInit() / onInit(productCode)
onInitSuccess / onInitFailed
onLogin() / onGuestLogin()
onLoginSuccess / onLoginFailed
onLogout()
onLogoutSuccess
onPay() / onPayOrder()
onPaySuccess / onPayFailed / onPayCancel
onRestoreNonConsumptionProducts()
onRestoreSuccess
菜单:QuickSDK → Settings→ 编辑 Assets/Resources/QKSettings.asset
字段
iOS
Android
WebGL
Windows
productCode
QKSettings/ onInit(code) / 桥接默认
Build 前写入 Manifest
onInit(productCode)
QKSettings
baseUrl
—
写入 StreamingAssets / quickgame_sdk / qg_ipconfig.txt
onSetHost
SDK 请求域名
miniGameChannel
—
—
选择 Channels/<渠道>/QGSDK.js
—
channelCode 等 UI 字段
—
—
—
PC 登录/支付窗体
Unity 脚本接入完成后,必须完成对应原生/宿主配置。详细步骤见后面的分平台操作文档
|
参数 |
获取方式 |
使用位置 |
|
productCode |
QuickGame 后台 |
iOS:QKConnector.mm;Android:QKSettings → Manifest;WebGL:onInit;Windows:QKSettings |
|
baseUrl |
平台运营人员 |
Android:qg_ipconfig.txt;WebGL:onSetHost;Windows:QKSettings |
|
微信 AppId / Secret / Universal Link |
微信开放平台 |
configureThirdPartyLogin、Info.plist |
|
QQ AppId / Universal Link |
QQ 互联 |
同上 |
|
内购商品 ID |
App Store / 后台 |
onPay 的 productId |
|
miniGameChannel |
平台运营人员 |
WebGL:Channels/<渠道>/QGSDK.js |
10.1 参考场景
10.2 建议验收项
项
iOS
Android
WebGL
Windows
Init
onInitSuccess
同左
onSetHost + onInit 后成功
同 iOS
Login
uid/token 非空
同左
同左
同左
上传角色
onUpdateRole 无崩溃
同左
同左
支付前必调
Pay
成功/失败/取消 回调
同左
onPayOrder 回调
同左
渠道
微信/QQ 回调(若已接)
—
微信/支付宝宿主内登录支付
PC 弹窗流程
现象
处理
Editor 下无回调
正常;须真机或对应平台 Player
setListener 后仍无回调
检查 GameObject 名称、Listener 是否挂在该物体上
iOS:JySDKManager.h not found
未找到 releaseSDK;确认 iOS/releaseSDK 或设 UNITY_QUICKGAME_SDK_ROOT 后重新 Build iOS
iOS:jywlNamed / HXTextView 崩溃
UnityFramework 缺少 -ObjC
iOS:Xcode 中 SDK 文件夹红色
确认磁盘存在 Frameworks/QuickGameSDK,重新导出
微信/QQ 无法回调
检查 configureThirdPartyLogin、URL Scheme、Universal Link
Android Build 失败:productCode 为空
在 QuickSDK → Settings 填写 QKSettings
WebGL Build 失败:渠道无效
检查 Channels/
WebGL 初始化无效
是否先 onSetHost 再 onInit(productCode)
Windows 支付无反应
是否先 onUpdateRole;PCSDKUI.exe 是否在 StreamingAssets
|
文件 |
作用 |
|
Plugins/QuickGameSDK/Scripts/QKGame.cs |
全平台 API 入口 |
|
Plugins/QuickGameSDK/Scripts/QuickListener.cs |
回调基类与 JSON 解析 |
|
Plugins/QuickGameSDK/Scripts/QuickGameAndroidBridge.cs |
Android JNI 桥 |
|
Plugins/QuickGameSDK/Scripts/QuickGameWebGLBridge.cs |
WebGL jslib 桥 |
|
Plugins/Android/com/quickgame/unity/QKConnector.java |
Android 原生桥 |
|
Plugins/Windows/Plugins/script/WindowsQGAdapter.cs |
Windows 适配层 |
|
Plugins/QuickGameSDK/Editor/IOSPostProcessBuild.cs |
iOS 导出后自动集成 SDK |
|
Plugins/QuickGameSDK/Editor/QuickGameIOSIntegrationSettings.cs |
iOS 微信/QQ、ReleaseSdkRoot |
|
Plugins/QuickGameSDK/Editor/AndroidPreprocessBuild.cs |
Android Build 前写配置 |
|
Plugins/QuickGameSDK/Editor/AndroidPostGenerateGradle.cs |
Android Gradle 合并 |
|
Plugins/QuickGameSDK/Editor/QuickGameWebGLChannelBuilder.cs |
小游戏渠道 jspre/jslib 构建 |
|
Plugins/QuickGameSDK/Channels/*/QGSDK.js |
小游戏各渠道资源 |
|
Plugins/WebGL/QuickGameWebGL.jslib |
WebGL 原生插件 |
|
Plugins/Windows/Plugins/script/PackageSettings.cs |
QKSettings 字段定义 |
|
Resources/QKSettings.asset |
运行时 / 构建配置 |
|
Plugins/QuickGameSDK/Demo/QuickGameDemoController.cs |
Demo 按钮逻辑 |
|
Plugins/QuickGameSDK/Demo/QuickGameDemoListener.cs |
Demo 回调实现 |
|
iOS/releaseSDK/ |
默认 iOS 原生 SDK 目录 |
CP 游戏代码
↓
QKGame.cs(统一 API,与 iOS 相同)
↓
QuickGameAndroidBridge.cs(C# → Java 反射调用)
↓
QKConnector.java(Unity 桥接层,对接 QGManager)
↓
QuickGame Android SDK(AAR:app-release.aar 等)
↓
UnitySendMessage → QuickListener(回调)
2.1 工程结构(QuickGame_unity)
Android Studio 侧以 Library Module 形式封装,供 Unity 合并 AAR:
QuickGame_unity/ ├── app/ # 主模块,导出 AAR │ ├── libs/ # SDK 本地 jar/aar + unity-classes.jar(compileOnly) │ ├── src/main/ │ │ ├── AndroidManifest.xml # SDK Activity / Provider / meta-data 模板 │ │ └── java/com/qk/game/ │ │ ├── GameApplication.java # Application,调用 QGManager.initMsa │ │ └── MainActivity.java # 继承 QuickUnityPlayerproxyActivity │ └── build.gradle.kts ├── aarlib/ # flatDir 本地 aar(编译用,需同步拷贝到 Unity) └── unity_export/ # exportUnitySdk 任务输出目录
2.2 SDK 依赖接入
本地 AAR/JAR(打进 AAR 或 Unity libs):
Maven 依赖(不会自动打进 AAR,Unity mainTemplate.gradle 需同步声明):
implementation 'org.jetbrains.kotlin:kotlin-stdlib-jdk8:1.7.21' implementation 'androidx.appcompat:appcompat:1.2.0' implementation 'androidx.core:core:1.6.0' implementation 'io.reactivex.rxjava2:rxandroid:2.1.1' implementation 'com.taptap.sdk:tap-login:4.8.2' implementation 'com.taptap.sdk:tap-core:4.8.2' implementation 'com.taptap.sdk:tap-update:4.8.2' implementation 'com.taptap.sdk:tap-review:4.8.2' implementation 'com.google.android.flexbox:flexbox:3.0.0' implementation 'com.tencent.vasdolly:helper:3.0.4'
2.3 导出 AAR 到 Unity
在 Android Studio 工程根目录执行:
./gradlew :app:exportUnitySdk
Assets/Plugins/Android/libs/
桥接类职责:对接 QGManager,通过 UnitySendMessage 回调 Unity QuickListener
|
Java 静态方法 |
对应 QGManager |
Unity 回调 |
|
setListener(name) |
— |
注册 listener GameObject 名 |
|
init() |
QGManager.init(activity, productCode, cb) |
onInitSuccess / onInitFailed |
|
login() |
QGManager.login |
onLoginSuccess / onLoginFailed |
|
loginAsGuest() |
QGManager.slienceLogin |
同上 |
|
userCenter() |
QGManager.showUserCenter |
— |
|
logout() |
QGManager.logout |
onLogoutSuccess |
|
pay(...) |
QGManager.pay |
onPaySuccess / onPayFailed |
|
updateRole(...) |
QGManager.setGameRoleInfo |
— |
|
bindPhone() |
QGManager.showBind |
— |
productCode 读取(防 Float 精度丢失):
Manifest 中写入 code:65195142454045007867755657815091 前缀格式;Java 侧 readProductCode() 去掉 code: 前缀后再传给 SDK
2.5 AndroidManifest 模板(AS 侧完整版)
AS 工程 app/src/main/AndroidManifest.xml 包含 SDK 所需的完整声明,Unity 侧需按需合并,至少包括:
权限:INTERNET、READ_PHONE_STATE、REQUEST_INSTALL_PACKAGES 等
queries:微信、支付宝、TapTap 等包名
Application:com.qk.game.GameApplication(QGManager.initMsa)
MainActivity:com.qk.game.MainActivity(继承 Unity 代理 Activity)+ MAIN/LAUNCHER
SDK Activity:LoginActivity、PayActivity、DownloadActivity 等(缺少会导致 ClassNotFoundException)
Provider:QGFileProvider
渠道 meta-data:QQ_APP_ID、WX_APP_ID、TAP_ID 等(按 CP 实际参数替换 QK0 占位符)
3. 导入资源到 Unity 工程
3.1 目录清单
将以下内容放入 Unity 工程 Assets/:
Assets/
├── QuickGameSDK/
│ ├── Scripts/
│ │ ├── QKGame.cs # 统一 API 入口(CP 只调此类)
│ │ ├── QuickListener.cs # 回调基类
│ │ └── QuickGameAndroidBridge.cs # Android C# 桥接
│ ├── Editor/
│ │ ├── AndroidPreprocessBuild.cs # Build 前写 productCode / baseUrl
│ │ └── AndroidPostGenerateGradle.cs # Gradle 生成后拷贝 QKConnector.java
│ └── Demo/ # 可选 Demo 场景
│ ├── QuickGameDemoController.cs
│ └── QuickGameDemoListener.cs
├── Plugins/
│ ├── Android/
│ │ ├── AndroidManifest.xml # 自定义 Manifest
│ │ ├── mainTemplate.gradle # unityLibrary 依赖模板
│ │ ├── baseProjectTemplate.gradle # AGP 7.4.2 + R8
│ │ ├── gradleTemplate.properties
│ │ ├── com/quickgame/unity/
│ │ │ └── QKConnector.java # 桥接源码(Build 后拷贝到 Gradle 工程)
│ │ └── libs/
│ │ ├── app-release.aar # SDK 主 AAR
│ │ ├── unity-classes.jar # Unity 运行时(implementation,非 compileOnly)
│ │ └── *.aar # 其他依赖 AAR
│ └── JsonNet/ # Newtonsoft.Json(QuickListener 解析 JSON)
├── QuickGameSDK/Windows/Plugins/script/
│ └── PackageSettings.cs # QKSettings ScriptableObject 定义
├── QuickGameSDK/Windows/Editor/
│ └── PackageSettingsWindow.cs # QuickSDK → Settings 菜单
└── Resources/
└── QKSettings.asset # 运行时/构建配置
Edit → Project Settings → Player → Android → Publishing Settings:
|
选项 |
值 |
|
Custom Main Manifest |
✅ |
|
Custom Main Gradle Template |
✅ |
|
Custom Base Gradle Template |
✅ |
|
Custom Gradle Properties Template |
✅ |
3.3 Gradle 模板要点
mainTemplate.gradle:
使用 apply plugin: 'com.android.library'(Unity 2022.3 导出为 library 模式)
implementation files('libs/unity-classes.jar') — 必须是 implementation,否则运行时找不到 UnityPlayer
aaptOptions.noCompress 使用 **BUILTIN_NOCOMPRESS** + unityStreamingAssets.tokenize(', ')(不要用旧版 aaptOptions { noCompress ... } 单行写法)
Maven 依赖与 AS 工程保持一致
注释中不要写 **DEPS** 字样(Unity 模板替换会误伤注释)
baseProjectTemplate.gradle:
classpath 'com.android.tools:r8:8.3.37' id 'com.android.application' version '7.4.2' apply false id 'com.android.library' version '7.4.2' apply false
Unity 自定义 Manifest 位于 Assets/Plugins/Android/AndroidManifest.xml,需包含:
...
Build 前 AndroidPreprocessBuild 会将 PLACEHOLDER_PRODUCT_CODE 替换为 QKSettings 中的 productCode(带 code: 前缀)
SDK Activity 声明: 若运行时出现 LoginActivity / PayActivity 等 ActivityNotFoundException,需从 AS 工程 Manifest 补全对应
3.5 QKConnector.java 编译机制
Unity 2022.3 导出 Gradle 时,Plugins/Android/*.java 不一定自动参与 unityLibrary 编译
已通过 AndroidPostGenerateGradle.cs 解决:Gradle 工程生成后,自动将 QKConnector.java 拷贝到:
<导出目录>/unityLibrary/src/main/java/com/quickgame/unity/QKConnector.java
4.1 QKSettings 配置
菜单:QuickSDK → Settings
字段
Android 用途
示例
baseUrl
Build 前写入 StreamingAssets/quickgame_sdk/qg_ipconfig.txt
https://qkgamesdk.quickapi.net
productCode
Build 前写入 Manifest
QKproductCode 65195142454045007867755657815091
channelCode
子渠道标识(按 SDK 文档配置)
cps001,cps002
配置文件路径:Assets/Resources/QKSettings.asset
Build 前自动处理(AndroidPreprocessBuild):
1. 校验 baseUrl、productCode 非空(为空则 Build 失败)
2. 替换 Manifest 中 QKproductCode 值
3. 生成 Assets/StreamingAssets/quickgame_sdk/qg_ipconfig.txt
4.2 CP 接入代码
4.2.1. 继承 QuickListener
using quickgame;
using UnityEngine;
public class MyGameListener : QuickListener
{
public override void onInitSuccess() { Debug.Log("Init OK"); }
public override void onInitFailed(ErrorMsg message) { Debug.Log("Init Fail: " + message.errMsg); }
public override void onLoginSuccess(UserInfo userInfo) { Debug.Log("Login: " + userInfo.uid); }
public override void onLoginFailed(ErrorMsg errMsg) { Debug.Log("Login Fail: " + errMsg.errMsg); }
public override void onLogoutSuccess() { }
public override void onPaySuccess(PayResult r) { }
public override void onPayFailed(PayResult r) { }
public override void onPayCancel(PayResult r) { }
}
// Awake 中(必须在 init 之前) QKGame.setListener(myListenerComponent); // Android:无参 init,productCode 已由 QKSettings + Manifest 注入 QKGame.onInit(); QKGame.onLogin(); // 支付(Android 使用 onPay,不是 WebGL 的 onPayOrder) QKGame.onPay(productId, productName, amount, orderNo, callbackUrl, extrasParams); // 上报角色(支付前建议先调用) QKGame.onUpdateRole(roleId, roleName, serverId, serverName, roleLevel, vipLevel, rolePower); QKGame.onLogout();
4.2.3. Demo 参考
场景:QuickGameDemo.unity
脚本:QuickGameDemoController.cs / QuickGameDemoListener.cs
Android Build 下按钮流程:Init → Login → Pay → Logout(与 iOS 相同,无 WebGL 的 SetHost 步骤)
4.3 回调 JSON 约定
原生通过 UnityPlayer.UnitySendMessage(gameObjectName, method, jsonString) 调用 QuickListener 的 字符串重载(QuickListener.cs 内自动解析 JSON)
登录成功:
{
"userId": "123456",
"userToken": "xxx",
"userName": "player1",
"msg": "success",
"timeleft": "-1",
"isNewUser": "0"
}
{ "msg": "错误描述" }
{
"code": "0",
"message": "success",
"orderNo": "SDK订单号",
"cpOrderNo": "游戏订单号",
"extras": "透传参数"
}
4.4 调用链路(代码层)
QKGame.onInit()
→ QuickGameAndroidBridge.Init()
→ AndroidJavaClass("com.quickgame.unity.QKConnector").CallStatic("init")
→ QGManager.init(activity, productCode, callback)
→ UnitySendMessage("ListenerGO", "onInitSuccess", "")
5.1 构建步骤
1. QuickSDK → Settings 填写 baseUrl、productCode
2. File → Build Settings → Android
3. 选择 Export Project 或直接 Build And Run
4. 首次 Build 建议在 Unity Console 确认日志:
[QuickGame] Android 预处理完成:productCode=...
[QuickGame] 已拷贝 QKConnector.java -> ...
5.2 验收清单
步骤
操作
预期
Init
QKGame.onInit()
onInitSuccess
Login
QKGame.onLogin()
onLoginSuccess,含 userId / userToken
Guest
QKGame.onGuestLogin()
静默登录回调
Pay
QKGame.onPay(...)
onPaySuccess 或 onPayFailed,含 orderNo / cpOrderNo
Role
QKGame.onUpdateRole(...)
无崩溃,SDK 收到角色信息
Logout
QKGame.onLogout()
onLogoutSuccess
浮球
登录后进游戏
Resume 显示浮球,Pause 隐藏
5.3 日志关键字
adb logcat | grep -E "QKConnector|QGManager|QuickGame"
6.1 配置相关
问题
原因
处理
productCode 变成错误数字
纯数字 meta-data 被 Android 解析为 Float
Manifest 使用 code: 前缀 + Java readMetaDataString
Init 报 productCode 为空
QKSettings 未填或 Build 预处理未执行
检查 Settings + Console 预处理日志
baseUrl 未生效
未生成 qg_ipconfig.txt
确认 StreamingAssets/quickgame_sdk/qg_ipconfig.txt 存在
6.2 编译 / Gradle
问题
原因
处理
UnityPlayer / IUnityPlayerLifecycleEvents 找不到
unity-classes.jar 为 compileOnly
改为 implementation files('libs/unity-classes.jar')
Gradle 注释语法错误
注释中含 **DEPS** 被 Unity 替换
注释改用其他写法
AAR 重复类
fileTree + DEPS 双重引入
去掉 fileTree('*.aar'),仅保留 Unity DEPS 机制
AGP / JDK 版本不匹配
Unity 2022 需 AGP 7.x + JDK 17
检查 External Tools JDK 与 baseProjectTemplate
6.3 运行时
QKConnector
ClassNotFoundException
LoginActivity
ClassNotFoundException
问题
原因
处理
java 未参与 unityLibrary 编译
确认 AndroidPostGenerateGradle 拷贝成功
Manifest 未声明 SDK Activity
从 AS 工程 Manifest 补全 Activity
桌面无应用图标
MainActivity 缺少 LAUNCHER
Manifest 为 MainActivity 添加 MAIN/LAUNCHER
Manifest 合并冲突
configChanges / screenOrientation 与 AAR 冲突
使用 tools:replace 显式覆盖
回调无响应
未 setListener 或 GameObject 名错误
Awake 中先 QKGame.setListener(this),物体名与 SendMessage 一致
Init 成功但 Listener 收不到
init 早于 setListener
QKConnector 已缓存 init 状态,setListener 后会补发
6.4 与其他平台共存
QKGame.cs / QuickListener.cs 为全平台公共 API,Android 改动不影响 iOS / Windows / WebGL 分支
Android 支付用 onPay();WebGL 小游戏用 onPayOrder()
Android init 无参;WebGL 需 onSetHost + onInit(productCode)
6.5 SDK 升级流程
使用新版 SDK AAR → 替换 Assets/Plugins/Android/libs/
对比 AS 工程 Manifest diff,补全新增 Activity / Provider / meta-data
若 QGManager API 有变,同步修改 QKConnector.java
重新 Export AAR(如有 AS 工程变更)→ Unity Build 真机回归
当 CP 需要接入 SDK 新增的 QGManager 能力时,需按 「Java 桥接 → C# Bridge → QKGame 对外 API →(可选)QuickListener 回调」 四层逐层暴露
本模块以 QGManager.getChannelId() 为例(同步返回值),并补充 异步回调 类接口的通用写法
7.1 先判断接口类型
类型
SDK 特征
Unity 暴露方式
现有参考
同步查询
public static String/Bool/Int xxx(),立即返回
Java 静态方法 → C# 直接 CallStatic
getUID() → onUserID()
异步操作
带 QGCallBack 或回调参数
Java 调 SDK 后在回调里 UnitySendMessage
login() → onLoginSuccess
UI 操作
需 Activity、弹 SDK 界面
Java 内 runOnUiThread + 可选回调
showUserCenter()、pay()
getChannelId() 属于 同步查询,与 userId() / deviceId() 同一模式,不需要改 QuickListener(除非 CP 希望用事件推送而非主动查询)
7.2 扩展链路总览

异步接口在 QKConnector 与 QuickListener 之间多一条 UnitySendMessage 回路(见 7.5)
7.3 示例一:同步接口 getChannelId()(完整四步)
Step 0:在 QuickGame_unity 中确认 SDK API(可选但推荐)
在 Android Studio 工程引入最新 AAR 后,可先写一段原生测试代码验证 API 可用(不必提交,仅用于确认签名与返回值):
// QuickGame_unity/app/src/main/java/com/qk/game/MainActivity.java(临时验证)
Log.d("Test", "channelId=" + com.quickgamesdk.QGManager.getChannelId());
文件:Assets/Plugins/Android/com/quickgame/unity/QKConnector.java
在现有同步方法(如 userId())附近新增:
/** 获取 SDK 渠道 ID,对应 QGManager.getChannelId() */
public static String channelId() {
return safeString(QGManager.getChannelId());
}
文件:Assets/QuickGameSDK/Scripts/QuickGameAndroidBridge.cs
public static string ChannelId()
{
return Bridge.CallStatic("channelId");
}
public static string ChannelId() { return ""; }
Step 3:QKGame.cs — 对外统一 API
文件:Assets/QuickGameSDK/Scripts/QKGame.cs
参照 onUserID() 增加 Android 分支:
///获取 SDK 渠道 ID(Android 登录后可用;其他平台返回空串)。 public static string onChannelId() { #if UNITY_ANDROID && !UNITY_EDITOR return QuickGameAndroidBridge.ChannelId(); #elif UNITY_STANDALONE_WIN return quicksdk.QuickSDK.getInstance().getChannelId(); // Windows 若已有同名能力可一并暴露 #else return ""; #endif }
Step 4:CP 侧调用与验收
// 建议在 onInitSuccess / onLoginSuccess 之后调用
string channelId = QKGame.onChannelId();
Debug.Log("[CP] channelId=" + channelId);
adb logcat | grep -E "channelId|QKConnector"
文件
动作
QKConnector.java
新增 public static 方法,内部调 QGManager.xxx()
QuickGameAndroidBridge.cs
新增 CallStatic
QKGame.cs
新增 public static API,#if UNITY_ANDROID 分支
Demo(可选)
QuickGameDemoController 增加测试按钮
文档
更新CP 接入文档中的 API 表
无需修改: AndroidPostGenerateGradle.cs(仍拷贝整个 QKConnector.java)、QuickListener.cs(纯同步返回时)
7.5 示例二:异步接口扩展(带 Unity 回调)
若新接口形如 QGManager.doSomething(Activity, QGCallBack callback),需增加 UnitySendMessage → QuickListener 回路。以虚构的 queryChannelInfo 为例:
Step 1:QKConnector.java
public static void queryChannelInfo() {
runOnUiThread(new Runnable() {
@Override
public void run() {
Activity activity = UnityPlayer.currentActivity;
if (activity == null) {
sendQueryChannelFailed("Unity activity is null");
return;
}
QGManager.queryChannelInfo(activity, new QGCallBack() {
@Override
public void onSuccess() {
try {
JSONObject json = new JSONObject();
json.put("channelId", safeString(QGManager.getChannelId()));
json.put("msg", "success");
sendMessage("onQueryChannelSuccess", json.toString());
} catch (Exception e) {
sendQueryChannelFailed(e.getMessage());
}
}
@Override
public void onFailed(String msg) {
sendQueryChannelFailed(msg);
}
});
}
});
}
private static void sendQueryChannelFailed(String msg) {
sendMessage("onQueryChannelFailed", "{"msg":"" + escapeJson(msg) + ""}");
}
public static void QueryChannelInfo()
{
Bridge.CallStatic("queryChannelInfo");
}
public static void onQueryChannelInfo()
{
#if UNITY_ANDROID && !UNITY_EDITOR
QuickGameAndroidBridge.QueryChannelInfo();
#elif UNITY_EDITOR
Debug.Log("[QKGame] onQueryChannelInfo (Editor)");
#endif
}
// 1) 抽象方法(CP 必须实现)
public abstract void onQueryChannelSuccess(string channelId);
public abstract void onQueryChannelFailed(ErrorMsg errMsg);
// 2) 字符串重载(Java SendMessage 入口,解析 JSON)
public void onQueryChannelSuccess(string msg)
{
var data = JObject.Parse(msg);
onQueryChannelSuccess(data["channelId"]?.Value() ?? "");
}
public void onQueryChannelFailed(string msg)
{
var data = JObject.Parse(msg);
var err = new ErrorMsg { errMsg = data["msg"]?.Value() ?? "" };
onQueryChannelFailed(err);
}
Step 5:CP 实现 Listener
public override void onQueryChannelSuccess(string channelId)
{
Debug.Log("[CP] query channel ok: " + channelId);
}
public override void onQueryChannelFailed(ErrorMsg errMsg)
{
Debug.Log("[CP] query channel fail: " + errMsg.errMsg);
}
// 触发
QKGame.onQueryChannelInfo();
文件
动作
QKConnector.java
UI 线程调 SDK;成功/失败 sendMessage(method, json)
QuickGameAndroidBridge.cs
CallStatic 触发
QKGame.cs
对外 public static void onXxx()
QuickListener.cs
新增 abstract + string 重载(JSON 解析)
CP Listener 子类
实现新 abstract 方法
真机验收
成功/失败路径各测一遍
7.7 常见问题
#if UNITY_ANDROID &&
!UNITY_EDITOR
问题
原因
处理
CallStatic 报 method not found
Java 方法名与 C# 字符串不一致
核对大小写,Java 为 channelId 则 C# 传 "channelId"
返回空串
未 init / 未 login 就查询
文档注明调用时机;Java 侧打 Log 辅助排查
异步回调进不来
Listener 未注册或方法名不匹配
SendMessage 的方法名须与 QuickListener 的 public void onXxx(string msg) 完全一致
Editor 下无法测试
正常;仅真机或 Android Player 验证
改 Java 后未生效
未重新 Build
重新 Android Build,确认 Console 有拷贝 QKConnector.java 日志
7.8 与 QuickGame_unity 的协作关系
QuickGame_unity(AS) unitybridgecn(Unity)
───────────────────── ────────────────────
商务 SDK AAR 接入 QKConnector.java 桥接 QGManager
exportUnitySdk → libs/*.aar ──拷贝──► Plugins/Android/libs/
Manifest 模板(Activity 等) ──合并──► Plugins/Android/AndroidManifest.xml
QuickGameAndroidBridge.cs
QKGame.cs → CP 调用
分工建议:
SDK 版本升级、AAR 导出、Manifest 大段合并 → 在 QuickGame_unity 完成
Unity 可调用的具体 API、回调 JSON 格式 → 在 unitybridgecn 的 QKConnector + QKGame 完成
每新增一个 CP 可见接口,至少改动 3 个文件(同步)或 4~5 个文件(异步含 Listener)
相关文件速查
|
类型 |
路径 |
|
C# API |
Assets/QuickGameSDK/Scripts/QKGame.cs |
|
C# Bridge |
Assets/QuickGameSDK/Scripts/QuickGameAndroidBridge.cs |
|
回调基类 |
Assets/QuickGameSDK/Scripts/QuickListener.cs |
|
Java Bridge |
Assets/Plugins/Android/com/quickgame/unity/QKConnector.java |
|
Manifest |
Assets/Plugins/Android/AndroidManifest.xml |
|
Gradle 模板 |
Assets/Plugins/Android/mainTemplate.gradle |
|
Build 预处理 |
Assets/QuickGameSDK/Editor/AndroidPreprocessBuild.cs |
|
Gradle 后处理 |
Assets/QuickGameSDK/Editor/AndroidPostGenerateGradle.cs |
|
配置 |
Assets/Resources/QKSettings.asset |
|
Settings 窗口 |
Assets/QuickGameSDK/Windows/Editor/PackageSettingsWindow.cs |
|
SDK AAR |
Assets/Plugins/Android/libs/app-release.aar |
|
AS 导出源 |
QuickGame_unity/app/build.gradle.kts |
# 在 QuickGame_unity 工程根目录
./gradlew :app:exportUnitySdk # 拷贝到 Unity cp unity_export/*.aar/Assets/Plugins/Android/libs/ cp unity_export/aarlib/*.aar /Assets/Plugins/Android/libs/
Unity 接口以 Assets/QuickGameSDK/Scripts/ 为准;原生 SDK 目录默认 iOS/releaseSDK
1.1 前提
项
说明
Unity 侧
实现 QuickListener,调用 QKGame.setListener、QKGame.startSdk 等 API
Build 产物
Xcode 工程(.xcodeproj),非 IPA
Xcode
配置签名、真机运行;
验证环境
须 iOS 真机;Editor Play 不调用原生 SDK
1.2 标准接入流程
采用 路径 A(自动集成)。工程准备可使用 unitybridgecn 参考工程,或将发版资源集成至自有工程(文件清单见 2.3)
|
步骤 |
操作 |
|
1 |
向运营人员获取 releaseSDK、productCode;按需获取微信/QQ 参数、内购商品 ID |
|
2 |
集成 Unity 脚本、Newtonsoft.Json.dll、IOSPostProcessBuild.cs;解压 iOS/releaseSDK(含 JySDK.framework) |
|
3 |
QuickSDK → Settings 配置 QKSettings;Player Settings → iOS 设置 Bundle ID |
|
4 |
实现 QuickListener;Awake 中 setListener;合适时机调用 startSdk |
|
5 |
Build Settings → iOS → Build |
|
6 |
Xcode 配置签名,真机 Run |
1.3 接入方式
路径 A:自动集成(推荐)
路径 B:手动集成
条件
含 IOSPostProcessBuild.cs 且配置 releaseSDK
未使用导出脚本
Unity Build 后
自动集成 SDK、桥接、链接参数、微信/QQ 配置
仅生成基础 Xcode 工程
Xcode 工作
签名与真机运行
手动集成 SDK 与桥接
2.1 参数配置
配置项
获取方
配置位置
说明
productCode
QuickGame 后台
QuickSDK → Settings 写入 QKSettings.asset;导出时 PostProcess 写入 QKConnector 的 kQKDefaultProductCode
运行时推荐 QKGame.startSdk();亦可 onInit(productCode)
Bundle ID
CP 自有
Unity Player Settings → iOS → Bundle Identifier
须与苹果开发者后台、描述文件、微信/QQ 应用配置一致
内购商品 ID
App Store Connect
onPayOrder 的 goodsId(或 onPay 的 productId)
与 App Store Connect 商品 ID 一致
2.2 Unity 工程内(CP 代码与资源)
配置项
配置位置
说明
回调监听
继承 QuickListener,Awake 最早调用 QKGame.setListener(this)
GameObject 名称固定,勿运行时改名
初始化
QKGame.startSdk()(推荐)
自动读 QKSettings、配置微信/QQ、再 onInit;收到 onInitSuccess 后再 onLogin
微信/QQ(运行时)
QKSettings 中 wxAppId 等字段,由 startSdk() 自动 configureThirdPartyLogin
亦可手动调用 configureThirdPartyLogin(须在 onInit 前)
微信/QQ(导出 plist)
QuickGameIOSIntegrationSettings.cs
修改 WxAppId、WxUniversalLink、QqAppId 等;正式包勿用 Demo 默认值
releaseSDK 路径
ReleaseSdkRoot(默认 iOS/releaseSDK)→ UNITY_QUICKGAME_SDK_ROOT → ../quickgame/releaseSDK
须含 iOS/SDK/JySDK.framework
推荐代码(无平台 #if):
void Awake() => QKGame.setListener(this);
public void StartSdk()
{
QKGame.startSdk(); // 读 QKSettings(含 productCode、微信/QQ)
// 或覆盖:QKGame.startSdk("你的productCode", null);
}
支付推荐全平台统一:
QKGame.onPayOrder(new QKGame.QKPayOrderInfo {
cpOrderNo = "...", subject = "元宝", goodsId = "com.xxx.item1",
amount = "6", /* 其余角色字段见总文档 §6.2.3 */
});
2.3 拷贝到自有 Unity 工程(首次集成)
必选
Assets/QuickGameSDK/Scripts/ # QKGame.cs、QuickListener.cs 等 Assets/Plugins/JsonNet/Newtonsoft.Json.dll
iOS 强烈建议(自动集成,免 Xcode 手拖 SDK)
Assets/QuickGameSDK/Editor/IOSPostProcessBuild.cs Assets/QuickGameSDK/Editor/QuickGameIOSIntegrationSettings.cs iOS/releaseSDK/ # 默认原生 SDK 目录(发版包解压)
推荐:不放入 Assets/Plugins/iOS/;Build 时由 IOSPostProcessBuild 从 releaseSDK/Unity3d/1. Xcode/ 拷贝到导出工程 Libraries/QuickGame/
手动路径 B:若不用 PostProcess,须自行将桥接文件放入 Assets/Plugins/iOS/ 或导出后拖入 Xcode
发版包等价路径:releaseSDK/Unity3d/1. Xcode/、releaseSDK/Unity3d/2. U3D/
2.4 本机证书与签名(无法由 Unity 生成)
配置项
操作
Apple 开发者账号
Xcode → Settings → Accounts 登录
证书
安装 Development / Distribution 证书
描述文件
下载与 Bundle ID 匹配的 Profile;参考工程默认名 DevAny
Team / Profile 名写入工程
环境变量 UNITY_IOS_DEVELOPMENT_TEAM、UNITY_IOS_PROVISIONING_PROFILE,或改 IOSPostProcessBuild.cs 中 DefaultTeamId / DefaultProvisioningProfile
# 从终端启动 Unity 前设置(Hub 直接点开 Unity 读不到终端环境变量时,可用 launchctl / 脚本包装) export UNITY_IOS_DEVELOPMENT_TEAM=你的TeamId export UNITY_IOS_PROVISIONING_PROFILE=你的描述文件名 export UNITY_QUICKGAME_SDK_ROOT=/path/to/releaseSDK
平台
配置
微信开放平台
iOS 应用 AppId、Universal Link 域名
微信
服务器部署 apple-app-site-association(与 WxUniversalLink 域名一致)
QQ 互联
iOS AppId、Universal Link(若使用)
与 Unity 一致
configureThirdPartyLogin 与 QuickGameIOSIntegrationSettings 中参数须与后台完全一致
2.6 Info.plist 隐私描述(须 CP 按游戏补充)
PostProcess 不会自动写入以下键;按 SDK / 苹果审核要求在 Unity Player Settings → iOS → Other Settings 或导出后 Info.plist 添加:
Key
何时需要
NSPhotoLibraryUsageDescription
相册选图
NSCameraUsageDescription
相机
NSMicrophoneUsageDescription
麦克风
NSUserTrackingUsageDescription
ATT 追踪(若接广告归因)
NSLocationWhenInUseUsageDescription
定位(若 SDK/游戏使用)
2.7 出包与验证
步骤
说明
Unity Build iOS
产出 Xcode 工程,不是 IPA
Xcode 真机 Run
日常联调;JySDK 为真机库,模拟器无法完整验证
Archive → 导出 IPA
内测 / 上架
1. 配置 QKSettings
2. 打开 Assets/Scenes/QuickGameDemo.unity
3. Build iOS → Xcode 真机 Run → 执行 Demo 按钮流程
4.1 查找顺序(IOSPostProcessBuild.ResolveSdkRoot)
1. QuickGameIOSIntegrationSettings.ReleaseSdkRoot(默认 iOS/releaseSDK,相对 Unity 工程根目录)
2. 环境变量 UNITY_QUICKGAME_SDK_ROOT
3. 工程内 <工程>/iOS/releaseSDK
4. 同级目录 ../quickgame/releaseSDK(研发联调兜底)
解析失败时 Console 会打印已尝试的完整路径列表
4.2 环境变量(可选)
变量
作用
默认
—
releaseSDK 根目录(代码常量)
ReleaseSdkRoot = "iOS/releaseSDK"
UNITY_QUICKGAME_SDK_ROOT
覆盖 SDK 路径
见 4.1 顺序
UNITY_IOS_DEVELOPMENT_TEAM
签名 Team ID
X29G7GACDM
UNITY_IOS_PROVISIONING_PROFILE
描述文件名称
DevAny
使用参考工程或已拷贝 IOSPostProcessBuild.cs 时,每次 Build iOS 后自动执行,一般无需在 Xcode 重复操作:
|
自动项 |
说明 |
|
拷贝 releaseSDK/iOS/SDK/* |
→ Frameworks/QuickGameSDK/ |
|
链接 JySDK.framework、.a |
UnityFramework Target |
|
拷贝 .bundle |
Unity-iPhone Target |
|
Other Linker Flags -ObjC |
UnityFramework + Unity-iPhone |
|
拷贝 QKConnector.mm |
从 releaseSDK/Unity3d/1. Xcode/(若存在) |
|
kQKDefaultProductCode |
若存在 QKSettings.productCode,写入导出工程内 QKConnector.mm |
|
微信/QQ URL Scheme |
Info.plist |
|
LSApplicationQueriesSchemes |
Info.plist |
|
URL / Universal Link |
补丁 UnityAppController.mm |
|
Team / Profile 名称 |
project.pbxproj |
若报 'JySDK/JySDKManager.h' file not found:未找到 releaseSDK → 确认 iOS/releaseSDK 存在或设置 UNITY_QUICKGAME_SDK_ROOT 后重新 Build iOS(只改 Unity 不会更新已导出的 Xcode 目录)
仅当 未 使用 IOSPostProcessBuild 时按下列步骤在 Xcode 操作
6.1 桥接文件
将以下文件加入工程(Unity 导出后通常在 Libraries/Plugins/iOS/ 或自行放在 Libraries/QuickGame/):
QKConnector.h / QKConnector.mm
QuickGameLifecycle.h / QuickGameLifecycle.mm
来源:Assets/Plugins/iOS/ 或 releaseSDK/Unity3d/1. Xcode/
6.2 原生 SDK
将 releaseSDK/iOS/SDK/ 下 framework / .a / .bundle 拖入 Xcode
Unity 2019.3+:.framework、.a → UnityFramework;.bundle → Unity-iPhone
UnityFramework → Build Settings → Other Linker Flags 添加 -ObjC
6.3 productCode
编辑 QKConnector.mm 中 kQKDefaultProductCode(与 QuickGame 后台一致);或在 Unity 配置 QKSettings 后重新 Build iOS 由 PostProcess 写入
6.4 微信 / QQ
Unity:configureThirdPartyLogin(见 2.2)
Xcode Info.plist 手动添加:
CFBundleURLTypes → CFBundleURLSchemes:wx你的AppId、tencent你的QQAppId
LSApplicationQueriesSchemes:weixin、weixinULAPI、mqq、mqqopensdkapi 等
UnityAppController.mm(对照 releaseSDK/iOS/Demo/AppDelegate.m):
#import "QuickGameLifecycle.h"
// application:openURL:options: 内、转发给 Unity 之前:
if (QuickGameForwardOpenURL(app, url, options))
return YES;
// application:continueUserActivity:restorationHandler: 内:
if (QuickGameForwardContinueUserActivity(application, userActivity, restorationHandler))
return YES;
6.5 签名
在 Xcode 为 Unity-iPhone 选择 Team、Provisioning Profile;或使用与 PostProcess 相同的 Manual 签名项
现象
处理
Build Unknown 0 秒、Xcode 目录为空
Unity Editor 脚本编译失败;修 Console 红字(如 IOSPostProcessBuild.cs API 不兼容)后重导
JySDK/JySDKManager.h not found
将 SDK 放到 iOS/releaseSDK 或设置 UNITY_QUICKGAME_SDK_ROOT,重新 Build iOS
jywlNamed / HXTextView 崩溃
UnityFramework 缺 -ObjC;确认 PostProcess 已执行或手动添加
缺少证书 / provisioning profile
本机安装证书与描述文件
Unity 无登录回调
未 setListener 或 Listener 物体名与原生不一致
链接 QKInit 失败
未加入 QKConnector.mm
微信/QQ 授权后无回调
检查2.5 后台与 Universal Link;Info.plist Scheme;UnityAppController 转发
Editor Play 无 SDK
正常;必须真机 Build
想要 IPA
Unity 只出 Xcode 工程;须 Xcode Archive 或 CI
文件
作用
Assets/QuickGameSDK/Scripts/QKGame.cs
Unity API
Assets/QuickGameSDK/Editor/IOSPostProcessBuild.cs
导出后自动集成 SDK、桥接、签名
Assets/QuickGameSDK/Editor/QuickGameIOSIntegrationSettings.cs
ReleaseSdkRoot、微信/QQ 默认参数
Assets/QuickGameSDK/Demo/QuickGameDemoController.cs
参考 Demo
iOS/releaseSDK/
默认原生 SDK 目录
releaseSDK/Unity3d/1. Xcode/QKConnector.*
桥接源(Build 时拷贝)
releaseSDK/Unity3d/1. Xcode/QuickGameLifecycle.*
URL 回调转发源
releaseSDK/iOS/Demo/AppDelegate.m
原生 Demo 对照
架构概览
CP 游戏代码
↓
QKGame.cs(统一 API)
↓
QuickGameWebGLBridge.cs(C# → jslib DllImport)
↓
QuickGameWebGL.jslib(mergeInto,转发 QuickGameJS.dispatch)
↓
QuickGameWebGLBootstrap.jspre(构建时生成,内联 QGSDK.js + QuickGameJS 适配层)
↓
QGManager(商务 QGSDK.js,wx / ali 等渠道版)
↓
SendMessage → QuickListener(回调)
1.1 目录结构
每个小游戏渠道对应一个目录,内含平台运营人员提供的 QGSDK.js:
Assets/QuickGameSDK/Channels/
├── wx/
│ └── QGSDK.js # 微信小游戏 SDK
└── ali/
└── QGSDK.js # 支付宝小游戏 SDK
1.2 QGSDK.js 格式要求
文件末尾须包含导出标记(构建脚本用于识别标准 QGSDK 源文件):
module.exports.QGManager = QGManager;
构建时 QuickGameWebGLChannelBuilder 会:
1. 去掉上述 module.exports 行
2. 将 QGSDK 主体缩进后嵌入 IIFE
3. 追加 QuickGameJS 适配层(dispatch / SendMessage)
4. 生成 QuickGameWebGLBootstrap.jspre
1.3 新增渠道
在 Assets/QuickGameSDK/Channels/ 下新建目录,如 tt(抖音)
放入运营人员提供的 QGSDK.js
QuickSDK → Settings 中即可在下拉列表看到新渠道
2.1 目录清单
Assets/
├── QuickGameSDK/
│ ├── Scripts/
│ │ ├── QKGame.cs # CP 统一 API
│ │ ├── QuickListener.cs # 回调基类
│ │ └── QuickGameWebGLBridge.cs # WebGL C# 桥接
│ ├── Editor/
│ │ └── QuickGameWebGLChannelBuilder.cs # 渠道构建 + WebGLPreprocessBuild
│ ├── Channels/
│ │ ├── wx/QGSDK.js
│ │ └── ali/QGSDK.js
│ └── Demo/ # 可选
├── Plugins/
│ ├── WebGL/
│ │ ├── QuickGameWebGL.jslib # 自动生成(可入库)
│ │ └── QuickGameWebGLBootstrap.jspre # 自动生成(.gitignore 忽略)
│ └── JsonNet/ # Newtonsoft.Json
├── QuickGameSDK/Windows/Plugins/script/
│ └── PackageSettings.cs # QKSettings 字段定义
├── QuickGameSDK/Windows/Editor/
│ └── PackageSettingsWindow.cs # QuickSDK → Settings
└── Resources/
└── QKSettings.asset # 运行时 / 构建配置
2.2 自动生成文件说明
文件
生成时机
是否入库
QuickGameWebGLBootstrap.jspre
Rebuild / WebGL Build 前
通常 .gitignore 忽略,拉代码后需 Rebuild
QuickGameWebGL.jslib
同上
建议入库,保证未 Rebuild 时结构正确
首次拉工程或切换渠道后,在 Unity 菜单执行:
QuickSDK → Settings → Rebuild WebGL Bridge (jspre/jslib)
或直接执行 WebGL Build(构建前会自动 Rebuild)
菜单:QuickSDK → Settings
|
字段 |
用途 |
对应 JS |
|
baseUrl |
SDK 服务器地址 |
QGManager.setHost(host),CP 调用 QKGame.onSetHost(baseUrl) |
|
productCode |
产品码(32 位) |
QGManager.init(productCode, cb),CP 调用 QKGame.onInit(productCode) |
|
miniGameChannel |
构建渠道 |
选择内联 Channels/ |
4.1 继承 QuickListener
using quickgame;
using UnityEngine;
public class MyGameListener : QuickListener
{
public override void onInitSuccess() { Debug.Log("Init OK"); }
public override void onInitFailed(ErrorMsg message) { Debug.Log("Init Fail: " + message.errMsg); }
public override void onLoginSuccess(UserInfo userInfo) { Debug.Log("Login: " + userInfo.uid); }
public override void onLoginFailed(ErrorMsg errMsg) { Debug.Log("Login Fail: " + errMsg.errMsg); }
public override void onLogoutSuccess() { }
public override void onPaySuccess(PayResult r) { Debug.Log("Pay OK: " + r.cpOrderNo); }
public override void onPayFailed(PayResult r) { Debug.Log("Pay Fail: " + r.message); }
public override void onPayCancel(PayResult r) { }
}
4.2 标准调用顺序(WebGL 专用)
void Start()
{
// 1. 注册回调(Awake 中亦可,必须在 init 之前)
QKGame.setListener(myListener);
// 2. 从 QKSettings 读取(或直接写死测试值)
var settings = Resources.Load("QKSettings");
string host = settings.baseUrl;
string productCode = settings.productCode;
// 3. 两步初始化(顺序不可颠倒)
QKGame.onSetHost(host);
QKGame.onInit(productCode);
// 4. 登录
QKGame.onLogin();
}
注意: WebGL 下调用无参 QKGame.onInit() 不会初始化 SDK,只会打 Warning。必须先 onSetHost 再 onInit(productCode)
4.3 支付
WebGL 使用 onPayOrder,参数类型为 QKGame.QKPayOrderInfo(不是 Android 的 onPay):
QKGame.onPayOrder(new QKGame.QKPayOrderInfo
{
cpOrderNo = "order_" + DateTime.UtcNow.Ticks,
subject = "60钻石",
desc = "购买描述",
goodsId = "goods_001",
amount = "6", // 金额(字符串)
extrasParams = "透传参数",
userRoleId = "role_001",
userRoleName = "玩家名",
serverId = "s1",
serverName = "一区",
userLevel = "10",
callbackUrl = "", // 可空
buy_quantity = "1"
});
4.4 其他 API
QKGame 方法
说明
onGuestLogin()
游客 / 静默登录(内部与 login 走同一 JS 分支)
onLogout()
登出
onUpdateRole(...)
上报角色(支付前建议调用)
onUserCenter()
小游戏侧暂不支持,JS 层仅打 Log
onRestoreNonConsumptionProducts()
小游戏侧 noop,直接回调 onRestoreSuccess
4.5 Demo 参考
场景:QuickGameDemo.unity
WebGL Build 下按钮:SetHost → Init(productCode) → Login → Pay (onPayOrder)
5.1 Unity WebGL Build
1.QuickSDK → Settings 填写 baseUrl、productCode,选择 Mini Game Channel
2.(可选)点击 Rebuild WebGL Bridge
3.File → Build Settings → WebGL → Build
4. Console 确认日志:
[QuickGame] WebGL bridge rebuilt: channel=wx, jspre=...B, jslib=...B
5.2 转小游戏工程
使用对应平台官方工具链将 Unity WebGL 产物转为小游戏
5.3 与旧方案的区别
新方案(当前工程):
QGSDK 已通过 jspre 内联进 Unity WebGL 产物
不需要在宿主 game.js 手动 import QuickGame_Bridge.js
不需要在小游戏工程根目录单独放一份 QGSDK.js
旧方案(母仓早期 Demo):
宿主侧引入 QuickGame_Bridge.js + 商务 QGSDK.js
Unity jslib 仅转发 window._CallMiniGameMethod
JS 侧通过 GameGlobal.unityInstance.SendMessage(gameObjectName, method, jsonString) 回调 Unity
QuickListener.cs 中的 字符串重载 负责 JSON 解析
初始化
成功: onInitSuccess
{ "msg": "init ok" }
失败: onInitFailed
{ "msg": "错误描述" }
登录
成功: onLoginSuccess
{
"userId": "123456",
"userToken": "xxx",
"userName": "player1",
"msg": "login ok",
"timeleft": "-1",
"isNewUser": "0"
}
{ "msg": "错误描述" }
成功 / 失败 / 取消(字段与 Android 一致):
{
"code": "0",
"message": "success",
"orderNo": "SDK订单号",
"cpOrderNo": "游戏订单号",
"extras": "透传参数"
}
登出
成功: onLogoutSuccess
{ "msg": "logout" }
以 onLogin() 为例:
QKGame.onLogin()
→ QuickGameWebGLBridge.Login()
→ CallMiniGameMethod("login", "")
→ jslib: QuickGameJS.dispatch("login", "")
→ QGManager.login(callback)
→ send("onLoginSuccess", { userId, userToken, ... })
→ Unity SendMessage → QuickListener.onLoginSuccess(string msg)
→ CP 实现的 onLoginSuccess(UserInfo)
jspre / jslib 分层原因:
jspre(--pre-js):可写任意顶层 JS,内联 QGSDK + 适配层
jslib:Unity 要求顶层只能是 mergeInto(LibraryManager.library, {...}),因此仅放 DllImport 入口
当 CP 需要接入 QGSDK.js 新增能力时,按以下四层扩展(以 QGManager.getChannelId() 为例)
8.1 判断接口类型
类型
处理方式
同步返回值
dispatch 内直接 return 或通过 SendMessage 一次性回传
异步回调
dispatch 内调 QGManager,在 callback 里 send(method, json)
纯 C# 查询
Bridge 增加方法 → jslib 增加导出(复杂,优先走 dispatch)
小游戏侧推荐统一走 CallMiniGameMethod(method, param) → QuickGameJS.dispatch,与现有 login / pay 一致
8.2 示例:同步查询 getChannelId()
Step 1:QuickGameWebGLChannelBuilder.cs — 在 AdapterSuffixTemplate 的 dispatch 中增加分支
if (method === 'getChannelId') {
var cid = '';
try {
if (QGManager && typeof QGManager.getChannelId === 'function')
cid = String(QGManager.getChannelId() || '');
} catch (e) { console.error('[QuickGame] getChannelId', e); }
send('onChannelIdResult', { channelId: cid, msg: 'ok' });
return;
}
Step 2:QuickGameWebGLBridge.cs
public static void GetChannelId()
{
CallMiniGameMethod("getChannelId", string.Empty);
}
Step 3:QKGame.cs
public static void onGetChannelId()
{
#if UNITY_WEBGL && !UNITY_EDITOR
QuickGameWebGLBridge.GetChannelId();
#elif UNITY_EDITOR
Debug.Log("[QKGame] onGetChannelId (Editor)");
#endif
}
Step 4:QuickListener.cs — 增加回调(异步通知模式)
public virtual void onChannelIdResult(string channelId) { }
public void onChannelIdResult(string msg)
{
var data = JObject.Parse(msg);
onChannelIdResult(data["channelId"]?.Value() ?? "");
}
Step 5:CP 触发
QKGame.onGetChannelId(); // 在 Listener.onChannelIdResult 中接收结果
8.3 扩展检查清单
文件
动作
QuickGameWebGLChannelBuilder.cs
dispatch 增加 method 分支
QuickGameWebGLBridge.cs
增加 Bridge 方法
QKGame.cs
增加对外 API
QuickListener.cs
增加回调(若有异步结果)
—
Rebuild WebGL Bridge → WebGL Build 验证
无需修改: QuickGameWebGL.jslib(通用转发 dispatch,Rebuild 时自动覆盖)
9.1 配置与构建
问题
原因
处理
Build 失败:baseUrl / productCode 为空
QKSettings 未填
QuickSDK → Settings 补全
Build 失败:miniGameChannel 无效
渠道目录缺少 QGSDK.js
检查 Channels/
jspre 未生成
未 Rebuild 且 .gitignore 忽略
Settings 点 Rebuild 或 WebGL Build
切换 ali 后仍是 wx SDK
未 Rebuild
改 channel 后 Rebuild + 重新 WebGL Build
9.2 运行时
问题
原因
处理
QuickGameJS not found
jspre 未注入
确认 WebGL Build 前 Rebuild 成功
QuickGameJS.dispatch missing
bootstrap 未完成或 QGSDK 语法错误
查 Console [QuickGame] bootstrap done
listener 未设置
未调 setListener
Awake 中 QKGame.setListener(this)
Unity 未就绪
init 过早,Unity 实例未创建
延迟到首帧 / Loading 完成后再 init
init 报 productCode is empty
未调 onInit 或传空
检查 QKSettings 与 CP 传参
init 报请初始化 host
未调 onSetHost
先 onSetHost 再 onInit
支付 JSON 解析失败
QKPayOrderInfo 字段缺失
必填字段勿传 null,用 ""
Editor 下无法测 SDK
#if UNITY_WEBGL && !UNITY_EDITOR
必须 WebGL Build + 小游戏开发者工具
9.3 与其他平台共存
QKGame.cs / QuickListener.cs 为全平台公共文件,WebGL 改动在 #elif UNITY_WEBGL 分支内
Android / iOS / Windows 不受 WebGL 渠道构建影响
PackageSettings.miniGameChannel 仅 WebGL Build 使用,Android 忽略此字段
9.4 微信小游戏专项
确保 MP 后台配置 request 合法域名(与 baseUrl 一致)
Console 搜索 [QuickGame] 排查 dispatch / SendMessage 日志
iOS 端微信小游戏支付走米大师等特殊逻辑,以商务 QGSDK 文档为准
9.5 SDK 升级流程
商务提供新版 QGSDK.js → 替换 Channels/
Rebuild WebGL Bridge
WebGL Build → 转小游戏 → 开发者工具验证 Init / Login / Pay 全链路
步骤
操作
预期
配置
Settings 选 wx,填 baseUrl / productCode
保存成功
Rebuild
Rebuild WebGL Bridge
Console 输出 channel=wx、jspre/jslib 大小
Init
onSetHost → onInit
onInitSuccess
Login
onLogin
onLoginSuccess,含 userId / userToken
Pay
onPayOrder
onPaySuccess 或 onPayFailed,含 orderNo / cpOrderNo
切渠道
改 miniGameChannel=ali,Rebuild,重打
包内 SDK 行为随渠道变化
Logout
onLogout
onLogoutSuccess
相关文件速查
类型
路径
C# API
Assets/QuickGameSDK/Scripts/QKGame.cs
C# Bridge
Assets/QuickGameSDK/Scripts/QuickGameWebGLBridge.cs
回调基类
Assets/QuickGameSDK/Scripts/QuickListener.cs
渠道构建
Assets/QuickGameSDK/Editor/QuickGameWebGLChannelBuilder.cs
jslib
Assets/Plugins/WebGL/QuickGameWebGL.jslib
jspre
Assets/Plugins/WebGL/QuickGameWebGLBootstrap.jspre
微信 QGSDK
Assets/QuickGameSDK/Channels/wx/QGSDK.js
支付宝 QGSDK
Assets/QuickGameSDK/Channels/ali/QGSDK.js
配置
Assets/Resources/QKSettings.asset
Settings 窗口
Assets/QuickGameSDK/Windows/Editor/PackageSettingsWindow.cs
Demo
Assets/QuickGameSDK/Demo/QuickGameDemoController.cs
1. QuickSDK → Settings
├── baseUrl = https://qkgamesdk.quickapi.net
├── productCode = 你的32位产品码
└── miniGameChannel = wx 或 ali
2. Rebuild WebGL Bridge(可选,Build 前也会自动执行)
3. Build Settings → WebGL → Build
4. 官方工具转小游戏 → 开发者工具导入 → 真机验证
1. 推荐方式(与 iOS 统一)
使用 QuickGameDemo.unity + QKGame
QKGame.setListener(this); QKGame.onInit(); QKGame.onUpdateRole(...); // 支付前必须先上报角色 QKGame.onPay(...);
项
路径
PC SDK 脚本
Assets/QuickGameSDK/Windows/
配置
Assets/Resources/QKSettings.asset
Webview程序
Assets/StreamingAssets/Quicksdk/PCSDK_release/
Build Settings → PC, Mac & Linux Standalone → Target Windows
在 Windows 环境构建与运行
baseUrl、productCode、channelCode
菜单 QuickSDK → Settings(Editor)可编辑 QKSettings.asset
Windows Build 运行 QuickGameDemo
Init → Login → UpdateRole → Pay 回调正常
李先生:13880511661
QQ:48157910
赵先生:15390049857
QQ:1077535763
孙女士:13551010407
QQ:1799614139
QQ群:698731538