Appearance
接入文档-抖音小游戏
宿主支持现状
native方案只支持Android,但是性能更好。WebGL可以支持iOS和Android双端,性能会低一些。建议可以Android上native方案,iOS上WebGL方案。
方案类型 | 支持平台 | 支持宿主 |
---|---|---|
原生方案 | Android | 抖音、抖音极速版、头条、头条极速版、火山视频、番茄小说 |
Wasm方案 | Android / IOS | 仅支持抖音,抖音极速版 (Android/iOS) |
注:native 方案,目前仅支持 Unity 2021.3.14f1 版本 SC使用方案及引擎选择建议
对接流程
INFO
SDK接入完毕后请发送二维码到对接群,测试验收通过后再提审发布!!!
环境搭建
根据接入文档StarkSDK_Unity文档 安装抖音小游戏插件。Uid获取方法
SDK接入
INFO
Unity
工程中添加DY_MINI_GAME
宏定义,将DN_MINI_PLUGIN_UNITY.unitypackage
导入工程。
工程配置
.SPgxUuSX.png)
接入准备
域名加白
使用下列域名
https://c.vigame.cn
https://p.vigame.cn
https://x.vimedia.cn
https://u.vigame.cn
https://r.vigame.cn
https://x.vigame.cn
1
2
3
4
5
6
2
3
4
5
6
配置抖音登录参数(抖音资质审核通过后才可以获取正式的openid)以及支付回调参数
联系运营同学配置
动能参数
联系运营同学提供
H5动能内部appid
H5动能内部appKey
广告位配置
联系运营同学配置
游戏的广告位埋点
SDK初始化(必接)
DANGER
初始化接口要在游戏执行的第一个脚本就调用初始化,以免无法监听到抖音Stark SDK
本身的初始化回调!!!注意:isRelax true 切换抖音账号不清空本地缓存,false 切换抖音账号清空本地缓存。直接入广告的游戏建议设置为 true,skd 默认为 false。
csharp
/// <summary>
/// 抖音小游戏sdk初始化
/// </summary>
/// <param name="appid">动能appid</param>
/// <param name="appKey">动能appkey</param>
/// <param name="callBack">初始化回调bool:是否初始化成功;string:openId;string:userCode</param>
/// <param name="payRate">根据小游戏平台配置支付时设置的支付比例(1:1、1:10、1:100)确认传1、10、100</param>
/// <param name="isRelax">是否为超休游戏,true切换抖音账号不清空本地缓存,false切换抖音账号清空本地缓存</param>
public void DouYinInit(string appid, string appKey, Action<bool, string, string> callBack, MiniPayRate payRate = MiniPayRate.Shi, bool isRelax = false)
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
示例
DANGER
接入时H5动能appid和H5动能appkey需改为正式参数!!!
csharp
Wb.CoreManager.Instance.DouYinInit(您的H5动能appid, 您的H5动能appkey, (ret, openId, userCode) =>
{
if (ret)
{
Debug.Log("DNSDK: 初始化成功 openId: " + openId + ", userCode: " + userCode);
}
else
{
Debug.Log("DNSDK: 初始化失败 openId: " + openId + ", userCode: " + userCode);
}
}, Wb.MiniPayRate.Shi);
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
统计(必接)
根据统计埋点文件使用合适接口上报游戏中产生的事件。
1. 自定义事件(必接)
接口说明
csharp
public void TJCustomEvent(string eventId)
public void TJCustomEvent(string eventId, string label)
public void TJCustomEvent(string eventId, Dictionary<string, string> attributes)
1
2
3
2
3
事件说明
事件名称 | 事件ID | 触发时机 | 附加参数 |
---|---|---|---|
游戏loading页面 | app_loading_show | 游戏引擎初始化后就触发上报 | 无 |
游戏内首页 | app_home_show | 主页展示时 | 无 |
使用示例
csharp
//示例
Wb.TjManager.Instance. TJCustomEvent("app_loading_show");
Wb.TjManager.Instance. TJCustomEvent("app_home_show");
1
2
3
2
3
2. 转化行为上报(必接)
INFO
注意:转化行为上报使用TjSendTrackingEvent
接口!!!
转化行为active
、active_register
事件必接,事件类型为tracking
!!!
SDK会本地缓存埋点记录,再上报会进行拦截。
接口说明
csharp
/// <summary>
/// 转化行为上报
/// </summary>
/// <param name="eventId">事件id</param>
/// <param name="val">额外参数json字符串</param>
public void TjSendTrackingEvent(string eventId, string val = "")
1
2
3
4
5
6
2
3
4
5
6
事件id | 事件定义 | data额外携带数据 | 建议上报时机 |
---|---|---|---|
active(自实现上报必接) | 激活 | 首次进入主页触发 | |
active_register(自实现上报必接) | 注册 | 完成角色创建后触发。如果没有角色创建过程,可跟active事件同时触发。 |
使用示例
csharp
Wb.TjManager.Instance.TjSendTrackingEvent("active");
Wb.TjManager.Instance.TjSendTrackingEvent("active_register");
1
2
2
3.关卡统计上报(必接)
接口说明
csharp
/// <summary>
/// 关卡开始
/// </summary>
/// <param name="level">关卡id</param>
public void StartLevel(string level)
/// <summary>
/// 关卡获胜
/// </summary>
/// <param name="level">关卡id</param>
/// <param name="score">得分</param>
public void FinishLevel(string level, string score)
/// <summary>
/// 关卡失败
/// </summary>
/// <param name="level">关卡id</param>
/// <param name="score">得分</param>
public void FailLevel(string level, string score)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
事件说明
事件id | 事件定义 | data额外携带数据 | 建议上报时机 |
---|---|---|---|
begin | 开始 | levelid:关卡ID | 进入关卡 |
complete | 胜利 | levelid:关卡IDscore:得分 | 关卡胜利 |
fail | 失败 | levelid:关卡IDscore: 得分 | 关卡失败 |
使用示例
csharp
Wb.TjManager.Instance.StartLevel("3-1");
Wb.TjManager.Instance.FinishLevel("3-1", "100");
Wb.TjManager.Instance.FailLevel("3-1", "100");
1
2
3
2
3
4.用户行为统计上报
事件id | 事件定义 | data额外携带数据 | 建议上报时机 |
---|---|---|---|
online | 在线时长 | duration--时长(秒) | 用户切到后台或者杀掉进程时 |
setting_page_click | 设置页点击 | button_click:1用户反馈,2游戏圈,3微信客服 | 设置页内点击按钮时(用户反馈,游戏圈、微信客服) |
self_button_click | 大厅内点击 | button:1-点击购物车,2-点击跳转合成界面,3-点击任务栏,4-点击能量弹窗(各游戏需要自己定义数值) | 大厅界面点击按钮时 |
5.分享/邀请统计上报
事件id | 事件定义 | data额外携带数据 | 建议上报时机 | |
---|---|---|---|---|
分享 | help_share | 分享小程序 | 分享小程序到会话时 | |
help_button_click | 点击求助好友按钮 | bonus_status:1领取成功,2领取失败 help_times_left: 剩余领取次数1,2,3 | 点击求助好友按钮时 | |
邀请 | invite_click | 点击邀请好友入口 | invite_number:邀请好友的数量 0,1,2... | 玩家在主页点击邀请好友入口时上报 (首次弹出时上报0) |
invite_click_plus | 点击加号邀请好友 | / | 玩家在邀请好友界面点击加号时 | |
bonus_click | 点击领取奖励 | bonus_status:1领取成功,2领取失败 | 点击领取奖励时 |
6.设置关卡和活动进度
INFO
sdk
上报stay_time
事件时会携带下面设置的数据
接口说明
csharp
/// <summary>
/// 设置上报level_id参数
/// </summary>
/// <param name="levelId"></param>
public void SetTjLevelId(string levelId)
/// <summary>
/// 设置上报活动进度参数
/// </summary>
/// <param name="json">活动json格式的字符串</param>
public void SetTjActivityProgress(string json)
1
2
3
4
5
6
7
8
9
10
11
2
3
4
5
6
7
8
9
10
11
使用示例
csharp
Wb.TjManager.Instance.SetTjLevelId("10");
Wb.TjManager.Instance.SetTjActivityProgress("{\"activity_id\":10,\"activity_progress\":15,\"activity_bonus_id\":15,\"begain_time\":100,\"valid_time\":120}");
1
2
3
2
3
7.设置用户标识
INFO
调用下面接口设置后,所有事件上报都会携带用户id
csharp
/// <summary>
/// 设置用户id
/// </summary>
/// <param name="userId">用户id</param>
public void SetLoginId(string userId)
1
2
3
4
5
2
3
4
5
使用示例
csharp
Wb.CoreManager.Instance.SetLoginId("123321");
1
广告(必接)
INFO
小游戏中广告按钮和文案在同一水平线时,位置需在文案左侧对齐、要用平台的按钮!!!(一定要按说明的方式处理,否则无法通过审核)
1. 打开广告
INFO
打开广告按钮可以加下屏蔽连点的操作,抖小从加载到展示有2~3s的缓冲时间。可以在用户点击后弹出3~4s的加载提示蒙版,3~4s后自动关闭以及收到sdk回调时关闭。
csharp
/// <summary>
/// 打开广告
/// </summary>
/// <param name="adName">广告位名称</param>
/// <param name="callBackFun">广告关闭回调,状态0成功、1失败、2加载失败</param>
/// <param name="adStartFun">广告播放状态回调,小游戏不要使用</param>
public void OpenAd(string adName, ADCallback callBackFun = null, AdStartCallback adStartFun = null)
1
2
3
4
5
6
7
2
3
4
5
6
7
示例
csharp
Wb.ADManager.Instance.OpenAd("home_mfzs", (ret, info) => {
if (ret == ADResult.Success)
{
Debug.Log("Unity: 广告打开成功 OpenAdTest VideoAd info = " + info);
}
else
{
Debug.Log("Unity: 广告打开失败 OpenAdTest VideoAd info = " + info);
}
});
1
2
3
4
5
6
7
8
9
10
2
3
4
5
6
7
8
9
10
2. 广告是否缓存好
广告为实时加载方式(不缓存广告),调用接口直接返回true
csharp
/// <summary>
/// 广告是否缓存好
/// </summary>
/// <param name="adName">广告位名称</param>
public bool IsAdReady(string adName)
1
2
3
4
5
2
3
4
5
3. 某关卡是否可以打开该广告
csharp
/// <summary>
/// 某关卡是否可以打开该广告
/// </summary>
/// <param name="adName">广告位名称</param>
/// <param name="level">关卡id</param>
public bool IsAdBeOpenInLevel(string adName, int level)
1
2
3
4
5
6
2
3
4
5
6
4. 关闭广告
csharp
/// <summary>
/// 关闭广告
/// </summary>
/// <param name="adName">广告位名称</param>
public void CloseAd(string adName)
1
2
3
4
5
2
3
4
5
分享(android必接)
分享策略名称由策划或运营提供。
1. 主动分享
csharp
/// <summary>
/// 小游戏-主动分享接口
/// </summary>
/// <param name="shareName">分享策略名称</param>
/// <param name="userData">自定义数据使用'&'拼接</param>
public void ShareAppMessage(string shareName, string userData = "")
//调用示例
Wb.SocialManager.Instance.ShareAppMessage("分享策略名称", "t1=1&t2=2");
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
2. 点击右上角分享
点击右上角"..."进行分享
触发,前提是要先主动调用设置分享监听OnShareAppMessage
,触发右上角分享时才会调用下面的设置。
csharp
/// <summary>
/// 小游戏-右上角分享接口
/// </summary>
/// <param name="shareName">分享策略名称</param>
/// <param name="userData">自定义数据使用'&'拼接</param>
public void OnShareAppMessage(string shareName, string userData = "")
//调用示例
Wb.SocialManager.Instance.OnShareAppMessage("分享策略名称", "t1=1&t2=2");
1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
隐私政策
侧边栏(抖音必接)
抖音必接,不接入审核被拒 示例
// 获取宿主信息
// Toutiao 今日头条
// Douyin 抖音
// news_article_lite 今日头条(极速版)
// live_stream 火山小视频
// XiGua 西瓜
// PPX 皮皮虾
// douyin_lite 抖音(极速版)
// live_stream_lite 火山(极速版)
// novel_fm 番茄畅听
// novelapp 番茄小说
var m_HostEnum = StarkSDK.s_ContainerEnv.m_HostEnum;
Debug.Log($"DNSDK: StarkSDK.s_ContainerEnv.m_HostEnum: {m_HostEnum}");
//侧边栏
public void SideBar()
{
if (CanIUse.GetStarkSideBarManager)
{
StarkSDK.API.GetStarkSideBarManager().CheckScene(StarkSideBar.SceneEnum.SideBar, b =>
{
Wb.Extend.Log.Debug("check scene success," + b);
if (b)
{
AndroidUIManager.ShowToast("调用侧边栏成功");
StarkSDK.API.GetStarkSideBarManager().NavigateToScene(StarkSideBar.SceneEnum.SideBar,
() => { Wb.Extend.Log.Debug("navigate to scene success"); },
() => { Wb.Extend.Log.Debug("navigate to scene complete"); }, (errCode, errMsg) =>
{
Wb.Extend.Log.Debug($"navigate to scene error, errCode:{errCode}, errMsg:{errMsg}");
AndroidUIManager.ShowToast($"调用侧边栏失败 errCode:{errCode}, errMsg:{errMsg}");
});
}
else
{
AndroidUIManager.ShowToast("当前宿主不支持侧边栏");
}
}, () => { Wb.Extend.Log.Debug("check scene complete"); }, (errCode, errMsg) =>
{
Wb.Extend.Log.Debug($"check scene error, errCode:{errCode}, errMsg:{errMsg}");
AndroidUIManager.ShowToast($"检测失败 errCode:{errCode}, errMsg:{errMsg}");
});
}
else
{
AndroidUIManager.ShowToast("当前宿主的Container版本过低,不可使用该接口");
}
}
录屏(Android 必接)
android必须
示例
StarkSDK.API.GetStarkGameRecorder().StartRecord(m_IsRecordAudio, m_MaxRecordTime, OnRecordStart, OnRecordError, OnRecordTimeout)
支付
逻辑可参考微信小游戏
1. 支付
抖音小游戏没有支付版本限制,
ver
字段可默认使用Wb.MiniPayVer.Ver1
INFO
收到支付成功回调游戏发奖后,需主动调用TjPayOnAccount
充值到账上报和消单。
csharp
/// <summary>
/// 小游戏支付
/// </summary>
/// <param name="ver">小游戏支付版本,1:虚拟支付1.0版; 2:虚拟支付2.0版</param>
/// <param name="payParam">支付参数</param>
/// <param name="rate">根据小游戏平台配置支付时设置的支付比例(1:1、1:10、1:100)确认传1、10、100</param>
/// <param name="callFun"></param>
public void MiniPay(MiniPayVer ver, PayParam payParam, OrderPayCallbackHandler callFun = null)
字段说明
payId 计费点id
price 金额(单位分)
payDesc 商品描述
payCode 支付code,没有填写计费点payId
giftId 礼包id,没有的话写计费点payId
giftType 礼包类型,没有填写空 非必传
giftNum 礼包数量,一次购买了几份,最小值为1
giftPrice 礼包价值,没有可填写price金额值(单位分)
levelId 有用户等级的传用户等级,没有用户等级的游戏传关卡id
tokenType 代币类型(当礼包类型为代币礼包时,传参。否则传空串)非必传
custom 用户自定义数据 ,最长128个字符(不会上传给平台) 非必传
payPush 礼包推送:1主动点击;0被动推送 非必传
userId 户的账号ID,无账号游戏为空。最长128个字符 非必传
extParams 额外参数,传参后支付事件上报时携带该数据 非必传
示例
csharp
// payId 计费点id
// price 金额(单位分)
// payDesc 商品描述
var payParam = new Wb.PayParam(1, 300, "钻石礼包");
payParam.SetCustom("自定义数据"); //非必传
payParam.SetGiftNum(1); //非必传
payParam.SetTokenType("10"); //非必传
payParam.SetGiftType("diamond"); //非必传
payParam.SetLevelId("lv1"); //非必传
payParam.SetUserId("user_1001"); //非必传
payParam.SetPayPush("1"); //非必传
//额外参数,传参后支付事件上报时携带该数据
var dic = new Dictionary<string, object>
{
{ "offer_wave", 100 },
{ "active_coin", 9999 }
};
payParam.SetExtraParam(dic); //非必传
Debug.Log("PayManager payParam json = " + payParam.ToJson());
var ver = Wb.MiniPayVer.Ver1;
Wb.PayManager.Instance.MiniPay(ver, payParam, (result, payId, userData, orderId) =>
{
switch (result)
{
case Wb.PayStatus.PaySuccess:
Debug.Log("PayManager 支付成功");
text.GetComponent<Text>().text = "支付成功";
Debug.Log("PayManager OrderPay 充值到账上报");
Wb.TjManager.Instance.TjPayOnAccount(orderId);
break;
case Wb.PayStatus.PayFail:
Debug.Log("PayManager 支付失败");
text.GetComponent<Text>().text = "支付失败";
break;
case Wb.PayStatus.PayCancel:
Debug.Log("PayManager 支付取消");
text.GetComponent<Text>().text = "支付取消";
break;
case Wb.PayStatus.PayNetError:
Debug.Log("PayManager 支付完成,遇到网络问题,请重新消耗订单");
text.GetComponent<Text>().text = "遇到网络问题";
break;
default:
throw new ArgumentOutOfRangeException(nameof(result), result, null);
}
Debug.Log("PayManager payId = " + payId);
Debug.Log("PayManager orderId = " + orderId);
Debug.Log("PayManager userData = " + userData);
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
2. 补单
INFO
服务器发奖游戏可跳过设置补单回调,要在sdk初始化成功进入游戏后设置。调用该接口会触发SDK
的补单流程,请根据游戏实际情况确认补单触发的时机。收到回调游戏发奖后,需主动调用TjPayOnAccount
充值到账上报和消单。
csharp
/// <summary>
/// 设置补单回调
/// 调用该接口会触发sdk补单流程
/// 根据实际情况确认调用时机
/// </summary>
/// <param name="callFun">支付回调</param>
public void SetInventoryCallBack(OrderPayCallbackHandler callFun)
1
2
3
4
5
6
7
2
3
4
5
6
7
示例
csharp
Wb.PayManager.Instance.SetInventoryCallBack((payStatus, payId, userData, orderId) =>
{
switch (payStatus)
{
case Wb.PayStatus.PaySuccess:
//支付成功"
Debug.Log("SetInventoryCallBack DNSDK: PayManager SetInventoryCallBack 充值到账上报");
Wb.TjManager.Instance.TjPayOnAccount(orderId);
break;
case Wb.PayStatus.PayFail:
//支付失败
break;
case Wb.PayStatus.PayCancel:
//支付取消
break;
case Wb.PayStatus.PayNetError:
//网络错误
break;
default:
//未知错误
}
});
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
3 代币变化上报(选接)
INFO
服务器发奖游戏可跳过
非服务端发奖游戏建议接入该事件上报,便于充值后奖励到账查询~
玩家游戏过程中虚拟货币发生变化时进行上报。内购上报统计事件为pay_token_change
。
示例
csharp
//以下参数仅供参考,以实际游戏为准
Dictionary<string, string> attributes = new Dictionary<string, string>();
attributes.Add("level_id", "有用户等级传用户等级,没有用户等级传关卡id");
attributes.Add("token_type", "代币类型(1金币,2钻石,3体力),没有填空");
attributes.Add("before_token", "变化前数量");
attributes.Add("change_token", "变化数量");
attributes.Add("after_token", "变化后数量");
attributes.Add("add_reduce", "增减标志(1增加, 2减少)");
attributes.Add("reason", "变化原因,eg: 1购买道具A、2充值、3奖励");
attributes.Add("scene", "场景(eg: 1游戏结束时、2游戏过程中、3商城)");
Wb.TjManager.Instance.TJCustomEvent("pay_token_change", attributes);
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
音效适配
iOS 建议使用StarkSDK内置接口
private AudioSource _audioSource;
private const string AudioPath = "https://lf3-stark-cdn.bdgp.cc/obj/game-res-cn/ucmc/TempTest/background_music.mp3";
private void Start()
{
if (StarkAudioManager.CanUseNativeAudio())
{
Debug.Log("DNSDK: StarkAudioManager 加载音频");
var innerAudioContext =StarkAudioManager.CreateInnerAudioContext(new StarkAudioManager.InnerAudioContextOptions
{
src = AudioPath,
startTime = 0, // 开始播放的位置(单位:s)
autoPlay = true, // 是否自动播放
loop = true, // 是否自动循环
needDownload = true, // 是否需要下载,如果为true,则会完全下载后再触发OnCanplay
});
innerAudioContext.onPlay += () =>
{
Debug.Log("StarkAudioManager onPlay 开始播放");
};
innerAudioContext.onError += (err) =>
{
Debug.Log("StarkAudioManager onError 播放出错 err:" + err);
};
}
else
{
Debug.Log("DNSDK: AudioSource 加载音频");
_audioSource = GetComponent<AudioSource>();
StartCoroutine(LoadAudio());
}
}
private IEnumerator LoadAudio()
{
var www = UnityWebRequestMultimedia.GetAudioClip(AudioPath, AudioType.MPEG); // 使用UnityWebRequest加载MP3音频
yield return www.SendWebRequest();
if (www.isNetworkError || www.isHttpError)
{
Debug.Error($"Load audio failed: {www.error}");
}
else
{
Debug.Error("获取加载的音频剪辑");
var audioClip = DownloadHandlerAudioClip.GetContent(www); // 获取加载的音频剪辑
_audioSource.clip = audioClip;
_audioSource.loop = true;
_audioSource.Play(); // 播放音频
}
}
小游戏自审
须仔细阅读:小游戏自审
[^1]:
[^2]:
[^3]:
[^4]:
[^5]: