cocos creator上架字节跳动(抖音)小游戏注意事项(匿名登录、录屏、分享等踩坑记录)

常见拒绝原因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.录屏

大坑,只要第一次上抖音基本都会因为相关问题被驳回,无外乎几种情况: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.分享

遇到个坑,原本的代码我是写在录屏的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"如果漏掉这个参数分享对话框里是不会有视频的。
另外可以页面上再放一个分享按钮,逻辑也是这个,这样如果是多场景游戏,在其他场景中录屏达到上限结束了(或者是在分享前不小心把这个对话框关掉了),玩家也能使用分享按钮对录好的视频进行分享。

以上,字节的审核非常快从第一次提审到全部修复总共也就半天时间,这点还是比微信给力的。以上代码仅供逻辑参考,可能有bug或者冗余代码(比如计数器里头),请见谅。

猜你喜欢

转载自blog.csdn.net/hangsky1990/article/details/128789110