Skip to content

接入文档-抖音小游戏

宿主支持现状

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导入工程。

工程配置

接入准备

域名加白

使用下列域名

https://c.vigame.cn
https://p.vigame.cn
https://x.vimedia.cn
https://u.vigame.cn
https://r.vigame.cn
https://x.vigame.cn

配置抖音登录参数(抖音资质审核通过后才可以获取正式的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)

示例

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. 自定义事件(必接)

接口说明

csharp
public void TJCustomEvent(string eventId)
public void TJCustomEvent(string eventId, string label)
public void TJCustomEvent(string eventId, Dictionary<string, string> attributes)

事件说明

事件名称事件ID触发时机附加参数
游戏loading页面

app_loading_show

游戏引擎初始化后就触发上报
游戏内首页app_home_show主页展示时

使用示例

csharp
//示例
Wb.TjManager.Instance. TJCustomEvent("app_loading_show");
Wb.TjManager.Instance. TJCustomEvent("app_home_show");

2. 转化行为上报(必接)

INFO

注意:转化行为上报使用TjSendTrackingEvent接口!!!

转化行为activeactive_register事件必接,事件类型为tracking!!!

SDK会本地缓存埋点记录,再上报会进行拦截。

接口说明

csharp
/// <summary>
/// 转化行为上报
/// </summary>
/// <param name="eventId">事件id</param>
/// <param name="val">额外参数json字符串</param>
public void TjSendTrackingEvent(string eventId, string val = "")
事件id事件定义data额外携带数据建议上报时机
active(自实现上报必接)激活


首次进入主页触发

active_register(自实现上报必接)

注册


完成角色创建后触发。如果没有角色创建过程,可跟active事件同时触发。

使用示例

csharp
Wb.TjManager.Instance.TjSendTrackingEvent("active");
Wb.TjManager.Instance.TjSendTrackingEvent("active_register");

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)

事件说明

事件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");

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)

使用示例

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}");

7.设置用户标识

INFO

调用下面接口设置后,所有事件上报都会携带用户id

csharp
/// <summary>
/// 设置用户id
/// </summary>
/// <param name="userId">用户id</param>
public void SetLoginId(string userId)

使用示例

csharp
Wb.CoreManager.Instance.SetLoginId("123321");

广告(必接)

抖音平台说明

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)

示例

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);
    }
});

2. 广告是否缓存好

广告为实时加载方式(不缓存广告),调用接口直接返回true

csharp
/// <summary>
/// 广告是否缓存好
/// </summary>
/// <param name="adName">广告位名称</param>
public bool IsAdReady(string adName)

3. 某关卡是否可以打开该广告

csharp
/// <summary>
/// 某关卡是否可以打开该广告
/// </summary>
/// <param name="adName">广告位名称</param>
/// <param name="level">关卡id</param>
public bool IsAdBeOpenInLevel(string adName, int level)

4. 关闭广告

csharp
/// <summary>
/// 关闭广告
/// </summary>
/// <param name="adName">广告位名称</param>
public void CloseAd(string adName)

分享(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");

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");

隐私政策

无需接入

侧边栏(抖音必接)

抖音必接,不接入审核被拒 示例

// 获取宿主信息
// 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);
});

2. 补单

INFO

服务器发奖游戏可跳过设置补单回调,要在sdk初始化成功进入游戏后设置。调用该接口会触发SDK的补单流程,请根据游戏实际情况确认补单触发的时机。收到回调游戏发奖后,需主动调用TjPayOnAccount充值到账上报和消单。

csharp
/// <summary>
/// 设置补单回调
/// 调用该接口会触发sdk补单流程
/// 根据实际情况确认调用时机
/// </summary>
/// <param name="callFun">支付回调</param>
public void SetInventoryCallBack(OrderPayCallbackHandler callFun)

示例

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:
            //未知错误
    }
});

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);

音效适配

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]: