常见拒绝原因1:小游戏无录屏功能,不符合平台要求 2:小游戏录屏时间小于3S,分享按钮点击无反应或提示错误文案,不符合平台要求 3:小游戏录屏时间大于300S,分享按钮点击无反应或无法正常分享录屏,不符合平台要求
不久前写了款小游戏,最近上架了字节跳动小游戏平台。因为这款游戏在微信小游戏里被归类为角色扮演类(微信平台不允许个人开发者上架角色类游戏),因此考虑上架字节跳动,只要有软件著作权即可。
游戏是之前在微信平台已经调试通的,所以只需要按照字节的要求做一点修改就可以了,主要变化如下:
1.支持匿名登录
微信小游戏只需要调用wx.login获得code,再用code去服务端调用code2Session就能拿到unionId了,有了unionId就基本完成登录,后续可以继续调用接口获得昵称,或者干脆让用户自己输入昵称完成角色创建,简单粗暴。
字节小游戏则有一堆的要求,比如支持匿名登录(弹出登录框,用户选择拒绝,也要能以游客的身份登录游戏游玩),又比如资料同步(本机有匿名登录的角色资料,此时又切换到非匿名的账号登录,之前的匿名数据需要覆盖到该账号里,这一条就包含了很多需要处理的后台逻辑)
start() {
this.labelProcess.string = "游戏初始化中";
this.login()
}
login() {
let _this = this;
tt.login({
force: true,
success(res) {
// 获取用户信息
tt.getUserInfo({
success(resUser) {
//用户很乖,一路确定,允许登录也允许捞取抖音昵称
console.log(`getUserInfo 调用成功`, resUser.userInfo);
console.log(res.code);
if (res.code) {
_this.init(res.code,res.anonymousCode,false, resUser.userInfo.nickName) //false表示非匿名,true表示匿名登录
}
},
fail(resUser) {
//用户允许登录了,但不给获取昵称的权限,这时候虽然昵称也是匿名用户,但不能算匿名登录了,因为res.code可以拿到账号APP唯一ID,后续可以在登录的时候把抖音昵称更新到游戏里(如果用户给昵称权限)
_this.init(res.code,res.anonymousCode,res,false, '匿名用户')
},
});
},
fail(res) {
//login fail了,表示用户拒绝了登录,启用匿名登录,res.code就是空,此时用res.anonymousCode去后台调用API拿手机识别码,手机识别码这玩意绑定的是手机,可以拿来当匿名角色主键用
_this.init(res.anonymousCode,true, '匿名用户')
},
});
//以下是微信小游戏的登录比较,要么给res.code,要么别玩,简单粗暴
// wx.login({
// success(res) {
// if (res.code) {
// //发起网络请求
// _this.init(res.code)
// } else {
// _this.popupError.active = true;
// _this.labelError.string = "服务器维护中~\n\n请睡醒一觉再试!";
// }
// }
// })
}
Init方法就是跟后端交互了,拿着res.code或者res.anonymousCode去调用jscode2session接口(注意匿名和非匿名传递的是不同参数),拿到openid或者anonymous_openid作为游戏账号主键即可。
上面的代码有人可能要问了,为啥非匿名登录init的时候也要传res.anonymousCode?不是有res.code吗?这就涉及到上面说的资料同步了,在用res.code换到openId以后,如果这个openId在游戏数据库中不存在,我们需要用这个res.anonymousCode再去换一次anonymous_openid,如果anonymous_openid在我们游戏中存在,表示这个用户之前匿名登录玩过,此时按照平台要求需要把这个匿名资料同步给账号(把数据库里anonymous_openid Update成openid即可)为什么是update不是copy?因为匿名资料同步一次后就要清掉,不然频繁切换账号就能无限复制了是不是。
2.录屏(2024年更新:该功能现在貌似不是强制必接了,能不接就不接吧…)
大坑,只要第一次上抖音基本都会因为相关问题被驳回,无外乎几种情况:1.直接从微信小游戏移植到抖音的,飘的不行文档也没看,直接就没有录屏被打回 2.按照官方文档或者网上找的资料,有功能但是不全被驳回的 3.游戏多场景比较复杂官方例子用了报错的
增加录屏方式:
1.首先在游戏主要场景新增一个按钮,增加点击事件
btnRecordingClick() {
if (stateInfo.isRecording == true) { //如果正在录制,把当前录制停止,文本替换成开始录制告诉用户你可以继续录新的了
this.lblIsRecording.string = '开始录制'
this.stopRecordScreen()
}
else { //如果没在录制,则开始录,文本替换告诉用户你现在正在录
this.lblIsRecording.string = '停止录制'
this.startRecordScreen()
}
}
因为我的游戏是多场景的,可能在这个场景点击了录制会跳转到其他场景,所以是否在录制的标志位isRecording是放在一个单例的对象里,保证其他场景也能用到,如果是单场景的游戏直接放页面里用this.就行了
开始录制方法(这个方法我是放在单例对象里的,如果是单场景游戏不需要加callback参数,直接写里头就行了)
public startRecordScreen(callback) {
if (!this.recorder) this.recorder = tt.getGameRecorderManager();
//注册开始录屏的回调,其实注册一次就行这里偷懒了每次录屏都注册了一次
this.recorder.onStart(res => {
callback("开始录屏")
})
//注册录屏结束事件,偷懒*2
this.recorder.onStop(res => {
this.isRecording = false
clearInterval(this.actionRecord);
if (this.recordingSecond < 4) { //这里用3也可以,不想管边界了就写了4
callback("录屏小于3s,无法分享!")
}
else {
console.log(res.videoPath);
this.videoPath = res.videoPath; //如果录屏成功,则获取视频文件的地址
callback("结束录屏")
}
})
//开始录屏
this.recorder.start({
duration: 300
});
console.log('start')
this.isRecording = true
this.recordingSecond = 0;
//开启一个计时器,统计录制了几秒钟,如果大于300则停止录制
this.actionRecord = setInterval(() => {
this.recordingSecond++
if (this.recordingSecond >= 300) {
this.isRecording = false
clearInterval(this.actionRecord);
}
}, 1000);
}
结束录制的方法
public stopRecordScreen(callback) {
//结束录屏
if (this.recorder)
this.recorder.stop();
}
注意点: this.recorder.start()如果不给参数默认是10秒,时间到后APP会自动关掉录像并执行onStop注册的方法,如果是多场景游戏也需要把这个事件写到单例对象里去,以免onStop的时候原场景被销毁了导致异常。
start以后需要启动个计数器统计录了几秒,如果启动不到3秒要给提示如果不给提示审核会直接打回。如果录屏时间到达五分钟上限,APP也会自动关掉录像,需要做好逻辑处理不然也会被打回。
后续更新:如果是类似消消乐、塔防、跑酷那种有开始游戏-结束游戏环节的,可以在游戏开始时自动开启录屏,游戏结束时自动结束录屏,并在结算弹窗里新增分享录屏按钮,审核也可以通过,不需要让玩家自己去控制开关录屏,这样就不需要考虑录屏时长过长过短的问题了
3.分享(2024年更新:该功能现在貌似不是强制必接了,能不接就不接吧…)
遇到个坑,原本的代码我是写在录屏的onStop里,类似于 this.recorder.onStop(res => {tt.shareAppMessage(…)})的,在IOS里测试正常但是审核那边却弹不出分享框被打回了,百思不得姐查遍了资料,最后也不知道在哪看到个文章说审核的手机是vivo,在vivo下是有差异的,于是换了个方式在onStop里弹出个对话框,对话框里放个分享按钮,由这个按钮去做分享,代码如下
onbtnShareClick() {
let _this = this
tt.shareAppMessage({
templateId: "xxxxxx", // 替换成通过审核的分享ID
query: "",
channel: "video",
extra: {
videoPath: stateInfo.videoPath, // 可用录屏得到的视频地址
videoTopics: ['XXXX']
},
success() {
_this.ndShare.active = false
_this.showWarning("分享成功");
console.log("分享成功");
},
fail(e) {
_this.showWarning("取消分享");
console.log("分享失败");
},
});
}
templateId必须要在控制台通过运营能力-分享设置,通过审核后生成的分享ID,当然也有其他的分享方式具体可看官方文档,channel参数必须写 "video"如果漏掉这个参数分享对话框里是不会有视频的。
另外可以页面上再放一个分享按钮,逻辑也是这个,这样如果是多场景游戏,在其他场景中录屏达到上限结束了(或者是在分享前不小心把这个对话框关掉了),玩家也能使用分享按钮对录好的视频进行分享。
4.侧边栏复访(这是2023年底新增的必接要求)
请见另一篇文章:cocos creator接入字节跳动抖音小游戏侧边栏复访功能(接入小游戏未配置侧边栏复访任务入口,或入口配置过深,不符合平台要求)
以上,字节的审核非常快从第一次提审到全部修复总共也就半天时间,这点还是比微信给力的。以上代码仅供逻辑参考,可能有bug或者冗余代码(比如计数器里头),请见谅。