Unity
- 概述
- 基本设置
- 类型安全的事件发送
- 标准事件目录
- 问题排查
AdStage Unity SDK v3.0 引入了 类型安全的事件系统,可在编译期防止错误,并与 Android/iOS 原生 SDK 完全兼容。
- ✅ Android (API 21+)
- ✅ iOS (12.0+)
通过 Package Manager 安装:
Window → Package Manager → + → Add package from git URL
https://github.com/nbase-io/NBase-SDK-Unity.git?path=/AdStageSDK-Package
或直接编辑 manifest.json:
{
"dependencies": {
"com.nbase.adstage": "https://github.com/nbase-io/NBase-SDK-Unity.git?path=/AdStageSDK-Package#3.0.0"
}
}
using AdStageSDK;
using UnityEngine;
public class GameManager : MonoBehaviour
{
void Start()
{
// AdStage 初始化
AdStage.Initialize(
apiKey: "your-api-key-here"
);
Debug.Log("✅ AdStage SDK 초기화 완료");
}
}
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
<!-- 必需权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
</manifest>
<!-- 网络使用权限 -->
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<false/>
</dict>
using AdStageSDK;
using AdStageSDK.Models;
public class GameController : MonoBehaviour
{
void Start()
{
// 无参数的事件
AdStage.TrackEvent(AdStageEvent.Custom());
// 登录事件
AdStage.TrackEvent(
AdStageEvent.Login(method: "email")
);
}
}
// ✅ GOOD: 同时提供 value 与 currency
AdStage.TrackEvent(
AdStageEvent.Purchase(
value: 29.99,
currency: "USD",
transactionId: "TXN_123456"
)
);
// ❌ BAD: 仅提供 value 时会发生运行时错误!
AdStage.TrackEvent(
AdStageEvent.Purchase(
value: 29.99 // ❌ 错误:currency 为必填!
)
);
// ✅ GOOD: 不带 currency,仅提供 transactionId
AdStage.TrackEvent(
AdStageEvent.Purchase(
transactionId: "TXN_123456"
)
);
AdStage.TrackEvent(
AdStageEvent.Purchase(
value: 9900.0,
currency: "KRW",
transactionId: "ORDER_001"
),
onSuccess: (success) => {
Debug.Log("✅ 이벤트 전송 성공");
},
onError: (error) => {
Debug.LogError($"❌ 이벤트 전송 실패: {error}");
}
);
除标准事件之外,要发送应用特有的事件时请使用 AdStageEvent.Custom。
若在参数中包含 event_name 键,该值会自动提升为实际的事件名称并保存到仪表板。
// 例:发送名为 'promotion_click' 的自定义事件
var promotionParams = new Dictionary<string, object>
{
{ "event_name", "promotion_click" },
{ "promotion_id", "summer_sale_2025" },
{ "screen", "home_banner" }
};
AdStage.TrackEvent(AdStageEvent.Custom(promotionParams));
// 在仪表板中会以 "promotion_click" 事件收集
// 不带 event_name 的普通自定义事件
var customParams = new Dictionary<string, object>
{
{ "action", "button_click" },
{ "button_id", "promo_banner" },
{ "screen", "home" },
{ "timestamp", DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
};
AdStage.TrackEvent(AdStageEvent.Custom(customParams));
// 在仪表板中会以 "custom" 事件收集
// Click、View 也支持自由参数
var clickParams = new Dictionary<string, object>
{
{ "campaign_id", "SUMMER2025" },
{ "ad_group", "electronics" }
};
AdStage.TrackEvent(AdStageEvent.Click(clickParams));
AdStage Unity SDK 提供 46 个标准事件。
// 1. 广告点击
AdStage.TrackEvent(AdStageEvent.Click(
new Dictionary<string, object> { { "campaign_id", "CAMP_123" } }
));
// 2. 广告展示
AdStage.TrackEvent(AdStageEvent.View(
new Dictionary<string, object> { { "impression_id", "IMP_456" } }
));
// 3. 应用安装
AdStage.TrackEvent(AdStageEvent.Install());
// 4. 自定义事件(用 event_name 指定事件名称)
AdStage.TrackEvent(AdStageEvent.Custom(
new Dictionary<string, object> {
{ "event_name", "promotion_click" },
{ "promotion_id", "summer_sale_2025" }
}
));
// 1. 注册完成
AdStage.TrackEvent(AdStageEvent.SignUp(method: "google"));
// 2. 注册开始
AdStage.TrackEvent(AdStageEvent.SignUpStart());
// 3. 登录
AdStage.TrackEvent(AdStageEvent.Login(method: "email"));
// 4. 退出登录
AdStage.TrackEvent(AdStageEvent.Logout());
// 5. 应用首次启动
AdStage.TrackEvent(AdStageEvent.FirstOpen());
// 1. 首页画面
AdStage.TrackEvent(AdStageEvent.HomeView());
// 2. 商品列表
AdStage.TrackEvent(AdStageEvent.ProductListView(itemCategory: "electronics"));
// 3. 搜索结果
AdStage.TrackEvent(AdStageEvent.SearchResultView(searchTerm: "wireless headphones"));
// 4. 商品详情
AdStage.TrackEvent(AdStageEvent.ProductDetailsView(
itemId: "PROD_123",
itemName: "Wireless Earbuds"
));
// 5. 页面浏览(Web)
AdStage.TrackEvent(AdStageEvent.PageView(
pageUrl: "https://example.com/products",
pageTitle: "Products"
));
// 6. 画面浏览(Unity Scene)
AdStage.TrackEvent(AdStageEvent.ScreenView(
screenName: "MainMenu",
screenClass: "MainMenuScene"
));
// 1. 添加到购物车
var cartItem = new EcommerceItem(
itemId : "PROD_123",
itemName : "Wireless Earbuds",
price : 99000.0,
quantity : 1
);
AdStage.TrackEvent(AdStageEvent.AddToCart(
value: 99000.0,
currency: "KRW",
items: new List<EcommerceItem> { cartItem }
));
// 2. 从购物车移除
AdStage.TrackEvent(AdStageEvent.RemoveFromCart(
value: 50000.0,
currency: "KRW"
));
// 3. 添加到愿望清单
AdStage.TrackEvent(AdStageEvent.AddToWishlist(
itemId: "PROD_456",
itemName: "Smart Watch"
));
// 4. 输入支付信息
AdStage.TrackEvent(AdStageEvent.AddPaymentInfo(paymentType: "credit_card"));
// 5. 开始结算
AdStage.TrackEvent(AdStageEvent.BeginCheckout(
value: 150000.0,
currency: "KRW"
));
// 6. 购买完成 ⭐⭐⭐
var purchaseItems = new List<EcommerceItem>
{
new EcommerceItem(
itemId: "PROD_123",
itemName: "Wireless Earbuds",
price: 126000.0,
quantity: 1
)
};
AdStage.TrackEvent(AdStageEvent.Purchase(
value: 129000.0,
currency: "KRW",
transactionId: "ORDER_20250105_001",
tax: 12900.0,
shipping: 3000.0,
coupon: "SUMMER2025",
items: purchaseItems
));
// 7. 退款
AdStage.TrackEvent(AdStageEvent.Refund(
transactionId: "ORDER_20250105_001",
value: 129000.0,
currency: "KRW"
));
// 1. 新手引导开始
AdStage.TrackEvent(AdStageEvent.TutorialBegin(
new Dictionary<string, object> { { "tutorial_id", "intro" } }
));
// 2. 新手引导完成
AdStage.TrackEvent(AdStageEvent.TutorialComplete(
new Dictionary<string, object> { { "duration_seconds", 120 } }
));
// 3. 升级
AdStage.TrackEvent(AdStageEvent.LevelUp(
level: 25,
character: "warrior"
));
// 4. 达成成就
AdStage.TrackEvent(AdStageEvent.Achievement(achievementId: "first_win"));
// 1. 搜索
AdStage.TrackEvent(AdStageEvent.Search(searchTerm: "gaming laptop"));
// 2. 分享
AdStage.TrackEvent(AdStageEvent.Share(
contentType: "product",
method: "kakao"
));
// 3. 广告点击
AdStage.TrackEvent(AdStageEvent.AdClick(adPlatform: "unity", adSource:"unity_source", adFormat:"unity_format", adUnitName: "AD_12345"));
// 1. 游戏游玩
AdStage.TrackEvent(AdStageEvent.GamePlay(
level: 10,
levelName: "Dragon's Lair",
character: "mage",
contentType: "dungeon"
));
// 2. 获得奖励
AdStage.TrackEvent(AdStageEvent.AcquireBonus(
contentType: "reward",
itemId: "ITEM_123",
itemName: "Gold Chest",
quantity: 1
));
// 3. 选择游戏服务器
AdStage.TrackEvent(AdStageEvent.SelectGameServer(
contentId: "SERVER_01",
contentType: "pvp",
itemName: "Asia Server"
));
// 4. 补丁完成
AdStage.TrackEvent(AdStageEvent.CompletePatch(
contentId: "PATCH_2.1.0",
contentType: "update"
));
// 1. 开始免费试用
AdStage.TrackEvent(AdStageEvent.StartTrial(
value: 9900.0,
currency: "KRW",
trialDays: 14
));
// 2. 开始订阅
AdStage.TrackEvent(AdStageEvent.Subscribe(
value: 9900.0,
currency: "KRW",
subscriptionId: "premium_monthly"
));
// 3. 取消订阅
AdStage.TrackEvent(AdStageEvent.Unsubscribe(subscriptionId: "premium_monthly"));
这是正常行为! 在 Editor 中只会输出日志,不会实际发送。
确认方法:
#if UNITY_EDITOR
Debug.Log("📊 [Editor Mode] 이벤트는 실제 기기에서만 전송됩니다");
#endif
检查清单:
- 确认 Logcat:
adb logcat | grep -i adstage
- 互联网权限:确认 AndroidManifest.xml 中是否有 INTERNET 权限
- 停用 Minify(测试用):确认 ProGuard/R8 设置
// 以调试版本进行测试
BuildOptions options = BuildOptions.Development | BuildOptions.AllowDebugging;
检查清单:
- 确认 Xcode Console:查看错误消息
- Framework 链接:确认是否已嵌入 AdapterAdStage.framework
- Bitcode 设置:在 Build Settings 中停用 Bitcode
解决方法:
// 创建 link.xml 文件
<linker>
<assembly fullname="AdStageSDK" preserve="all"/>
<assembly fullname="AdStageSDK.Models" preserve="all"/>
</linker>
问题:
System.ArgumentException: Invalid JSON
解决方法:
// 确认 Dictionary 的值是否为 null
var parameters = new Dictionary<string, object>
{
{ "key1", value ?? "default" },
{ "key2", string.IsNullOrEmpty(value2) ? "unknown" : value2 }
};
// ❌ 2 位代码
AdStageEvent.Purchase(value: 100.0, currency: "KR")
// ValidationException: "Currency must be 3-letter ISO 4217 code"
// ✅ 3 位 ISO 4217 代码
AdStageEvent.Purchase(value: 100.0, currency: "KRW") // 韩元
AdStageEvent.Purchase(value: 100.0, currency: "USD") // 美元
AdStageEvent.Purchase(value: 100.0, currency: "JPY") // 日元
Q:可以在 Unity Editor 中测试吗?
A:在 Editor 中只会输出日志。实际测试必须在真机上进行。
Q:在 Android 与 iOS 上的行为相同吗?
A:是的,46 个事件的行为完全相同。
Q:可以与 Unity IAP 一起使用吗?
A:可以,在 ProcessPurchase 回调中调用 AdStage 事件即可。
Q:离线状态下也能运行吗?
A:可以,原生 SDK 会自动将事件存入队列,并在网络恢复时发送。
Q:自定义事件该如何发送?
A:使用 AdStageEvent.Custom(new Dictionary<string, object> {...})
联系方式:
© 2025 NBase. All rights reserved.